-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
FIX: correctly handle large arcs #17564
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
Conversation
Any chance this fixes, or you understand it enough to fix, #7491? |
1cca12a
to
7f840f9
Compare
Apparently we do need to squash the angles in both code paths. |
0da5826
to
719a920
Compare
I adjusted the tests and squashed this down to one commit. |
On closer inspection, this test is not testing what I thought it was. Will work up a new test (and rebase). |
620af63
to
03da86e
Compare
This is ready for review again and very different that the original version. The new test should be more understandable as well. I am still not sure that the threshold for switching to the "big path" logic is right, but it is possible I am confused about how it should work. |
https://github.com/matplotlib/matplotlib/blob/ce9bade034cc09e3fb49d7d12fc83aa36c557cdb/lib/matplotlib/patches.py is I think the reference to look at when trying to understand this code. |
95b85ae
to
d43b105
Compare
Looking at the paper, for a 4-spline, it said:
and since 8-spline is 1e-6 (or 1000 times smaller), it makes sense that we need a circle of such a large radius in order to see something with only about a pixel difference. |
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.
Not 100% on the tests, but the change seems right, individually.
ax2.set_xlim(-25000, 18000) | ||
ax2.set_ylim(-20000, 6600) |
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.
Is this still the right trigger?
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.
The second axis is trying to hit the "small" path which this does. These numbers could be made much smaller now that we have fixed the quadratic growth issue.
The draw method of mpatches.Arc has two paths: - if the arc is "small" compared to its size in the rendered image then render the whole arc and let clipping do it's thing - if the arc is "big" compared to its size on the screen then sort out where the circle intersects the axes boundary and only draw that part of it This makes several changes to the Arc draw method: - make sure that we keep angles in [0, 360) range - only go through the angle stretching code if we need to (to avoid numerical instability of angles not round-tripping with scale=1) - compute length, not offset from origin of width / height and use the correct transform. Previously we were effectively squaring the height and width Tests: - Adjusted an existing test image to use this failing case and to exercise both code paths. - Added a test function of ensuring we can draw a big arc in each quadrant
The previous commit removed a quadratic scaling when deciding which path we should go through. The quadratic scaling made us kick into the high-resolution code path too soon. We now no longer go through the high-resolution code path in this test which changes the curves slightly due to using different control points.
Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
# if we need to stretch the angles because we are distorted | ||
width != height | ||
# and we are not doing a full circle | ||
and not (theta1 != theta2 and theta1 % 360 == theta2 % 360) |
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.
probably needs a comment, IIRC you do this because theta1 and theta2 may not match anymore after stretching? (i.e. why can't you just always stretch)
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.
can you instead first take everything mod 360 and then always stretch?
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 tried that and it did not work, as 0%360 == 360%360
. I guess we could keep track of if theta1 == theta2
up front and then add back 360 if they were? I don't think we want to special case theta1 == theta2
as input to mean "full circle" not "no arc".
why did arc_angles.png change? |
Because this fixes a bug where we triggered the "big arc" path too soon in many cases (we were checking if |
Is that really |
|
@QuLogic beat me to posting, but link to where the transform is set up: matplotlib/lib/matplotlib/patches.py Lines 1398 to 1414 in 7f298e1
|
I'm going to make an executive decision and self-merge this with one review.
|
Owee, I'm MrMeeseeks, Look at me. There seem to be a conflict, please backport manually. Here are approximate instructions:
And apply the correct labels and milestones. Congratulation you did some good work ! Hopefully your backport PR will be tested by the continuous integration and merged soon! If these instruction are inaccurate, feel free to suggest an improvement. |
Merge pull request matplotlib#17564 from tacaswell/fix_big_arc FIX: big arc code path Conflicts: lib/matplotlib/patches.py - implicitly backport a change from matplotlib#15356 (from `- trans ` -> `+ trans.inverted()`)
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.
Retrospectively approving :)
The draw method of mpatches.Arc has two paths:
then render the whole arc and let clipping do it's thing
out where the circle intersects the axes boundary and only draw
that part of it
This makes several changes to the Arc draw method:
in the "big" case via transforms
Adjusted the test image to use this failing case and to exercise both
code paths, but could be convinced to split it out into its own file.
closes #17547
PR Checklist