8000 fix FancyArrowPatch picker fails depending on arrowstyle by zhoubecky · Pull Request #10776 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

fix FancyArrowPatch picker fails depending on arrowstyle #10776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 23, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions lib/matplotlib/patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,18 @@ def contains(self, mouseevent, radius=None):
if callable(self._contains):
return self._contains(self, mouseevent)
radius = self._process_radius(radius)
inside = self.get_path().contains_point(
(mouseevent.x, mouseevent.y), self.get_transform(), radius)
return inside, {}
codes = self.get_path().codes
vertices = self.get_path().vertices
# if the current path is concatenated by multiple sub paths.
# get the indexes of the starting code(MOVETO) of all sub paths
idxs, = np.where(codes == 1)
# Don't split before the first MOVETO.
idxs = idxs[1:]
return any(
subpath.contains_point(
(mouseevent.x, mouseevent.y), self.get_transform(), radius)
for subpath in map(
Path, np.split(vertices, idxs), np.split(codes, idxs))), {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I finally see what this is doing, but, can this be deconvolved to ease in maintenance and understanding? Other devs are free to approve if they are OK with this, and its just my python ignorance, but its not the clearest return statement in the code base.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you reformat this to

        subpaths = map(Path, np.split(vertices, idxs), np.split(codes, idxs)))
        contains = any(
            subpath.contains_point(
                (mouseevent.x, mouseevent.y), self.get_transform(), radius)
            for subpath in subpaths))
	return contains, {}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is OK to leave as-is.


def contains_point(self, point, radius=None):
"""
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions lib/matplotlib/tests/test_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
from numpy.testing import assert_array_equal
import pytest

from matplotlib import patches
from matplotlib.path import Path
from matplotlib.patches import Polygon
from matplotlib.testing.decorators import image_comparison
import matplotlib.pyplot as plt
from matplotlib import transforms
from matplotlib.backend_bases import MouseEvent


def test_empty_closed_path():
Expand Down Expand Up @@ -70,6 +72,46 @@ def test_nonlinear_containment():
ax.transData.transform_point((50, .5)), ax.transData)


@image_comparison(
baseline_images=['arrow_contains_point'], extensions=['png'],
remove_text=True, style='mpl20')
def test_arrow_contains_point():
# fix bug (#8384)
fig, ax = plt.subplots()
ax.set_xlim((0, 2))
ax.set_ylim((0, 2))

# create an arrow with Curve style
arrow = patches.FancyArrowPatch((0.5, 0.25), (1.5, 0.75),
arrowstyle='->',
mutation_scale=40)
ax.add_patch(arrow)
# create an arrow with Bracket style
arrow1 = patches.FancyArrowPatch((0.5, 1), (1.5, 1.25),
arrowstyle=']-[',
mutation_scale=40)
ax.add_patch(arrow1)
# create an arrow with other arrow style
arrow2 = patches.FancyArrowPatch((0.5, 1.5), (1.5, 1.75),
arrowstyle='fancy',
fill=False,
mutation_scale=40)
ax.add_patch(arrow2)
patches_list = [arrow, arrow1, arrow2]

# generate some points
X, Y = np.meshgrid(np.arange(0, 2, 0.1),
np.arange(0, 2, 0.1))
for k, (x, y) in enumerate(zip(X.ravel(), Y.ravel())):
xdisp, ydisp = ax.transData.transform_point([x, y])
event = MouseEvent('button_press_event', fig.canvas, xdisp, ydisp)
for m, patch in enumerate(patches_list):
# set the points to red only if the arrow contains the point
inside, res = patch.contains(event)
if inside:
ax.scatter(x, y, s=5, c="r")


@image_comparison(baseline_images=['path_clipping'],
extensions=['svg'], remove_text=True)
def test_path_clipping():
Expand Down
0