diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index 4f18d0526e6..3af482cf603 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -737,6 +737,7 @@ def _auto_legend_data(self): ax = self.parent bboxes = [] lines = [] + offsets = [] for handle in ax.lines: assert isinstance(handle, Line2D) @@ -755,12 +756,19 @@ def _auto_legend_data(self): transform = handle.get_transform() bboxes.append(handle.get_path().get_extents(transform)) + for handle in ax.collections: + transform, transOffset, hoffsets, paths = handle._prepare_points() + + if len(hoffsets): + for offset in transOffset.transform(hoffsets): + offsets.append(offset) + try: vertices = np.concatenate([l.vertices for l in lines]) except ValueError: vertices = np.array([]) - return [vertices, bboxes, lines] + return [vertices, bboxes, lines, offsets] def draw_frame(self, b): 'b is a boolean. Set draw frame to b' @@ -920,7 +928,7 @@ def _find_best_position(self, width, height, renderer, consider=None): # should always hold because function is only called internally assert self.isaxes - verts, bboxes, lines = self._auto_legend_data() + verts, bboxes, lines, offsets = self._auto_legend_data() bbox = Bbox.from_bounds(0, 0, width, height) if consider is None: @@ -939,6 +947,7 @@ def _find_best_position(self, width, height, renderer, consider=None): # take their into account when checking vertex overlaps in # the next line. badness = legendBox.count_contains(verts) + badness += legendBox.count_contains(offsets) badness += legendBox.count_overlaps(bboxes) for line in lines: # FIXME: the following line is ill-suited for lines diff --git a/lib/matplotlib/tests/baseline_images/test_legend/not_covering_scatter.png b/lib/matplotlib/tests/baseline_images/test_legend/not_covering_scatter.png new file mode 100644 index 00000000000..4e9b72e640c Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_legend/not_covering_scatter.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_legend/not_covering_scatter_transform.png b/lib/matplotlib/tests/baseline_images/test_legend/not_covering_scatter_transform.png new file mode 100644 index 00000000000..e2a90732fc1 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_legend/not_covering_scatter_transform.png differ diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index a43231b964e..293c64a3dbf 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -16,6 +16,7 @@ import matplotlib.pyplot as plt import matplotlib as mpl import matplotlib.patches as mpatches +import matplotlib.transforms as mtrans @image_comparison(baseline_images=['legend_auto1'], remove_text=True) @@ -261,6 +262,32 @@ def test_nanscatter(): ax.grid(True) +@image_comparison(baseline_images=['not_covering_scatter'], extensions=['png']) +def test_not_covering_scatter(): + colors = ['b','g','r'] + + for n in range(3): + plt.scatter([n,], [n,], color=colors[n]) + + plt.legend(['foo', 'foo', 'foo'], loc='best') + plt.gca().set_xlim(-0.5, 2.2) + plt.gca().set_ylim(-0.5, 2.2) + + +@image_comparison(baseline_images=['not_covering_scatter_transform'], + extensions=['png']) +def test_not_covering_scatter_transform(): + # Offsets point to top left, the default auto position + offset = mtrans.Affine2D().translate(-20, 20) + x = np.linspace(0, 30, 1000) + plt.plot(x, x) + + plt.scatter([20], [10], transform=offset + plt.gca().transData) + + plt.legend(['foo', 'bar'], loc='best') + + if __name__ == '__main__': import nose nose.runmodule(argv=['-s', '--with-doctest'], exit=False) +