@@ -270,16 +270,41 @@ def draw(self, renderer):
270270 if self .get_path_effects ():
271271 for pe in self .get_path_effects ():
272272 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 ,
276278 self ._offset_position )
277279 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 )
283308
284309 gc .restore ()
285310 renderer .close_group (self .__class__ .__name__ )
@@ -686,7 +711,31 @@ def update_from(self, other):
686711""" )
687712
688713
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 ):
690739 """
691740 This is the most basic :class:`Collection` subclass.
692741 """
@@ -701,28 +750,16 @@ def __init__(self, paths, sizes=None, **kwargs):
701750
702751 Collection .__init__ (self , ** kwargs )
703752 self .set_paths (paths )
704- self ._sizes = sizes
753+ self .set_sizes ( sizes )
705754
706755 def set_paths (self , paths ):
707756 self ._paths = paths
708757
709758 def get_paths (self ):
710759 return self ._paths
711760
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 )
723761
724-
725- class PolyCollection (Collection ):
762+ class PolyCollection (_CollectionWithSizes ):
726763 @docstring .dedent_interpd
727764 def __init__ (self , verts , sizes = None , closed = True , ** kwargs ):
728765 """
@@ -744,7 +781,7 @@ def __init__(self, verts, sizes=None, closed=True, **kwargs):
744781 %(Collection)s
745782 """
746783 Collection .__init__ (self , ** kwargs )
747- self ._sizes = sizes
784+ self .set_sizes ( sizes )
748785 self .set_verts (verts , closed )
749786
750787 def set_verts (self , verts , closed = True ):
@@ -773,15 +810,6 @@ def set_verts(self, verts, closed=True):
773810
774811 set_paths = set_verts
775812
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-
785813
786814class BrokenBarHCollection (PolyCollection ):
787815 """
@@ -830,7 +858,7 @@ def span_where(x, ymin, ymax, where, **kwargs):
830858 return collection
831859
832860
833- class RegularPolyCollection (Collection ):
861+ class RegularPolyCollection (_CollectionWithSizes ):
834862 """Draw a collection of regular polygons with *numsides*."""
835863 _path_generator = mpath .Path .unit_regular_polygon
836864
@@ -871,29 +899,18 @@ def __init__(self,
871899 )
872900 """
873901 Collection .__init__ (self , ** kwargs )
874- self ._sizes = sizes
902+ self .set_sizes ( sizes )
875903 self ._numsides = numsides
876904 self ._paths = [self ._path_generator (numsides )]
877905 self ._rotation = rotation
878906 self .set_transform (transforms .IdentityTransform ())
879907
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-
888908 def get_numsides (self ):
889909 return self ._numsides
890910
891911 def get_rotation (self ):
892912 return self ._rotation
893913
894- def get_sizes (self ):
895- return self ._sizes
896-
897914
898915class StarPolygonCollection (RegularPolyCollection ):
899916 """
@@ -1339,7 +1356,7 @@ def get_color(self):
13391356 return self .get_colors ()[0 ]
13401357
13411358
1342- class CircleCollection (Collection ):
1359+ class CircleCollection (_CollectionWithSizes ):
13431360 """
13441361 A collection of circles, drawn using splines.
13451362 """
@@ -1352,24 +1369,10 @@ def __init__(self, sizes, **kwargs):
13521369 %(Collection)s
13531370 """
13541371 Collection .__init__ (self , ** kwargs )
1355- self ._sizes = sizes
1372+ self .set_sizes ( sizes )
13561373 self .set_transform (transforms .IdentityTransform ())
13571374 self ._paths = [mpath .Path .unit_circle ()]
13581375
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-
13731376
13741377class EllipseCollection (Collection ):
13751378 """
@@ -1416,7 +1419,6 @@ def _set_transforms(self):
14161419 """
14171420 Calculate transforms immediately before drawing.
14181421 """
1419- self ._transforms = []
14201422 ax = self .axes
14211423 fig = self .figure
14221424
@@ -1439,10 +1441,16 @@ def _set_transforms(self):
14391441 else :
14401442 raise ValueError ('unrecognized units: %s' % self ._units )
14411443
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
14461454
14471455 if self ._units == 'xy' :
14481456 m = ax .transData .get_affine ().get_matrix ().copy ()
0 commit comments