4

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)?

tipycalFlow
  • 7,594
  • 4
  • 34
  • 45

2 Answers2

6

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.

andrew cooke
  • 45,717
  • 10
  • 93
  • 143
  • ya...I found atan2 and it does what I wanted to. Thanks... but for a challenge's sake...how would this be possible with acos() ? – tipycalFlow Aug 04 '11 at 13:08
  • i don't have a canned solution - i'd need to sit down with pencil + paper and work out the different cases and write tests for them. i think you'd end up comparing deltas in x and y, which is effectively using tangents anyway. – andrew cooke Aug 04 '11 at 14:42
  • came up with one solution... but atan2 is still the preferred way! – tipycalFlow Aug 08 '11 at 07:54
2

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)).

tipycalFlow
  • 7,594
  • 4
  • 34
  • 45