Check if Point on circle is between two other points on circle

2k Views Asked by At

I'm looking for a better solution than the 2 algorithms I've currently written (in C) to check if a point on the circumference of a circle is located in the short arc created between two other points on the same circle.

For example: p1 = 358 deg, p2 = 1 deg on the circumference, and I need to know if p3 = .5 degrees is located between p1 and p2 (the solution should regard it as such).

Clarification: For this use case I only check "betweenness" if p1 != p3 or p2 != p3. In those exceedingly rare cases (floating point numbers) I already have the answer I need.

This problem is complicated by the fact that sometimes retrograde motion means p2 < p1, and also because p1 and p2 can straddle the 0/360 degree boundary.

My real world use case (in case you are interested) is to determine when to continue on and apply an interpolation algorithm for finding exact time of conjunction (occultation) between two bodies in space, one body represented by p1 & p2 at known times, and a different object at p3.

4

There are 4 best solutions below

4
On BEST ANSWER

I've marked @tp1 answer correct because of the effort he expended in answering it, but I've not gotten around to testing it. It is computationally intensive and the following ended up being a simpler (and probably faster) solution which didn't require transforming the angle values into cartesian coordinates.

This definitely works in all cases I can think to test.

bool is_P3_between_P1_and_P2(double p1, double p2, double p3)
{
  double p1_p2, p1_p3;
  p1_p2 = fmod(p2 - p1 + 360, 360);
  p1_p3 = fmod(p3 - p1 + 360, 360);

  return (p1_p2 <= 180) != (p1_p3 > p1_p2);
}
1
On

You want to know if numbers $a,b,c\in[0,360)$ correspond to angles in anticlockwise order. This is the case if and only if either $a<b<c$ or $b<c<a$ or $a<c<b$.

11
On

This can be easily solved by "angle between two lines". Form angle between origo-A and origo-B, and another angle between origo-A and origo-P, and you'll get two angles. Now which one is larger will determine whether P is between A and B.

Angle between two lines $(x_1,x_2),(x_3,x_4)$ can be found from: $$ \cos \alpha = \frac{(x_2-x_1) \cdot (x_4-x_3)}{|x_2-x_1| |x_4-x_3|} $$, which means you'll use $\arccos$ to find the angles. You need to use this twice. Then it's just matter of comparing which angle is larger. Obviously you need to know the position of the point $(x,y) = (r \cos \beta, r \sin \beta)$ and position of origo $O(x,y) = (0,0)$.

So to wrap up, if your input is angles $p1 = 358$, $p2 = 1$, $p3 = .5$, then you'll need the following ($r$ is arbitrary choice $\neq 0$, for example $r=1.0$): $$ (x_1,y_1) = (r \cos(p1), r \sin(p1)) \\ (x_2,y_2) = (r \cos(p2), r \sin(p2)) \\ (x_3,y_3) = (r \cos(p3), r \sin(p3)) \\ (o_x,o_y) = (0,0)$$, then the lines are $((x_1,y_1),(o_x,o_y))$ and $((x_2,y_2),(o_x,o_y))$: $$ \alpha = \arccos { \frac{((x_1,y_1)-(o_x,o_y))\cdot((x_2,y_2)-(o_x,o_y))} {|(x_1,y_1)-(o_x,o_y)| |(x_2,y_1)-(o_x,o_y)| } }$$ Then the 2nd lines are $((x_3,y_3),(o_x,o_y))$ and $((x_1,y_1),(o_x,o_y))$: $$ \beta_1 = \arccos { \frac{((x_3,y_3)-(o_x,o_y))\cdot((x_1,y_1)-(o_x,o_y))}{|((x_3,y_3)-(o_x,o_y))| |((x_1,y_1)-(o_x,o_y))| } } $$ $$ \beta_2 = \arccos { \frac{((x_3,y_3)-(o_x,o_y))\cdot((x_2,y_2)-(o_x,o_y))}{|((x_3,y_3)-(o_x,o_y))| |((x_2,y_2)-(o_x,o_y))| } } $$ $$ \beta = max(\beta_1,\beta_2) $$

Then it's just comparision: $$\alpha < \beta $$ (note that there's still notational conviniences for $a \cdot b$ and $|a|$ an $a-b$ for dot product and distance of a vector and vector difference: $$ (a_x,a_y) \cdot (b_x,b_y) = a_x b_x + a_y b_y \\ |(a_x,a_y)| = \sqrt{a_x^2+a_y^2} \\ (a_x,a_y) - (b_x,b_y) = (a_x-b_x, a_y-b_y) $$ )

0
On

From your description, I assume you have the variables p1 and p2 that represent the location of the two given points on the circle, given as an angle in the range $[0,360)$.

I'll assume that p1<p2. If this is not the case, just swap their values.

If p2-p1<=180, then the short arc is from p1 to p2, and you want the angle x of your third point to be between them. If p2-p1>180, then the long arc is from p1 to p2, and you want the angle x of your third point to not be between them.

So you can write the condition in short as
(p2-p1<=180) == (p1<=x AND x<=p2)

In longhand form it would be
((p2-p1<=180) AND (p1<=x AND x<=p2))
OR
(NOT(p2-p1<=180) AND NOT (p1<=x AND x<=p2))