FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Legend auto positioning takes text objects into account by RiazCharania · Pull Request #16716 · matplotlib/matplotlib · GitHub

Repository navigation

21 changes: 14 additions & 7 deletions lib/matplotlib/legend.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,8 @@ def _auto_legend_data(self):
List of `.Path` corresponding to each line.
offsets
List of (x, y) offsets of all collection.
texts
List of the axes bounding boxes of all texts.
"""
assert self.isaxes # always holds, as this is only called internally
ax = self.parent
Expand All @@ -838,7 +840,11 @@ def _auto_legend_data(self):
_, transOffset, hoffsets, _ = handle._prepare_points()
for offset in transOffset.transform(hoffsets):
offsets.append(offset)
return bboxes, lines, offsets

texts = [text.get_window_extent()
for text in ax.texts]

return bboxes, lines, offsets, texts

def get_children(self):
# docstring inherited
Expand Down Expand Up @@ -1011,7 +1017,7 @@ def _find_best_position(self, width, height, renderer, consider=None):

start_time = time.perf_counter()

bboxes, lines, offsets = self._auto_legend_data()
bboxes, lines, offsets, texts = self._auto_legend_data()

bbox = Bbox.from_bounds(0, 0, width, height)
if consider is None:
Expand All @@ -1027,11 +1033,12 @@ def _find_best_position(self, width, height, renderer, consider=None):
# XXX TODO: If markers are present, it would be good to take them
# into account when checking vertex overlaps in the next line.
badness = (sum(legendBox.count_contains(line.vertices)
for line in lines)
+ legendBox.count_contains(offsets)
+ legendBox.count_overlaps(bboxes)
+ sum(line.intersects_bbox(legendBox, filled=False)
for line in lines))
for line in lines) +
legendBox.count_contains(offsets) +
legendBox.count_overlaps(bboxes) +
legendBox.count_overlaps(texts) +
sum(line.intersects_bbox(legendBox, filled=False)
for line in lines))
if badness == 0:
return l, b
# Include the index to favor lower codes in case of a tie.
Expand Down
35 changes: 35 additions & 0 deletions lib/matplotlib/tests/test_legend.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -570,3 +570,38 @@ def test_no_warn_big_data_when_loc_specified():
ax.plot(np.arange(5000), label=idx)
legend = ax.legend('best')
fig.draw_artist(legend) # Check that no warning is emitted.


def test_overlap_no_texts():
# test there is no error without text
fig, ax = plt.subplots()
fig.canvas.draw()
legend = ax.legend()
fig.draw_artist(legend)


def test_overlap_one_text():
# test legend doesn't overlap with one text
fig, ax = plt.subplots()
fig.canvas.draw()
ax.text(1, 0, "Text")
legend = ax.legend()
fig.draw_artist(legend)
texts = [text.get_window_extent()
for text in ax.texts]

assert legend.get_window_extent().count_overlaps(texts) == 0


def test_overlap_two_texts():
# test legend doesn't overlap with two texts
fig, ax = plt.subplots()
fig.canvas.draw()
ax.text(1, 0, "Text")
ax.text(0, 1, "Text")
legend = ax.legend()
fig.draw_artist(legend)
texts = [text.get_window_extent()
for text in ax.texts]

assert legend.get_window_extent().count_overlaps(texts) == 0

Back | FazBrowse Home | New Git URL