2 つの 2D ベクトルがあるとします。1 つはオブジェクトの現在の位置用で、もう 1 つはそのオブジェクトの前の位置用です。移動の角度方向をどのように計算できますか?
この画像は、私が求めているものを理解するのに役立つかもしれません:
2 つの 2D ベクトルがあるとします。1 つはオブジェクトの現在の位置用で、もう 1 つはそのオブジェクトの前の位置用です。移動の角度方向をどのように計算できますか?
この画像は、私が求めているものを理解するのに役立つかもしれません:
移動の方向ベクトルは、2 つの位置ベクトルの差になります。
d = (x1, y1) - (x, y) = (x1 - x, y1 - y)
方向角度を尋ねると、角度を測定する方向によって異なります。x軸に対してですか?Raduの答えに行きます。任意のベクトルに対して?justjeffの答えを見てください。
編集:y軸に対する角度を取得するには:
tan (theta) = (x1 -x)/(y1 - y)
角度の正接は、差分ベクトルの x 座標と差分ベクトルの y 座標の比率です。
そう
theta = arctan[(x1 - x)/(y1 - y)]
arctan は逆正接を意味します。多くの人が行う正接の逆数と混同しないでください。どちらも tan^-1 で示されることが多いからです。また、度またはラジアンで作業しているかどうかを確認してください。
C (または同じ関数セットを使用する他の言語) を使用している場合は、おそらくその関数を探しているでしょうatan2()
。あなたの図から:
double theta = atan2(x1-x, y1-y);
その角度は、マークしたように垂直軸からのもので、ラジアン(神自身の角度単位) で測定されます。
象限の問題とゼロ除算を回避するために、 atan2を使用するように注意してください。それがその目的です。
float getAngle(CGPoint ptA, CGPoint ptOrigin, CGPoint ptB)
{
CGPoint A = makeVec(ptOrigin, ptA);
CGPoint B = makeVec(ptOrigin, ptB);
// angle with +ve x-axis, in the range (−π, π]
float thetaA = atan2(A.x, A.y);
float thetaB = atan2(B.x, B.y);
float thetaAB = thetaB - thetaA;
// get in range (−π, π]
while (thetaAB <= - M_PI)
thetaAB += 2 * M_PI;
while (thetaAB > M_PI)
thetaAB -= 2 * M_PI;
return thetaAB;
}
ただし、角度が+ veか-veかを気にしない場合は、内積規則を使用してください(CPU負荷が少ない)。
float dotProduct(CGPoint p1, CGPoint p2) { return p1.x * p2.x + p1.y * p2.y; }
float getAngle(CGPoint A, CGPoint O, CGPoint B)
{
CGPoint U = makeVec(O, A);
CGPoint V = makeVec(O, B);
float magU = vecGetMag(U);
float magV = vecGetMag(V);
float magUmagV = magU * magV; assert (ABS(magUmagV) > 0.00001);
// U.V = |U| |V| cos t
float cosT = dotProduct(U, V) / magUmagV;
float theta = acos(cosT);
return theta;
}
上記のいずれかのコードセクションで、一方(または両方)のベクトルの長さが0に近い場合、これは失敗することに注意してください。だから、どういうわけかそれをトラップしたいかもしれません。
回転行列の意味はまだわかりませんが、これは方向ベクトルから方位角を取得する単純なケースです。
複雑な答え:
通常、2D ベクトルにはいくつかの変換/ユーティリティ関数をパックする必要があります。1 つは、X、Y (デカルト) から Theta、R (極座標) に変換するためのものです。また、加算、減算、内積などの基本的なベクトル演算もサポートする必要があります。この場合の答えは次のようになります。
double azimuth = (P2 - P1).ToPolarCoordinate().Azimuth;
ToPolarCoordinate() と ToCarhtesianCoordinate() は、あるタイプのベクトルから別のタイプのベクトルに切り替える 2 つの相互関数です。
シンプルなもの:
double azimuth = acos ((x2-x1)/sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));
//then do a quadrant resolution based on the +/- sign of (y2-y1) and (x2-x1)
if (x2-x1)>0 {
if (y2-y1)<0 { azimuth = Pi-azimuth; } //quadrant 2
} else
{ if (y2-y1)> 0 { azimuth = 2*Pi-azimuth;} //quadrant 4
else { azimuth = Pi + azimuth;} //quadrant 3
}