-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
bugfix for PathSimplifier
#28478
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
bugfix for PathSimplifier
#28478
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for opening your first PR into Matplotlib!
If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks.
You can also join us on gitter for real-time discussion.
For details on testing, writing docs, and our review process, please see the developer guide
We strive to be a welcoming and open project. Please follow our Code of Conduct.
Thank you for your work on this, but I do not this is the right solution. It does make it look better, but simplify is still not handling the
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think that this is addressing the actual underlying bug.
I think that this is not an issue with this handling of
Do you mean that it should be handling |
As I mentioned earlier,
Removing these lines produces the "intended" behavior of
However, I am not sure what would break if these lines are removed. Moreover, I think that it is better to address this issue in a different PR, because I feel that the underlying issue in #17914 was that And for special casing of I would like to hear your thoughts on this @tacaswell |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems reasonable to me, but I think there could be a fair number of edge cases here that we could try to hit in the test to make it a bit more robust.
The extra LINETOs being added was noticed in the original issue: #17914 (comment)
Did you try running the test suite with your proposed change to remove that extra LINETO to see if it breaks anything?
Thanks for the response.
I agree. I have modified the tests according to your suggestions.
A significant number of tests in The only test that was not off by one was
This would guarantee that there is at least one vertex in the path, which would be a Nevertheless, I couldn't find any tests where removing that extra LINETO produces a logical error. |
lib/matplotlib/tests/test_path.py
Outdated
expected_path = Path([(1, 1), (2, 1), (2, 2), (1, 1), | ||
(-1, 0), (-2, 0), (-2, 1), (-1, 0), (-1, 0), (0, 0)], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting that only the final CLOSEPOLY simplification gets the extra LINETO section.
I personally think it'd be nice to apply your fixes here and not assert against the extra LINETO since you've gone through the work of investigating them and your fix looks good to me at first glance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting that only the final CLOSEPOLY simplification gets the extra LINETO section.
The extra LINETO is not related to CLOSEPOLY simplification. Even a simple path has it's final LINETO vertex duplicated.
>>> p
Path(array([[1., 1.],
[2., 1.],
[2., 0.],
[0., 0.]]), array([1, 2, 2, 0], dtype=uint8))
>>> p.cleaned(simplify=True)
Path(array([[1., 1.],
[2., 1.],
[2., 0.],
[2., 0.],
[0., 0.]]), array([1, 2, 2, 2, 0], dtype=uint8))
For now, the fix that I mentioned is just to remove the part of code which adds that LINETO.
I personally think it'd be nice to apply your fixes here and not assert against the extra LINETO since you've gone through the work of investigating them and your fix looks good to me at first glance.
It is good to hear that. However, what about the failing pytests in path_simplification.py
as mentioned in #28478 (comment). Should I also modify them so as to fix the off by one errors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, what about the failing pytests in path_simplification.py
as mentioned in #28478 (comment). Should I also modify them so as to fix the off by one errors?
I forgot about needing to update those as well. Maybe it is best to just leave the assertion with the extra expected LINETO for now and then update all the off-by-one issues in a follow-up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tacaswell it would be good to get your eyes on this again since you're currently requesting changes.
Thanks for reviewing the changes. I was thinking that moving the test from These are small changes, so can I go ahead with them? |
/* If we don't have a valid initial vertex, then | ||
we can't close the path, so we skip the vertex */ | ||
continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a test for this case as well?
What is the expected result if the second MOVETO of a compound path is (nan, nan)
? Here it looks like we are still adding the inbetween LINETOs and just not starting/closing the path. Does it therefore merge into the first path in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a compound path such as:
p = Path([(1, 0), (1, -1), (2, -1),
(np.nan, np.nan), (-1, -1), (-2, 1), (-1, 1),
(2, 2), (0, -1)],
[Path.MOVETO, Path.LINETO, Path.LINETO,
Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO,
Path.CLOSEPOLY, Path.LINETO])
Here the second MOVETO is (nan, nan)
. I plotted this path without simplification to see what the intended plot should be like.

So it seems like, when plotting, if CLOSEPOLY is encountered without having a valid MOVETO vertex, it plots the point corresponding to the CLOSEPOLY (in this case, it is point 8 at (2, 2)
) but doesn't close the polygon. After this, the LINETO to (0, -1)
is continuous with the previously existing path.
Here it looks like we are still adding the inbetween LINETOs and just not starting/closing the path. Does it therefore merge into the first path in this case?
So yes, you are correct, and it seems to be the expected result as well.
Therefore, the simplified Path would be:

>>> p.cleaned(simplify=True)
Path(array([[ 1., 0.],
[ 1., -1.],
[ 2., -1.],
[nan, nan],
[-1., -1.],
[-2., 1.],
[-1., 1.],
[ 0., -1.],
[ 0., -1.],
[ 0., 0.]]), array([1, 2, 2, 1, 2, 2, 2, 2, 2, 0], dtype=uint8))
Could you add a test for this case as well?
I think that the compound path discussed above will be good for the test.
@tacaswell pinging you for a review on this since you're blocking. We are hitting some of these edge cases in Cartopy I think where we are currently working around them manually ourselves. @r3kste do you have a separate update/PR with the removal of the extra LINETO you mentioned? |
I haven't yet opened a separate PR for the removal of the extra LINETO, but I would like to do so. |
Yes, please feel free to open a PR with that update, I just wanted to make sure I hadn't missed it coming in. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not remember the previous code, but this seems correct to me now.
Thanks, @r3kste and congratulations on your first merged Matplotlib PR 🎉 Hope to hear from you again! |
PR summary
closes #17914
PathSimplifier
should ignore vertices corresponding toPath.CLOSEPOLY
, and rather replace them with the most recentPath.MOVETO
vertex.Code for reproducing the bug / Actual outcome
Expected Outcome
The Path should be closed.
Actual Outcome
PR checklist