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
[Bug]: contains_point()
does not appear to work?
#23178
Comments
On further investigation, it appears that the docs might not be fully clear. It is not |
Can you simplify this so that it is not an animation? Its not trivial to debug in this form. Thanks.... |
@jklymak Ok here is a simpler code without any animation: import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import matplotlib
def main():
print(f"matplotlib version: {matplotlib.__version__}")
print(f"matplotlib backend: {matplotlib.get_backend()}")
fig, ax = plt.subplots()
ax.set_aspect("equal")
fig: plt.Figure
ax: plt.Axes
# Create two non-overlapping circles whose colour changes depending on certain conditions.
circle_1_centre = (0, 5)
patch_1 = Circle(circle_1_centre, 1, color="red")
circle_2_centre = (0, -5)
patch_2 = Circle(circle_2_centre, 1, color="red")
patches = [patch_1, patch_2]
for patch in patches:
ax.add_patch(patch)
# Create a test point.
test_point_coords = (0, 4.5)
_ = ax.plot(test_point_coords[0], test_point_coords[1], linestyle="None", marker="d")
# Logic to test if the test point lies inside a patch. If it does, change the colour.
for patch in patches:
# Case 1 without transform (doesn't work):
# if patch.contains_point(test_point_coords):
# patch.set_color("green")
# Case 2 with patch transform (also doesn't work):
# if patch.contains_point(patch.get_transform().transform(test_point_coords)):
# patch.set_color("green")
# Case 3 with axes transform (this one works):
if patch.contains_point(ax.transData.transform(test_point_coords)):
patch.set_color("green")
plt.show()
if __name__ == '__main__':
main() I tested three cases: without any transform, with transform that the patch returns, and with the transform the axes returns. Only the transform returned by the axes appears to work as intended. Look the the figures: |
I actually have no idea why the transform changes, but it definitely is not the same as |
Yes, the Patch Circle is intended to retain it's "circle-ness" regardless
of the underlying transforms. Pretty sure that's how circle markers are
implemented.
…On Thu, Jun 2, 2022 at 12:51 PM Jody Klymak ***@***.***> wrote:
I actually have no idea why the transform changes, but it definitely is
not the same as ax.transData. I *suspect* its so that the circle stays a
circle regardless of the aspect ratio of the axes, but I'm not sure
—
Reply to this email directly, view it on GitHub
<#23178 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACHF6C3ZMY7CM2THL6YOQDVNDRC3ANCNFSM5XSP6NWQ>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Stumbled over a similar problem myself. @stallam-unb there is also: matplotlib/lib/matplotlib/patches.py Lines 264 to 268 in dc0328f
Which I think is what you need for your use case. (Same as transData but easier to get to if you have a patch)
If I understand the And then there is the above mentioned So the documentation of
is technically correct because we need Note that the example that is given is also confusing: matplotlib/lib/matplotlib/patches.py Lines 193 to 198 in dc0328f
The code does return true, but change it a little: import matplotlib.pyplot as plt
from matplotlib.patches import Circle
f = plt.figure()
ax = f.subplots(1, 1)
c = Circle((0, 0), radius=0.5)
ax.add_patch(c)
point_outside = (0, .75)
wrong = c.get_transform().transform(point_outside)
correct = c.get_data_transform().transform(point_outside)
print(c.contains_point(wrong)) # prints true
print(c.contains_point(correct)) # prints false And now it shows that one needs So the docs of |
@hassec Huh, interesting! I am not a huge fan of the transformation step though as it does make it a bit confusing. After all, if I am specifying a circle (or any polygon) |
@stallam-unb I totally see your point of view. I actually also think that having Not sure if that's an easy to make change though? 🤔 |
Bug summary
The method
contains_point()
of a circular patch does not appear to return the correct answer. Note that I have also tested solution proposed in #14207, but it did not help.Code for reproduction
Actual outcome
Case 2 (calling
contains_point()
without transform):Case_2.mp4
Case 3 (calling
contains_point()
with transform):Case_3.mp4
Expected outcome
Case 1 (manually checking point):
Case_1.mp4
Additional information
No response
Operating system
Windows
Matplotlib Version
3.5.2
Matplotlib Backend
Qt5Agg
Python version
3.10.4
Jupyter version
NA
Installation
conda
The text was updated successfully, but these errors were encountered: