@@ -146,6 +146,8 @@ def __init__(self,
146146 self ._joinstyle = None
147147
148148 self ._offsets = np .zeros ((1 , 2 ))
149+ # save if offsets passed in were none...
150+ self ._offsetsNone = offsets is None
149151 self ._uniform_offsets = None
150152 if offsets is not None :
151153 offsets = np .asanyarray (offsets , float )
@@ -179,9 +181,30 @@ def get_offset_transform(self):
179181 return t
180182
181183 def get_datalim (self , transData ):
184+
185+ # Get the automatic datalim of the collection.
186+ #
187+ # This operation depends on the transforms for the data in the
188+ # collection and whether the collection has offsets.
189+ #
190+ # 1) offsets = None, transform child of transData: use the paths for
191+ # the automatic limits (i.e. for LineCollection in streamline).
192+ # 2) offsets != None: offset_transform is child of transData:
193+ # a) transform is child of transData: use the path + offset for
194+ # limits (i.e for bar).
195+ # b) transform is not a child of transData: just use the offsets
196+ # for the limits (i.e. for scatter)
197+ # 3) otherwise return a null Bbox.
198+
182199 transform = self .get_transform ()
183200 transOffset = self .get_offset_transform ()
201+ if (not self ._offsetsNone and
202+ not transOffset .contains_branch (transData )):
203+ # if there are offsets but in some co-ords other than data,
204+ # then don't use them for autoscaling.
205+ return transforms .Bbox .null ()
184206 offsets = self ._offsets
207+
185208 paths = self .get_paths ()
186209
187210 if not transform .is_affine :
@@ -196,13 +219,30 @@ def get_datalim(self, transData):
196219 # get_path_collection_extents handles nan but not masked arrays
197220
198221 if len (paths ) and len (offsets ):
199- result = mpath .get_path_collection_extents (
200- transform .frozen (), paths , self .get_transforms (),
201- offsets , transOffset .frozen ())
202- result = result .inverse_transformed (transData )
203- else :
204- result = transforms .Bbox .null ()
205- return result
222+ if transform .contains_branch (transData ):
223+ # collections that are just in data units (like quiver)
224+ # can properly have the axes limits set by their shape +
225+ # offset. LineCollections that have no offsets can
226+ # also use this algorithm (like streamplot).
227+ result = mpath .get_path_collection_extents (
228+ transform .frozen (), paths , self .get_transforms (),
229+ offsets , transOffset .frozen ())
230+ return result .inverse_transformed (transData )
231+ if not self ._offsetsNone :
232+ # this is for collections that have their paths (shapes)
233+ # in physical, axes-relative, or figure-relative units
234+ # (i.e. like scatter). We can't uniquely set limits based on
235+ # those shapes, so we just set the limits based on their
236+ # location.
237+ # Finish the transform:
238+ offsets = (transOffset +
239+ transData .inverted ()).transform (offsets )
240+ offsets = np .ma .masked_invalid (offsets )
241+ if not offsets .mask .all ():
242+ points = np .row_stack ((offsets .min (axis = 0 ),
243+ offsets .max (axis = 0 )))
244+ return transforms .Bbox (points )
245+ return transforms .Bbox .null ()
206246
207247 def get_window_extent (self , renderer ):
208248 # TODO: check to ensure that this does not fail for
@@ -1299,7 +1339,6 @@ def __init__(self, segments, # Can be None.
12991339 antialiaseds = (mpl .rcParams ['lines.antialiased' ],)
13001340
13011341 colors = mcolors .to_rgba_array (colors )
1302-
13031342 Collection .__init__ (
13041343 self ,
13051344 edgecolors = colors ,
0 commit comments