Using python to calculate radial angle, in clockwise/counterclockwise directions, given pixel coordinates (and then vice-versa)
<p>For a context I won't get into, I need two functions that are essentially reciprocals of each other.</p>

<p><code>angle_to()</code> should return the number of degrees a clockhand would have to turn to travel from 0° to the line connecting <code>p1</code> to <code>p2</code> (ie. <code>p1</code> is the center of rotation), and where both <code>p1</code> and <code>p2</code> are <em>pixel coordinates</em>.</p>

<p><code>point_pos()</code> should return the pixel coordinates of where a clockhand of length <code>amplitude</code> would be had it turned <code>angle</code>.</p>

<p>For both, the positive x-axis = 0° = 3 o'clock, and the argument <code>rotation</code> should shift that axis before the calculation begins in either the clockwise or counter-clockwise direction; then said calculation should move in the same direction with this adjusted reference. </p>

<p>My progress on each is included below; the failure is:</p>

<p>When clockwise=False, it returns the correct answer for the clockwise condition; when clockwise=True, angle_between() returns the right answer with a rounding error, and point_pos() gives me the wrong answer entirely.</p>

<p>I've also attached a visual explanation I mocked up in Illustrator as an apology to the internet for being unable to solve this and in case what I'm seeking isn't clear.</p>

<p><strong>Edit:</strong> cleaned up a line that unnecessarily complicated as per one answer below.</p>

<pre><code>from math import sin, cos, radians, pi, atan2, degrees

def angle_to(p1, p2, rotation=0, clockwise=False):
    if abs(rotation) &gt; 360:
        rotation %= 360
    p2 = list(p2)
    p2[0] = p2[0] - p1[0]
    p2[1] = p2[1] - p1[1]

    angle = degrees(atan2(p2[1], p2[0]))
    if clockwise:
        angle -= rotation
        return angle if angle &gt; 0 else angle + 360
    else:
        angle = (360 - angle if angle &gt; 0 else -1 * angle) - rotation
        return angle if angle &gt; 0 else angle + 360

def point_pos(origin, amplitude, angle, rotation=0, clockwise=False):
    if abs(rotation) &gt; 360:
        rotation %= 360
    if clockwise:
        rotation *= -1
    if clockwise:
        angle -= rotation
        angle = angle if angle &gt; 0 else angle + 360
    else:
        angle = (360 - angle if angle &gt; 0 else -1 * angle) - rotation
        angle = angle if angle &gt; 0 else angle + 360

    theta_rad = radians(angle)
    return int(origin[0] + amplitude * cos(theta_rad)), int(origin[1] + amplitude * sin(theta_rad))
</code></pre>

<p><a href="https://i.stack.imgur.com/B9qni.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/B9qni.png" alt="angle_to()"></a>
<a href="https://i.stack.imgur.com/hPoTZ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/hPoTZ.png" alt="point_pos()"></a></p>

<p><strong>Edit #2:</strong> Upon request, here's some failed output:</p>

<p><code>angle_to()</code> is flipping clockwise and counterclockwise (when I've tried to fix it, I end up getting wrong answers altogether), and in the clockwise direction, rotating and calculating in different directions</p>

<pre><code>&gt;&gt;&gt; print angle_to((100,100), (25,25))  # should be 225  
135.0
&gt;&gt;&gt; print angle_to((100,100), (25,25), 45)  # should be 180
90.0
&gt;&gt;&gt; print angle_to((100,100), (25,25), clockwise=True) # should be 135
225.0
&gt;&gt;&gt; print angle_to((100,100), (25,25), 45, clockwise=True)  # should be 90
180.0
</code></pre>

<p><code>point_pos()</code> is just wrong in the counterclockwise direction</p>

<pre><code># dunno what these should be (i'm bad at trig) but when I visually place the
# given p1 and the output p2 on screen it's obvious that they're wrong
&gt;&gt;&gt; print point_pos((100,100), 75, 225)               
(46, 153)
&gt;&gt;&gt; print point_pos((100,100), 75, 225, 45)
(100, 175)

# these are basically correct, rounding-errors notwithstanding
&gt;&gt;&gt; print point_pos((100,100), 75, 225, clockwise=True)
(46, 46)
&gt;&gt;&gt; print point_pos((100,100), 75, 225, 45, clockwise=True)
(99, 25)
</code></pre>