Skip to content

Commit 5652c66

Browse files
authored
Merge pull request #7625 from anntzer/legend-autoposition-avoid-lines
Legend autopositioning with "spiraling" lines.
2 parents c6e5515 + e64f3fb commit 5652c66

File tree

2 files changed

+16
-34
lines changed

2 files changed

+16
-34
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
More accurate legend autopositioning
2+
````````````````````````````````````
3+
4+
Automatic positioning of legends now prefers using the area surrounded by a `Line2D` rather than placing the legend over the line itself.

lib/matplotlib/legend.py

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -909,47 +909,25 @@ def _find_best_position(self, width, height, renderer, consider=None):
909909
renderer)
910910
for x in range(1, len(self.codes))]
911911

912-
# tx, ty = self.legendPatch.get_x(), self.legendPatch.get_y()
913-
914912
candidates = []
915-
for l, b in consider:
913+
for idx, (l, b) in enumerate(consider):
916914
legendBox = Bbox.from_bounds(l, b, width, height)
917915
badness = 0
918916
# XXX TODO: If markers are present, it would be good to
919-
# take their into account when checking vertex overlaps in
917+
# take them into account when checking vertex overlaps in
920918
# the next line.
921-
badness = legendBox.count_contains(verts)
922-
badness += legendBox.count_contains(offsets)
923-
badness += legendBox.count_overlaps(bboxes)
924-
for line in lines:
925-
# FIXME: the following line is ill-suited for lines
926-
# that 'spiral' around the center, because the bbox
927-
# may intersect with the legend even if the line
928-
# itself doesn't. One solution would be to break up
929-
# the line into its straight-segment components, but
930-
# this may (or may not) result in a significant
931-
# slowdown if lines with many vertices are present.
932-
if line.intersects_bbox(legendBox):
933-
badness += 1
934-
935-
ox, oy = l, b
919+
badness = (legendBox.count_contains(verts)
920+
+ legendBox.count_contains(offsets)
921+
+ legendBox.count_overlaps(bboxes)
922+
+ sum(line.intersects_bbox(legendBox, filled=False)
923+
for line in lines))
936924
if badness == 0:
937-
return ox, oy
938-
939-
candidates.append((badness, (l, b)))
940-
941-
# rather than use min() or list.sort(), do this so that we are assured
942-
# that in the case of two equal badnesses, the one first considered is
943-
# returned.
944-
# NOTE: list.sort() is stable.But leave as it is for now. -JJL
945-
minCandidate = candidates[0]
946-
for candidate in candidates:
947-
if candidate[0] < minCandidate[0]:
948-
minCandidate = candidate
949-
950-
ox, oy = minCandidate[1]
925+
return l, b
926+
# Include the index to favor lower codes in case of a tie.
927+
candidates.append((badness, idx, (l, b)))
951928

952-
return ox, oy
929+
_, _, (l, b) = min(candidates)
930+
return l, b
953931

954932
def contains(self, event):
955933
return self.legendPatch.contains(event)

0 commit comments

Comments
 (0)