2
votes

I have three points that I know to be on a circle that represent the start, middle and end of an arc (a, m and b). I also have the angle of these points, from the positive X axis in an anti-clockwise direction, using atan2(y,x) of the three respective vectors from the centre to the points, so we have -pi < theta < pi.

I also know which of the points is m, and what I want to know is which of a and b is the clockwise end of the arc.

I can see that there are 8 ways the points can be arranged:

"East"       "West"     "East"
0          -pi | pi        0
---------------+-------------   
       a  m  b |           
          a  m | b         
             a | m  b 
               | a  m  b


       b  m  a |
          b  m | a
             b | m  a
               | b  m  a

where the first four have a as the "end" and b as the "start" and the latter four are the other way around. Bear in mind that orders about can wrap around at 0 and appear on the right or left, so sign is not helpful.

Is there a tidy way to work out which is the start and which is the end point? Other than laboriously checking relative values among each of the 8 options in a big, dense if/else-if block, that is.

Implementation language is Python, but this is not a language specific question!

2

2 Answers

2
votes

If m is on the left side of the directed line segment from a to b, then a is the counterclockwise end; otherwise, it's the clockwise end.

That is, take the left perpendicular of the vector ab, and find its dot product with am. If the dot product is positive, a is the CCW endpoint.

Incidentally, the tidiest way to deal with angles is to avoid using them. Vectors and linear algebra out-tidy angles and trigonometry any day of the week.

0
votes

I have just run into the same problem - thanks for the great writeup of the question. I think solving it the way you were heading is actually not so "laborious".

You can use your table to see it's just a question of which order the three angles are arranged, cyclically. A < M < B or A > M > B.

// = a < m < b ||
//   b < a < m || 
//   m < b < a;
anticlockwise = a < m && m < b || b < a && a < m || m < b && b < a;

Depending on how your language of choice feels about coercing booleans into integers, you might be able to write that as:

anticlockwise = (a < m + m < b + b < a) === 2;

(Well I found this a lot easier than trying to understand and compute perpendiculars, dot products, linear algebra...)