diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index 9da20b65c489..a512f4cfbd07 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -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 @@ -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 @@ -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: @@ -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. diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 0e340e7f1e82..0332488aa8f7 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -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