-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Wedge not honouring specified angular range #3298
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
I am pretty sure that this is an issue with float rounding/comparison and generating the path. Below is a modified example which I think shows the bug more clearly:
|
Hi I have chatted to Ludwig Schwardt about this who will submit a pull request Cheers On Thu, Jul 24, 2014 at 2:35 PM, Thomas A Caswell notifications@github.com
|
The problem is actually with Path.arc... Try this snippet: import matplotlib
arc = matplotlib.path.Path.arc
arc(52.31386924,232.31386924)
arc(52.313869244286224,232.31386924428622) The second arc does an extra loop around the circle. I've traced the problem to line 835 in path.py (7-year old @mdboom code!) - the last if-statement in the snippet below. The test is False for the first arc and True for the second arc. @classmethod
def arc(cls, theta1, theta2, n=None, is_wedge=False):
"""
Return an arc on the unit circle from angle
*theta1* to angle *theta2* (in degrees).
....
"""
# degrees to radians
theta1 *= np.pi / 180.0
theta2 *= np.pi / 180.0
twopi = np.pi * 2.0
halfpi = np.pi * 0.5
eta1 = np.arctan2(np.sin(theta1), np.cos(theta1))
eta2 = np.arctan2(np.sin(theta2), np.cos(theta2))
eta2 -= twopi * np.floor((eta2 - eta1) / twopi)
if (theta2 - theta1 > np.pi) and (eta2 - eta1 < np.pi):
eta2 += twopi This is one of those nasty trig corner cases... The if-statement ostensibly caters for the case (theta1, theta2) = (0, 360) or similar, where the user wants the full circle but could get a very thin sliver instead due to the angles getting normalised to the range -180 to 180 degrees (the purpose of eta1 and eta2). While the example theta1 and theta2 differ by exactly 180 degrees in both cases, after conversion to radians the first case differs by minutely less than pi and the second case by minutely more than pi. The original (theta1, theta2) arc setup has a sensitive spot around 0 degrees difference, since you either get a single point or a full circle, depending on whether theta1 is bigger or smaller than theta2. Part of the problem is that it is not clear how the arc is intended to map onto the theta1, theta2 range. Should the arc always stick to a full circle or less, as the case of eta2 - eta1 > 360 degrees is visually indistinguishable from eta2 - eta1 = 360 degrees (or eta1=0, eta2=360 for that matter)? Or should it preserve the number of turns and start and end points, i.e. a full mapping of the sweep? Or just the start and end points with a minimal sweep in between? That's why I'll leave a pull request to the experts for now, as the specification of arc is unclear and it will affect how this test could be improved :-) |
@ludwigschwardt Thanks for tracking this down so well. |
@ludwigschwardt: Yes, thanks also from me. To answer your question about intended behavior: I think it should never be more than 360 degrees. It's for drawing, so anything not visible is not necessary. But it should not be the minimal path between starting and ending points, it always should go from theta1 counterclockwise to theta2. Now it's just a matter of fixing the implementation to follow that... |
y = i // 3 | ||
|
||
wedge = mpatches.Wedge( | ||
(x * 3, y * 3), 1, theta1, theta2, facecolor='none', edgecolor='k', lw=3) |
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 line is too long
BUG : Wedge not honouring specified angular range Fixed minor PEP8 as part of merge
BUG : Wedge not honouring specified angular range Fixed minor PEP8 as part of merge
The following code illustrates the issue. The only difference in the two figures is that there is added decimal places to the precision of the angular range. This added precision however results in complete failure to draw the wedge correctly - a disc is drawn instead. It is repeatable, and tested to be faulty in matplotlib.version '1.2.0' as well as '1.3.1'
[TAC - edited to fix yelling/formatting