-1

I have 3 CGPoints A, B and C. I want to find the angle between AB and BC. I am trying to develop a swipe keyboard and I want to get the points whenever my swipe path changes the angle by a margin

1 Answers1

1

We need vectors representing AB and BC. Then we can compute the angle using the standard formula, which relates the cos of that angle to the dot product divided by the product of the magnitudes...

float angleBetween(CGPoint v, CGPoint a, CGPoint b) {
    CGVector vA = vectorFromTo(v, a);
    CGVector vB = vectorFromTo(v, b);
    return acosf(dot(vA, vB) / (magnitude(vA) * magnitude(vB)));
}

Here's how to make a vector from a pair of points...

CGVector vectorFromTo(CGPoint from, CGPoint to) {
    return CGVectorMake(to.x-from.x, to.y-from.y);
}

Here's how to dot product two vectors...

float dot(CGVector a, CGVector b) {
    return a.dx*b.dx + a.dy*b.dy;
}

And here's how to compute magnitude...

float magnitude(CGVector v) {
    return sqrtf(v.dx*v.dx + v.dy*v.dy);
}
danh
  • 62,181
  • 10
  • 95
  • 136
  • CGPoint v is the center point? – Nagavardhan Venkata Mar 24 '17 at 01:39
  • Yes - the vectors both emanate from it. – danh Mar 24 '17 at 12:54
  • I am not sure why I am getting the same angle for all points. – Nagavardhan Venkata Mar 24 '17 at 14:52
  • Can you show some log output? I'll be at a dev machine to help in about 2-3 hrs – danh Mar 24 '17 at 14:56
  • angle between A:{90.99, 115.33} (s), B:{55.99, 115.33}(a), C:{63.99, 111.99}(s) is 1.569754 angle between A:{55.99, 115.33} (a), B:{63.99, 111.99}(s), C:{101.99, 103.33}(d) is 1.568393 angle between A:{63.99, 111.99} (s), B:{101.99, 103.33}(d), C:{139.66, 93.33}(r) is 1.570467 angle between A:{101.99, 103.33} (d), B:{139.66, 93.33}(r), C:{170.66, 84.99}(t) is 1.570435 – Nagavardhan Venkata Mar 24 '17 at 14:56
  • I can provide additional logs if needed – Nagavardhan Venkata Mar 24 '17 at 19:10
  • @NagavardhanVenkata, sorry about my error. My magnitude function left out the obvious pythagorean step of taking the square root of the components squared. Fixed in an edit. I've up-voted the question, also. It might have been a dup but it was well formed. – danh Mar 24 '17 at 23:49
  • This is working great! – Nagavardhan Venkata Mar 29 '17 at 19:11
  • If the Y value does not change much (all 3 points are on the same line), the angle should be close to 180. But it is giving me between 0 and 1 – Nagavardhan Venkata Apr 26 '17 at 04:14
  • You mean instead of acosf(dot(vA,vB)) I should use fabs(dotvA,vB))? – Nagavardhan Venkata Apr 26 '17 at 04:27
  • 2017-04-26 00:55:11.935 Thumbs[96906:11369906] Angle between (175.750000,68.500000), (208.000000,68.500000) and (240.250000,68.500000) is 0.000000 2017-04-26 00:55:11.935 Thumbs[96906:11369906] Angle between (208.000000,68.500000), (240.250000,68.500000) and (272.750000,68.500000) is 0.000000 2017-04-26 00:55:11.935 Thumbs[96906:11369906] Angle between (240.250000,68.500000), (272.750000,68.500000) and (240.250000,68.500000) is nan 2017-04-26 00:55:11.936 Thumbs[96906:11369906] Angle between (272.750000,68.500000), (240.250000,68.500000) and (208.000000,68.500000) is 0.000000 – Nagavardhan Venkata Apr 26 '17 at 04:56
  • @NagavardhanVenkata - see edit. There was an error in the formula. We need to divide by the product of the magnitudes, without the parens, it was dividing by one and multiplying by the other – danh Apr 26 '17 at 04:56
  • 1
    @NagavardhanVenkata, With the fix, we get pi, which is correct for the collinear vectors – danh Apr 26 '17 at 04:59
  • I am not able to figure out the change that was made to the above code – Nagavardhan Venkata Apr 26 '17 at 05:17
  • Got it. Product of magnitude in () – Nagavardhan Venkata Apr 26 '17 at 05:18
  • Extra parents on this line: return acosf(dot(vA, vB) / (magnitude(vA) * magnitude(vB))); – danh Apr 26 '17 at 05:19