Skip to content
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

Check if point is in path or not by contains_point #14207

Closed
zhangt58 opened this issue May 13, 2019 · 2 comments · Fixed by #15216
Closed

Check if point is in path or not by contains_point #14207

zhangt58 opened this issue May 13, 2019 · 2 comments · Fixed by #15216
Milestone

Comments

@zhangt58
Copy link

zhangt58 commented May 13, 2019

I tried to use contains_point method of Patch to check if some point is inside the closed path, e.g.
I defined an ellipse with the center, width, height and angle parameters:

>>> from matplotlib.patches import Ellipse
>>> e1 = Ellipse((3,5), 10, 8, 20)
>>> e1.contains_point((3,5))
True

The last line prints out True, which means the center is in the defined ellipse. But after I added the e1 to an axes, the same line just print out False, e.g.

>>> import matplotlib.pyplot as plt
>>> from matplotlib.patches import Ellipse
>>> fig, ax = plt.subplots()
>>> e1 = Ellipse((3,5), 10, 8, 20)
>>> e1.contains_point((3,5))
True
>>> ax.add_patch(e1)
>>> e1.contains_point((3,5))
False

I'm testing the above with matplotlib of version 3.0.3. Is this a bug? Or something I did was not correct? Thanks!

@timhoffm
Copy link
Member

This is a bug. Probably caused by add_patch changing the transform, which is not correctly accounted for by contains_point.

@tacaswell
Copy link
Member

I am not sure this is a bug per-say, but confusion over what coordinate system the incoming point is in. When it is first created, the artist has no transform which means it is implicitly the unit transfrom and all of your center, and radii are in the same coordinate frame. Once you add the patch to the axes we set the transform to be the data trasfrom (data space -> screen space) (see https://matplotlib.org/3.1.1/tutorials/advanced/transforms_tutorial.html). This means internal to contains_point we convert the path to screen units before asking if your point is in it but we do not transform the input point. In the screen coordinate frame (3, 5) is way down at the bottom corner of the figure. If you transfrom the input point to screen space via

>>> e1.contains_point(ax.transData.transform((3, 5)))                                                                                       
True

it works again. I suspect the reason it behaves this way is that almost always when we are checking if a point falls in a path it is because we are seeing if a mouse event was over a given artist and there the "natural" input is screen units (as that is (more or less) what the GUI toolkits give us).

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

Successfully merging a pull request may close this issue.

3 participants