Using python to calculate radial angle, in clockwise/counterclockwise directions, given pixel coordinates (and then vice-versa)
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------
Take control of your privacy with Proton's trusted, Swiss-based, secure services.
Choose what you need and safeguard your digital life:
Mail: https://go.getproton.me/SH1CU
VPN: https://go.getproton.me/SH1DI
Password Manager: https://go.getproton.me/SH1DJ
Drive: https://go.getproton.me/SH1CT
Music by Eric Matyas
https://www.soundimage.org
Track title: Puddle Jumping Looping
--
Chapters
00:00 Using Python To Calculate Radial Angle, In Clockwise/Counterclockwise Directions, Given Pixel Coordi
02:26 Answer 1 Score 1
04:12 Answer 2 Score 1
05:17 Accepted Answer Score 7
05:55 Thank you
--
Full question
https://stackoverflow.com/questions/3725...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #trigonometry
#avk47
ACCEPTED ANSWER
Score 7
You can simplify your code quite a bit by using a couple of simple rules. Simple code is less likely to have bugs.
First, converting between clockwise and counter-clockwise just means inverting the sign: angle = -angle.
Second, to restrict an angle to the range [0, 360) you simply use angle % 360. This works no matter if the angle started out negative or positive, integer or floating point.
def angle_to(p1, p2, rotation=0, clockwise=False):
angle = degrees(atan2(p2[1] - p1[1], p2[0] - p1[0])) - rotation
if not clockwise:
angle = -angle
return angle % 360
ANSWER 2
Score 1
Re: "angle_to() should return the number of degrees a clockhand would have to turn to travel from p1 to p2"
In your code, you subtract the coordinates of point p1 from p2 before you calculate the angle using atan2. Essentially, you're considering p1 to be the center of your clock, so it doesn't make any sense to talk about "travelling from p1 to p2 by a rotation". You'll need to specify three points: the center around which you do the rotations, point 1, and point 2. If the coordinates are xc, yc, x1, y1, x2, y2, then you'd need to do something like this:
angle1 = atan2(y1-yc, x1-xc)
angle2 = atan2(y2-yc, x2-xc)
relative_angle = angle1 - angle2
# now convert to degrees and handle +/-360 issues.
Update with your new specification: "return the number of degrees a clockhand would have to turn to travel from 0° to the line connecting p1 to p2":
angle = degrees(atan2(p2[1], p2[0]))
This will return the clockwise angle (in pixel coordinates) in the range -pi to +pi (-180 to +180 deg). In your example, angle_to((100,100), (25,25)) ("want 225, but get 135"), the atan2 will result in -135 deg, which means +135 deg counterclockwise. That is the answer that you would want (modulo 360 degrees), since you have not specified whether the clock hand should be turning cw or ccw (you only specify whether the starting position is cw or ccw relative to the 3 o'clock position). However, depending on the value of clockwise, which defaults to False, you do something complicated.
If you want to ensure that the clock hand turns cw, then you should add 360 deg to the result angle if it is negative, not revert the angle.
(Note: I deleted the old answer; the first two comments refer to the old answer.)
ANSWER 3
Score 1
This:
angle = (360 - angle if angle > 0 else -1 * angle) - rotation
I don't know what you were trying to achieve there, but that indeed does not do what you want. Just having -angle reflects the angle; changes the angle direction, from anti-clockwise to clockwise, noting that you're in the counter-clockwise branch of the condition. Then you add 360, and that messes everything up. The else branch just multiplies the angle by -1 - reversing it again. The clockwise branch is where you needed to reverse the angle (and add 360 to ensure the angle is positive).
Here is a simple version of your function fixed without the extra rotation parameter:
def angle_to(p1, p2, clockwise=False):
p2 = list(p2)
p2[0] = p2[0] - p1[0]
p2[1] = (p2[1] - p1[1])
angle = degrees(atan2(p2[1], p2[0]))
angle = 360 + angle if angle < 0 else angle
return angle if not clockwise else -angle+360
Your other function suffers from exactly the same problem in these lines:
if clockwise:
angle -= rotation
angle = angle if angle > 0 else angle + 360
else:
angle = (360 - angle if angle > 0 else -1 * angle) - rotation
angle = angle if angle > 0 else angle + 360
Should be:
angle -= rotation
if clockwise:
angle = -angle+360 if angle > 0 else -angle
else:
angle = angle if angle > 0 else angle + 360