Get angle from 2 positions
Does this other answer help?
How to map atan2() to degrees 0-360
I've written it like this:
- (CGFloat) pointPairToBearingDegrees:(CGPoint)startingPoint secondPoint:(CGPoint) endingPoint
{
CGPoint originPoint = CGPointMake(endingPoint.x - startingPoint.x, endingPoint.y - startingPoint.y); // get origin point to origin by subtracting end from start
float bearingRadians = atan2f(originPoint.y, originPoint.x); // get bearing in radians
float bearingDegrees = bearingRadians * (180.0 / M_PI); // convert to degrees
bearingDegrees = (bearingDegrees > 0.0 ? bearingDegrees : (360.0 + bearingDegrees)); // correct discontinuity
return bearingDegrees;
}
Running the code:
CGPoint p1 = CGPointMake(10, 10);
CGPoint p2 = CGPointMake(20,20);
CGFloat f = [self pointPairToBearingDegrees:p1 secondPoint:p2];
And this returns 45.
Hope this helps.
Here's how I'm doing it in Swift for those interested, it's based on @bshirley's answer above w/ a few modifications to help match to the calayer rotation system:
extension CGFloat {
var degrees: CGFloat {
return self * CGFloat(180) / .pi
}
}
extension CGPoint {
func angle(to comparisonPoint: CGPoint) -> CGFloat {
let originX = comparisonPoint.x - x
let originY = comparisonPoint.y - y
let bearingRadians = atan2f(Float(originY), Float(originX))
var bearingDegrees = CGFloat(bearingRadians).degrees
while bearingDegrees < 0 {
bearingDegrees += 360
}
return bearingDegrees
}
}
This provides a coordinate system like this:
90
180 0
270
Usage:
point.angle(to: point2)
CGPoint.zero.angle(to: CGPoint(x: 0, y: 1)) // 90
I modified @tomas' solution to be streamlined. It's likely (it was for me) that this math is going to be called frequently.
In my incarnation, you have to perform the difference between the two points yourself (or if you're lucky, (0,0) is already one of your points). The value being calculated is the direction of the point from (0,0). Yes, that's simple enough and you could inline it if you really want to. My preference is for more readable code.
I also converted it to a function call:
CGFloat CGPointToDegree(CGPoint point) {
// Provides a directional bearing from (0,0) to the given point.
// standard cartesian plain coords: X goes up, Y goes right
// result returns degrees, -180 to 180 ish: 0 degrees = up, -90 = left, 90 = right
CGFloat bearingRadians = atan2f(point.y, point.x);
CGFloat bearingDegrees = bearingRadians * (180. / M_PI);
return bearingDegrees;
}
If you don't want negative values, you need to convert it yourself. Negative values were fine for me - no need to make unneeded calculations.
I was using this in a cocos2d environment, this is how I call it: (Mathematically, we are translating the plane to make p0
the origin. Thus subtracting p0
from p1
(p0
- p0
= {0,0}). The angles are unchanged when the plane is translated.)
CGPoint p0 = self.position;
CGPoint p1 = other.position;
CGPoint pnormal = ccpSub(p1, p0);
CGFloat angle = CGPointToDegree(pnormal);
ccpSub
is provided by cocos2d, it's subtraction of a tuple - you can do that yourself if you don't have that available
aside: it's generally not polite style to name the method as above with the CG___
naming scheme, which identifies the function as part of CoreGraphics
- so if you want to rename it to MyConvertCGPointToBearing()
or FredLovesWilma()
then you should do that.