Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Absolute angle between lines using inverse cosine

I want to calculate the angle between two lines formed by three points(one of the points is the point of intersection of the two lines) using inverse cosine function as follows:

CGFloat a = initialPosition.x - origin.x;
CGFloat b = initialPosition.y - origin.y;
CGFloat c = currentPosition.x - origin.x;
CGFloat d = currentPosition.y - origin.y;
CGFloat angle = (180/M_PI) * acosf(((a*c) + (b*d)) / ((sqrt(a*a + b*b)) * (sqrt(c*c + d*d))));

Unfortunately, acosf returns a value between 0 and pi only. How do I find a value between 0 and 2*pi (going, say, in the anti-clockwise manner)?

like image 620
tipycalFlow Avatar asked Feb 23 '23 09:02

tipycalFlow


2 Answers

i don't know what language you are using, but typically there is an atan2 function that gives you a value from the full 360 degrees. in this case you need to use it twice and then add a little additional logic.

some pseudocode will help clear things up:

initialAngle = atan2(initialPosition.y - origin.y, initialPosition.x - origin.x)
currentAngle = atan2(currentPosition.y - origin.y, currentPosition.x - origin.x)
# angle is measured from x axis anti-clock, so lets find the value starting from
# initial and rotating anti-clock to current, as a positive number
# so we want current to be larger than initial
if (currentAngle < initialAngle) {currentAngle += 2 pi}
# and then we can subtract
return currentAngle - initialAngle

i know this isn't using acos, but that is multi-valued so to do so ends up using lots of logic about signs of differences that is bug-prone. atan2 is what you want.

like image 186
andrew cooke Avatar answered Feb 27 '23 09:02

andrew cooke


found a simple solution...This comes from high school maths! First make an equation of a line made from the origin and the initialPosition of the form y = mx+c. A point lying on either side of this line will satisfy y < mx+c or y > mx+c, depending on where it is. If finding angles in the clockwise or anti-clockwise sense, make the following check:

currentPosition.y < (currentPosition.x *(initialPosition.y - origin.y) + (initialPosition .x * origin.y - initialPosition.y * origin.x))  / (initialPosition.x - origin.x)

If the above condition is true, then the line formed from origin and currentPosition makes an angle less than 180 deg (in the clockwise sense) with the line formed from origin and initialPosition. Otherwise it makes an angle more than 180 deg in the clockwise sense and less than 180 deg in the anti-clockwise sense...and so on. Depending on the requirement, the final angle is either the (angle returned by acos) or (360 - (angle returned by acos)).

like image 40
tipycalFlow Avatar answered Feb 27 '23 10:02

tipycalFlow