Fix bugs in legend positioning with loc='best' #1640

Merged
merged 10 commits into from Feb 19, 2013
View
@@ -73,7 +73,7 @@ example, here is a test from :mod:`matplotlib.tests.test_basic`::
Nose determines which functions are tests by searching for functions
beginning with "test" in their name.
-If the test as side effects that need to be cleaned up, such as
+If the test has side effects that need to be cleaned up, such as
creating figures using the pyplot interface, use the ``@cleanup``
decorator::
View
@@ -108,7 +108,7 @@ class Legend(Artist):
'upper center' : 9,
'center' : 10,
- loc can be a tuple of the noramilzed coordinate values with
+ loc can be a tuple of the normalized coordinate values with

This comment has been minimized.

Show comment Hide comment
@NelleV

NelleV Jan 7, 2013

Contributor

Good catch!

@NelleV

NelleV Jan 7, 2013

Contributor

Good catch!

respect its parent.
"""
@@ -729,7 +729,6 @@ def _auto_legend_data(self):
assert self.isaxes
ax = self.parent
- vertices = []
bboxes = []
lines = []
@@ -750,6 +749,11 @@ def _auto_legend_data(self):
transform = handle.get_transform()
bboxes.append(handle.get_path().get_extents(transform))
+ try:
+ vertices = np.concatenate([l.vertices for l in lines])
+ except ValueError:
+ vertices = np.array([])
+
return [vertices, bboxes, lines]
def draw_frame(self, b):
@@ -915,20 +919,31 @@ def _find_best_position(self, width, height, renderer, consider=None):
verts, bboxes, lines = self._auto_legend_data()
bbox = Bbox.from_bounds(0, 0, width, height)
- consider = [self._get_anchored_bbox(x, bbox, self.get_bbox_to_anchor(),
- renderer)
- for x
- in range(1, len(self.codes))]
+ if consider is None:
+ consider = [self._get_anchored_bbox(x, bbox,
+ self.get_bbox_to_anchor(),
+ renderer)
+ for x in range(1, len(self.codes))]
#tx, ty = self.legendPatch.get_x(), self.legendPatch.get_y()
candidates = []
for l, b in consider:
legendBox = Bbox.from_bounds(l, b, width, height)
badness = 0
+ # XXX TODO: If markers are present, it would be good to
+ # take their into account when checking vertex overlaps in
+ # the next line.
badness = legendBox.count_contains(verts)
badness += legendBox.count_overlaps(bboxes)
for line in lines:
+ # FIXME: the following line is ill-suited for lines
+ # that 'spiral' around the center, because the bbox
+ # may intersect with the legend even if the line
+ # itself doesn't. One solution would be to break up
+ # the line into its straight-segment components, but
+ # this may (or may not) result in a significant
+ # slowdown if lines with many vertices are present.
if line.intersects_bbox(legendBox):
badness += 1
Oops, something went wrong.