From bc15d12f82003bf13392909ef6091357687f5dda Mon Sep 17 00:00:00 2001 From: Jordan Feng Date: Sun, 8 Mar 2020 23:09:48 -0400 Subject: [PATCH 1/7] Add texts into legend hit test --- lib/matplotlib/legend.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index 9da20b65c489..2dce906f4550 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -838,7 +838,10 @@ 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_bbox_patch()) + for text in ax.texts] + return bboxes, lines, offsets, texts def get_children(self): # docstring inherited @@ -1011,7 +1014,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: @@ -1030,6 +1033,7 @@ def _find_best_position(self, width, height, renderer, consider=None): 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: From 59f3188d1bcae7eff4d4b96499823876df9bc376 Mon Sep 17 00:00:00 2001 From: Jordan Feng Date: Mon, 9 Mar 2020 13:42:08 -0400 Subject: [PATCH 2/7] Changed some calls. --- lib/matplotlib/legend.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index 2dce906f4550..efdbc5fc8ebd 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -38,6 +38,7 @@ PolyCollection) from matplotlib.transforms import Bbox, BboxBase, TransformedBbox from matplotlib.transforms import BboxTransformTo, BboxTransformFrom +from matplotlib.text import Text from matplotlib.offsetbox import HPacker, VPacker, TextArea, DrawingArea from matplotlib.offsetbox import DraggableOffsetBox @@ -839,8 +840,9 @@ def _auto_legend_data(self): for offset in transOffset.transform(hoffsets): offsets.append(offset) - texts = [text.get_bbox_patch()) + texts = [text._get_xy_display() for text in ax.texts] + return bboxes, lines, offsets, texts def get_children(self): @@ -1033,7 +1035,7 @@ def _find_best_position(self, width, height, renderer, consider=None): for line in lines) + legendBox.count_contains(offsets) + legendBox.count_overlaps(bboxes) - + legendBox.count_overlaps(texts) + + legendBox.count_contains(texts) + sum(line.intersects_bbox(legendBox, filled=False) for line in lines)) if badness == 0: From 6288eeb55d6531736ce5d2e3340c471ec9438b90 Mon Sep 17 00:00:00 2001 From: Jordan Feng Date: Mon, 9 Mar 2020 15:20:42 -0400 Subject: [PATCH 3/7] Fixed text overlapping with legend --- lib/matplotlib/legend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index efdbc5fc8ebd..c7c379c6d0d5 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -840,7 +840,7 @@ def _auto_legend_data(self): for offset in transOffset.transform(hoffsets): offsets.append(offset) - texts = [text._get_xy_display() + texts = [text.get_window_extent() for text in ax.texts] return bboxes, lines, offsets, texts @@ -1035,7 +1035,7 @@ def _find_best_position(self, width, height, renderer, consider=None): for line in lines) + legendBox.count_contains(offsets) + legendBox.count_overlaps(bboxes) - + legendBox.count_contains(texts) + + legendBox.count_overlaps(texts) + sum(line.intersects_bbox(legendBox, filled=False) for line in lines)) if badness == 0: From 63fbaa4c831fac6b23bc9b7c21d5e7b2165f6c5f Mon Sep 17 00:00:00 2001 From: Jordan Feng Date: Mon, 9 Mar 2020 15:32:22 -0400 Subject: [PATCH 4/7] Remove unused import statement --- lib/matplotlib/legend.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index c7c379c6d0d5..60ab77ffa8c8 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -38,7 +38,6 @@ PolyCollection) from matplotlib.transforms import Bbox, BboxBase, TransformedBbox from matplotlib.transforms import BboxTransformTo, BboxTransformFrom -from matplotlib.text import Text from matplotlib.offsetbox import HPacker, VPacker, TextArea, DrawingArea from matplotlib.offsetbox import DraggableOffsetBox From e360ebdee289c1137f4bf6f58b5a37faf52e12db Mon Sep 17 00:00:00 2001 From: RiazCharania Date: Mon, 9 Mar 2020 17:09:59 -0400 Subject: [PATCH 5/7] fixed flake8 issue --- lib/matplotlib/legend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index 60ab77ffa8c8..336057bac379 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -840,7 +840,7 @@ def _auto_legend_data(self): offsets.append(offset) texts = [text.get_window_extent() - for text in ax.texts] + for text in ax.texts] return bboxes, lines, offsets, texts From 2a88fe14b81a88a624c3848172c47db99ff462dc Mon Sep 17 00:00:00 2001 From: Jordan Feng Date: Mon, 9 Mar 2020 18:45:00 -0400 Subject: [PATCH 6/7] Add return of texts in documentation --- lib/matplotlib/legend.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index 60ab77ffa8c8..61830bb47b7e 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 From 732b5c434b5268dea0cd950fb77f4068ff5763c5 Mon Sep 17 00:00:00 2001 From: RiazCharania Date: Mon, 9 Mar 2020 19:56:15 -0400 Subject: [PATCH 7/7] added unit tests, edited legend.py for pep8 compliance --- lib/matplotlib/legend.py | 14 ++++++------ lib/matplotlib/tests/test_legend.py | 35 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index 336057bac379..7474ece5de0b 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -840,7 +840,7 @@ def _auto_legend_data(self): offsets.append(offset) texts = [text.get_window_extent() - for text in ax.texts] + for text in ax.texts] return bboxes, lines, offsets, texts @@ -1031,12 +1031,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) - + legendBox.count_overlaps(texts) - + 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