@@ -270,16 +270,41 @@ def draw(self, renderer):
270
270
if self .get_path_effects ():
271
271
for pe in self .get_path_effects ():
272
272
pe .draw_path_collection (renderer ,
273
- gc , transform .frozen (), paths , self .get_transforms (),
274
- offsets , transOffset , self .get_facecolor (), self .get_edgecolor (),
275
- self ._linewidths , self ._linestyles , self ._antialiaseds , self ._urls ,
273
+ gc , transform .frozen (), paths ,
274
+ self .get_transforms (), offsets , transOffset ,
275
+ self .get_facecolor (), self .get_edgecolor (),
276
+ self ._linewidths , self ._linestyles ,
277
+ self ._antialiaseds , self ._urls ,
276
278
self ._offset_position )
277
279
else :
278
- renderer .draw_path_collection (
279
- gc , transform .frozen (), paths , self .get_transforms (),
280
- offsets , transOffset , self .get_facecolor (), self .get_edgecolor (),
281
- self ._linewidths , self ._linestyles , self ._antialiaseds , self ._urls ,
282
- self ._offset_position )
280
+ trans = self .get_transforms ()
281
+ facecolors = self .get_facecolor ()
282
+ edgecolors = self .get_edgecolor ()
283
+ if (len (paths ) == 1 and len (trans ) <= 1 and
284
+ len (facecolors ) == 1 and len (edgecolors ) == 1 and
285
+ len (self ._linewidths ) == 1 and
286
+ self ._linestyles == [(None , None )] and
287
+ len (self ._antialiaseds ) == 1 and len (self ._urls ) == 1 and
288
+ self .get_hatch () is None ):
289
+ gc .set_foreground (tuple (edgecolors [0 ]))
290
+ gc .set_linewidth (self ._linewidths [0 ])
291
+ gc .set_linestyle (self ._linestyles [0 ])
292
+ gc .set_antialiased (self ._antialiaseds [0 ])
293
+ gc .set_url (self ._urls [0 ])
294
+ if len (trans ):
295
+ transform = (transforms .Affine2D (trans [0 ]) +
296
+ transform )
297
+ renderer .draw_markers (
298
+ gc , paths [0 ], transform .frozen (),
299
+ mpath .Path (offsets ), transOffset , tuple (facecolors [0 ]))
300
+ else :
301
+ renderer .draw_path_collection (
302
+ gc , transform .frozen (), paths ,
303
+ self .get_transforms (), offsets , transOffset ,
304
+ self .get_facecolor (), self .get_edgecolor (),
305
+ self ._linewidths , self ._linestyles ,
306
+ self ._antialiaseds , self ._urls ,
307
+ self ._offset_position )
283
308
284
309
gc .restore ()
285
310
renderer .close_group (self .__class__ .__name__ )
@@ -686,7 +711,31 @@ def update_from(self, other):
686
711
""" )
687
712
688
713
689
- class PathCollection (Collection ):
714
+ class _CollectionWithSizes (Collection ):
715
+ """
716
+ Base class for collections that have an array of sizes.
717
+ """
718
+ def get_sizes (self ):
719
+ return self ._sizes
720
+
721
+ def set_sizes (self , sizes , dpi = 72.0 ):
722
+ if sizes is None :
723
+ self ._sizes = np .array ([])
724
+ self ._transforms = np .empty ((0 , 3 , 3 ))
725
+ else :
726
+ self ._sizes = np .asarray (sizes )
727
+ self ._transforms = np .zeros ((len (self ._sizes ), 3 , 3 ))
728
+ scale = np .sqrt (self ._sizes ) * dpi / 72.0
729
+ self ._transforms [:, 0 , 0 ] = scale
730
+ self ._transforms [:, 1 , 1 ] = scale
731
+ self ._transforms [:, 2 , 2 ] = 1.0
732
+
733
+ def draw (self , renderer ):
734
+ self .set_sizes (self ._sizes , self .figure .dpi )
735
+ Collection .draw (self , renderer )
736
+
737
+
738
+ class PathCollection (_CollectionWithSizes ):
690
739
"""
691
740
This is the most basic :class:`Collection` subclass.
692
741
"""
@@ -701,28 +750,16 @@ def __init__(self, paths, sizes=None, **kwargs):
701
750
702
751
Collection .__init__ (self , ** kwargs )
703
752
self .set_paths (paths )
704
- self ._sizes = sizes
753
+ self .set_sizes ( sizes )
705
754
706
755
def set_paths (self , paths ):
707
756
self ._paths = paths
708
757
709
758
def get_paths (self ):
710
759
return self ._paths
711
760
712
- def get_sizes (self ):
713
- return self ._sizes
714
-
715
- @allow_rasterization
716
- def draw (self , renderer ):
717
- if self ._sizes is not None :
718
- self ._transforms = [
719
- transforms .Affine2D ().scale (
720
- (np .sqrt (x ) * self .figure .dpi / 72.0 ))
721
- for x in self ._sizes ]
722
- return Collection .draw (self , renderer )
723
761
724
-
725
- class PolyCollection (Collection ):
762
+ class PolyCollection (_CollectionWithSizes ):
726
763
@docstring .dedent_interpd
727
764
def __init__ (self , verts , sizes = None , closed = True , ** kwargs ):
728
765
"""
@@ -744,7 +781,7 @@ def __init__(self, verts, sizes=None, closed=True, **kwargs):
744
781
%(Collection)s
745
782
"""
746
783
Collection .__init__ (self , ** kwargs )
747
- self ._sizes = sizes
784
+ self .set_sizes ( sizes )
748
785
self .set_verts (verts , closed )
749
786
750
787
def set_verts (self , verts , closed = True ):
@@ -773,15 +810,6 @@ def set_verts(self, verts, closed=True):
773
810
774
811
set_paths = set_verts
775
812
776
- @allow_rasterization
777
- def draw (self , renderer ):
778
- if self ._sizes is not None :
779
- self ._transforms = [
780
- transforms .Affine2D ().scale (
781
- (np .sqrt (x ) * self .figure .dpi / 72.0 ))
782
- for x in self ._sizes ]
783
- return Collection .draw (self , renderer )
784
-
785
813
786
814
class BrokenBarHCollection (PolyCollection ):
787
815
"""
@@ -830,7 +858,7 @@ def span_where(x, ymin, ymax, where, **kwargs):
830
858
return collection
831
859
832
860
833
- class RegularPolyCollection (Collection ):
861
+ class RegularPolyCollection (_CollectionWithSizes ):
834
862
"""Draw a collection of regular polygons with *numsides*."""
835
863
_path_generator = mpath .Path .unit_regular_polygon
836
864
@@ -871,29 +899,18 @@ def __init__(self,
871
899
)
872
900
"""
873
901
Collection .__init__ (self , ** kwargs )
874
- self ._sizes = sizes
902
+ self .set_sizes ( sizes )
875
903
self ._numsides = numsides
876
904
self ._paths = [self ._path_generator (numsides )]
877
905
self ._rotation = rotation
878
906
self .set_transform (transforms .IdentityTransform ())
879
907
880
- @allow_rasterization
881
- def draw (self , renderer ):
882
- self ._transforms = [
883
- transforms .Affine2D ().rotate (- self ._rotation ).scale (
884
- (np .sqrt (x ) * self .figure .dpi / 72.0 ) / np .sqrt (np .pi ))
885
- for x in self ._sizes ]
886
- return Collection .draw (self , renderer )
887
-
888
908
def get_numsides (self ):
889
909
return self ._numsides
890
910
891
911
def get_rotation (self ):
892
912
return self ._rotation
893
913
894
- def get_sizes (self ):
895
- return self ._sizes
896
-
897
914
898
915
class StarPolygonCollection (RegularPolyCollection ):
899
916
"""
@@ -1339,7 +1356,7 @@ def get_color(self):
1339
1356
return self .get_colors ()[0 ]
1340
1357
1341
1358
1342
- class CircleCollection (Collection ):
1359
+ class CircleCollection (_CollectionWithSizes ):
1343
1360
"""
1344
1361
A collection of circles, drawn using splines.
1345
1362
"""
@@ -1352,24 +1369,10 @@ def __init__(self, sizes, **kwargs):
1352
1369
%(Collection)s
1353
1370
"""
1354
1371
Collection .__init__ (self , ** kwargs )
1355
- self ._sizes = sizes
1372
+ self .set_sizes ( sizes )
1356
1373
self .set_transform (transforms .IdentityTransform ())
1357
1374
self ._paths = [mpath .Path .unit_circle ()]
1358
1375
1359
- def get_sizes (self ):
1360
- "return sizes of circles"
1361
- return self ._sizes
1362
-
1363
- @allow_rasterization
1364
- def draw (self , renderer ):
1365
- # sizes is the area of the circle circumscribing the polygon
1366
- # in points^2
1367
- self ._transforms = [
1368
- transforms .Affine2D ().scale (
1369
- (np .sqrt (x ) * self .figure .dpi / 72.0 ) / np .sqrt (np .pi ))
1370
- for x in self ._sizes ]
1371
- return Collection .draw (self , renderer )
1372
-
1373
1376
1374
1377
class EllipseCollection (Collection ):
1375
1378
"""
@@ -1416,7 +1419,6 @@ def _set_transforms(self):
1416
1419
"""
1417
1420
Calculate transforms immediately before drawing.
1418
1421
"""
1419
- self ._transforms = []
1420
1422
ax = self .axes
1421
1423
fig = self .figure
1422
1424
@@ -1439,10 +1441,16 @@ def _set_transforms(self):
1439
1441
else :
1440
1442
raise ValueError ('unrecognized units: %s' % self ._units )
1441
1443
1442
- _affine = transforms .Affine2D
1443
- for x , y , a in zip (self ._widths , self ._heights , self ._angles ):
1444
- trans = _affine ().scale (x * sc , y * sc ).rotate (a )
1445
- self ._transforms .append (trans )
1444
+ self ._transforms = np .zeros ((len (self ._widths ), 3 , 3 ))
1445
+ widths = self ._widths * sc
1446
+ heights = self ._heights * sc
1447
+ sin_angle = np .cos (np .deg2rad (self ._angles ))
1448
+ cos_angle = np .cos (np .deg2rad (self ._angles ))
1449
+ self ._transforms [:, 0 , 0 ] = widths * cos_angle
1450
+ self ._transforms [:, 0 , 1 ] = heights * - sin_angle
1451
+ self ._transforms [:, 1 , 0 ] = widths * sin_angle
1452
+ self ._transforms [:, 1 , 1 ] = heights * cos_angle
1453
+ self ._transforms [:, 2 , 2 ] = 1.0
1446
1454
1447
1455
if self ._units == 'xy' :
1448
1456
m = ax .transData .get_affine ().get_matrix ().copy ()
0 commit comments