从2个位置获取角度

时间:2011-05-19 20:41:06

标签: ios cocos2d-iphone

我有两个物体,当我移动一个物体时,我想从另一个物体获得角度。

例如:

Object1X = 211.000000, Object1Y = 429.000000
Object2X = 246.500000, Object2Y = 441.500000

我在阳光下尝试过以下各种变化:

double radians = ccpAngle(Object1,Object2);
double degrees = ((radians * 180) / Pi); 

但是我只是得到了2.949023,我想要45度等等。

6 个答案:

答案 0 :(得分:44)

这个其他答案有帮助吗?

How to map atan2() to degrees 0-360

我写得像这样:

- (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;
}

运行代码:

CGPoint p1 = CGPointMake(10, 10);
CGPoint p2 = CGPointMake(20,20);

CGFloat f = [self pointPairToBearingDegrees:p1 secondPoint:p2];

这将返回45。

希望这有帮助。

答案 1 :(得分:12)

我修改了@tomas'解决方案以简化。很可能(这对我来说)这个数学将被频繁调用。

在我的化身中,你必须自己完成两点之间的差异(或者如果你很幸运,(0,0)已经是你的一个点)。计算的值是从(0,0)开始的点的方向。是的,这很简单,如果你真的想要,你可以内联它。我更喜欢更易读的代码。

我还将它转换为函数调用:

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;
}

如果您不想要负值,则需要自行转换。负值对我来说没问题 - 不需要进行不必要的计算。

我在cocos2d环境中使用它,这就是我所说的:(数学上,我们正在翻译平面以使p0成为原点。因此从p0中减去p1p0 - p0 = {0,0})。平面翻译时角度不变。)

CGPoint p0 = self.position;
CGPoint p1 = other.position;
CGPoint pnormal = ccpSub(p1, p0);
CGFloat angle = CGPointToDegree(pnormal);

ccpSub由cocos2d提供,它是一个元组的减法 - 你可以自己做,如果你没有那个

除此之外:使用CG___命名方案将上述方法命名为通常不礼貌的方式,该方案将函数标识为CoreGraphics的一部分 - 所以如果要将其重命名为{{1或者MyConvertCGPointToBearing()那么你应该这样做。

答案 2 :(得分:10)

以下是我在Swift中为感兴趣的人做的事情,它是基于@ bshirley上面的回答而做的一些修改,以帮助匹配calayer旋转系统:

extension CGPoint {
    func angle(to comparisonPoint: CGPoint) -> CGFloat {
        let originX = comparisonPoint.x - self.x
        let originY = comparisonPoint.y - self.y
        let bearingRadians = atan2f(Float(originY), Float(originX))
        var bearingDegrees = CGFloat(bearingRadians).degrees
        while bearingDegrees < 0 {
            bearingDegrees += 360
        }
        return bearingDegrees
    }
}

extension CGFloat {
    var degrees: CGFloat {
        return self * CGFloat(180.0 / M_PI)
    }
}

这提供了这样的坐标系:

        270
180              0
        90

用法:

point.angle(to: point2)
CGPoint.zero.angle(to: CGPoint(x: 0, y: 1)) // 90

答案 3 :(得分:1)

两点之间没有角度。如果您想知道从原点(0,0)到对象的矢量之间的角度,请使用标量(点)乘积:

theta = arccos ( (veca dot vecb) / ( |veca| * |vecb| )

您正在使用的语言的数学标准库肯定会提供arcus余弦,标量积和长度的函数。

答案 4 :(得分:0)

角度的顶点是点(0,0)。

考虑object1X = x1 .... object2Y = y2。

Angle(object1-object2) = 
   90       * (  (1 + sign(x1)) * (1 - sign(y1^2))
               - (1 + sign(x2)) * (1 - sign(y2^2)) )
 + 45       * (  (2 + sign(x1)) * sign(y1)
               - (2 + sign(x2)) * sign(y2)         )
 + 180/pi() * sign(x1*y1) * atan( (abs(x1) - abs(y1)) / (abs(x1) + abs(y1)) )
 - 180/pi() * sign(x2*y2) * atan( (abs(x2) - abs(y2)) / (abs(x2) + abs(y2)) )

答案 5 :(得分:0)

Swift 5.1

中的

Tomas' answer

func angle(between starting: CGPoint, ending: CGPoint) -> CGFloat {
    let center = CGPoint(x: ending.x - starting.x, y: ending.y - starting.y)
    let radians = atan2(center.y, center.x)
    let degrees = radians * 180 / .pi
    return degrees > 0 ? degrees : degrees + degrees
}