web-dev-qa-db-ja.com

2つの位置から角度を取得します

2つのオブジェクトがあり、一方を移動するときに、もう一方から角度を取得したいと思います。

例えば:

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

私は太陽の下で次のすべてのバリエーションを試しました:

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

しかし、45度などが必要な場合は2.949023が返されます。

この他の答えは役に立ちますか?

atan2()を度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を返します。

お役に立てれば。

44

@tomasのソリューションを合理化するように変更しました。この数学は頻繁に呼び出される可能性があります(私にとってはそうだった)。

私の化身では、2つのポイントの違いを自分で実行する必要があります(または、運が良ければ、(0,0)はすでにポイントの1つです)。計算される値は、(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_から_p1_を減算します(_p0_ --_p0_ = {0,0})。平面が平行移動されても角度は変更されません。)

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

ccpSubはcocos2dによって提供されます。これはタプルの減算です。使用可能なものがない場合は、自分で行うことができます。

余談ですが、関数をCoreGraphicsの一部として識別する_CG____命名スキームを使用して、上記のようにメソッドに名前を付けるのは一般的に礼儀正しいスタイルではありません。したがって、名前をMyConvertCGPointToBearing()に変更する場合はまたはFredLovesWilma()それならあなたはそれをするべきです。

12
bshirley

これが私がSwiftに興味のある人のためにそれをしている方法です、それはキャレイヤー回転システムに一致するのを助けるためにいくつかの修正を加えた上記の@bshirleyの答えに基づいています:

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
10
Logan

2点間に角度はありません。原点(0,0)からオブジェクトまでのベクトル間の角度を知りたい場合は、スカラー(ドット)積を使用します。

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

使用している言語のmathstd libは、アーカスコサイン、スカラー積、および長さの関数を確実に提供します。

1
Hyperboreus

角度の頂点は点(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)) )
0