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

Conversation

zhoubecky
Copy link
Contributor

PR Summary

fix FancyArrowPatch picker fails depending on arrowstyle #8384

@jklymak jklymak changed the title fix FancyArrowPatch picker fails depending on arrowstyle #8384 fix FancyArrowPatch picker fails depending on arrowstyle Mar 14, 2018
@zhoubecky
Copy link
Contributor Author
zhoubecky commented Mar 14, 2018

Every arrowstyle(Curve, Bracket or others) contains one to three sub paths which represent the head arrow (if present), line, and tail arrow (if present) respectively.
If a Patch contains multiple Pathes, all the Pathes will be concatenated to one Path by joining the vertices list and the codes list. A composite Path with not properly closed sub Pathes will cause error in transformation thus resulting in incorrect evaluation of contains, a function check whether a point is within the Path.
FancyArrowPatch picker not works on Curve and Bracket arrows are because their paths consisted by multiple subpaths, and only the last subpath is closed properly(code 79).

Because whether a location should respond to a mouse event depends on the result of the contains function. So I check whether any sub path contains the point separately(separate by the starting code=1) in contains function.

@zhoubecky
Copy link
Contributor Author

Hi @tacaswell, I push a temp fix of this bug and add a test, could you take a look at it? Thank you.

@tacaswell tacaswell added this to the v3.0 milestone Mar 16, 2018
Copy link
Member
@tacaswell tacaswell left a comment

Choose a reason for hiding this comment

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

Left a few questions about the implementation.

This can be an a hot-path so I am a bit worried about performance (but have not bench marked anything).

Would it make sense to push this fix back up into the Path class?

Love the test!

@tacaswell
Copy link
Member

👍 on sorting out what is wrong here! This bug had me stumped.

@anntzer
Copy link
Contributor
anntzer commented Mar 25, 2018

Something like

        radius = self._process_radius(radius)
        codes = self.get_path().codes
        vertices = self.get_path().vertices
        idxs, = np.nonzero(codes == 1)
        idxs = idxs[1:]  # Don't split before the first MOVETO.
        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))), {}

is probably faster (moving all the logic to numpy and taking advantage of the lazy map).

But +1 to the PR in general.

@zhoubecky
Copy link
Contributor Author

Hi @anntzer , thanks for your suggestion! I have updated the code.

@zhoubecky
Copy link
Contributor Author

hi @tacaswell , is there anything else need to be fixed to make it better?

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.

@tacaswell tacaswell closed this Jul 4, 2018
@tacaswell tacaswell reopened this Jul 4, 2018
@tacaswell
Copy link
Member

Power-cycled to re-trigger CI

@tacaswell tacaswell added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Jul 4, 2018
@tacaswell
Copy link
Member

@zhoubecky Are you still interested in working on this and can you look into why the tests are failing? I suspect a re-base may help.

@tacaswell tacaswell modified the milestones: v3.0, v3.1 Jul 8, 2018
@tacaswell tacaswell removed the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Jul 8, 2018
@zhoubecky
Copy link
Contributor Author

@tacaswell sorry I just saw your message. I will take a look this weekend.

@zhoubecky
Copy link
Contributor Author

@tacaswell I have checked the failure message and it shows ImageComparisonFailure, the expected image name is arrow_contains_point-expected.png but the actual is arrow_contains_point.png. Change the image name and the tests should pass. I will double check and fix it. I need some time to reinstall the developing environment. Sorry for the late.

 and update fix based on reviewers' suggestion

change to use ax.scatter

Update test image
@dstansby
Copy link
Member
dstansby commented Oct 1, 2018

@zhoubecky I've just updated the test image for you on your branch - hopefully this should all pass now, and if it does I'll give it a review!

@tacaswell tacaswell reopened this Feb 1, 2019
@tacaswell
Copy link
Member

Power-cycled to re-run against current master.

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.

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
@tacaswell tacaswell left a comment

Choose a reason for hiding this comment

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

pending CI an the commit I just pushed.

@QuLogic QuLogic merged commit 68cfdcd into matplotlib:master Feb 23, 2019
meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Feb 23, 2019
@tacaswell
Copy link
Member

Thanks @zhoubecky ! Sorry this took almost a year to get in, hopefully we will hear from you again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants
0