ホームページ > バックエンド開発 > C++ > 2D 空間と 3D 空間の両方で 2 つのベクトル間の時計回りの角度を効率的に計算するにはどうすればよいですか?

2D 空間と 3D 空間の両方で 2 つのベクトル間の時計回りの角度を効率的に計算するにはどうすればよいですか?

Patricia Arquette
リリース: 2024-11-21 07:44:09
オリジナル
859 人が閲覧しました

How can I efficiently calculate the clockwise angle between two vectors in both 2D and 3D space?

ベクトル間の時計回りの角度を効率的に計算する

従来、2 つのベクトル間の角度を計算するには、内積を利用して内角を決定する必要がありました。 0 ~ 180 度の範囲。ただし、このアプローチでは、角度とその補数の間の適切な結果を決定する際に課題が生じます。

時計回りの角度を計算するためのより直接的な方法はありますか?

2D ケース

内積が角度の余弦にどのように関係するのと同様に、行列式はその正弦に比例します。この関係を組み込むことで、次のように角度を計算できます。

dot = x1 * x2 + y1 * y2  # Dot product between [x1, y1] and [x2, y2]
det = x1 * y2 - y1 * x2  # Determinant
angle = atan2(det, dot)  # atan2(y, x) or atan2(sin, cos)
ログイン後にコピー
ログイン後にコピー
計算された角度の方向は、座標系の方向と一致します。 x が右を指し、y が下を指す左手座標系では、時計回りの角度は正の値を生成します。逆に、y が上を指す数学座標系では、数学では慣習的に、結果は反時計回りの角度を反映します。入力ベクトルの順序を入れ替えると符号が変更され、結果の符号を柔軟に変更できます。

3D の場合

3 次元では、任意のベクトルが独自の軸を定義します。両方に垂直な回転。この軸には固定された向きがないため、回転角度の方向を一意に決定することはできません。一般的な規則は、正の角度を割り当て、この規則に合わせて軸を揃えることです。このコンテキストでは、角度の計算には正規化されたベクトルのドット積で十分です。

dot = x1 * x2 + y1 * y2 + z1 * z2  # Between [x1, y1, z1] and [x2, y2, z2]
lenSq1 = x1 * x1 + y1 * y1 + z1 * z1
lenSq2 = x2 * x2 + y2 * y2 + z2 * z2
angle = acos(dot / sqrt(lenSq1 * lenSq2))
ログイン後にコピー
ログイン後にコピー

3D に埋め込まれた平面

既知の法線を持つ平面内に拘束されたベクトルの場合ベクトル n については、考慮すべき特定のケースがあります。回転軸は n と一致し、n の向きによって軸の向きが固定されます。このシナリオでは、行列式に n を含めるように上記の 2D 計算を変更し、それを 3x3 行列に変換できます。

dot = x1 * x2 + y1 * y2 + z1 * z2
det = x1 * y2 * zn + x2 * yn * z1 + xn * y1 * z2 - z1 * y2 * xn - z2 * yn * x1 - zn * y1 * x2
angle = atan2(det, dot)
ログイン後にコピー
この計算を有効にするには、法線ベクトル n を単位に正規化する必要があります。

あるいは、行列式をトリプルとして表すこともできます。 product:

det = n · (v1 × v2)
ログイン後にコピー
このアプローチは、一部の API では実装が簡単な場合があり、基礎となる仕組みへの洞察が得られます。外積は角度の正弦に比例し、平面に垂直です。つまり、倍数です。 nの。したがって、ドット積は、基本的に、正しい符号が適用されたベクトルの長さを測定します。

範囲 0 – 360°

ほとんどの atan2 実装は、範囲内の角度を返します。ラジアン単位の [-π, π] または度単位の [-180°, 180°]。 [0, 2π] または [0°, 360°] 以内の正の角度を取得するには、次の変換を適用できます。

dot = x1 * x2 + y1 * y2  # Dot product between [x1, y1] and [x2, y2]
det = x1 * y2 - y1 * x2  # Determinant
angle = atan2(det, dot)  # atan2(y, x) or atan2(sin, cos)
ログイン後にコピー
ログイン後にコピー

代わりに、次の式は大文字と小文字の区別を回避します。

dot = x1 * x2 + y1 * y2 + z1 * z2  # Between [x1, y1, z1] and [x2, y2, z2]
lenSq1 = x1 * x1 + y1 * y1 + z1 * z1
lenSq2 = x2 * x2 + y2 * y2 + z2 * z2
angle = acos(dot / sqrt(lenSq1 * lenSq2))
ログイン後にコピー
ログイン後にコピー

この修正手法は、この特定の問題に限定されず、atan2 が関係するあらゆるシナリオに適用できます。

以上が2D 空間と 3D 空間の両方で 2 つのベクトル間の時計回りの角度を効率的に計算するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート