14

ベクトル B がベクトル A とベクトル C の小さな角度の間にあるかどうかを判断するための高速で効果的な方法を探しています。次の理由により、非常に単純です。

  • どのベクトルも正規化されていると想定することはできず、それらを正規化することは避けたい余分なステップです。
  • どちらが角度が小さいかという明確な概念がないので、線のどちらが良いか悪いかは一概には言えません。
  • A と B が同一線上にあるか、正確に 180 度離れている可能性があります。その場合は false を返します。
  • 私は 3D 環境で作業していますが、これを 2D に簡略化するのは簡単です。このテストは、できるだけ高速に実行する必要があるアルゴリズムで使用されます。

垂直ベクトルがどちらを指すかを決定する簡単で効率的な方法があれば、テストに 2 つの内積を使用できます。

私が検討してきた別のアプローチは、これまでのところあまり成功していませんが、マトリックスを使用することです。理論的には、マトリックス変換について理解していることから、A と C を基底ベクトルとして使用できるはずです。次に、B に行列 I を掛けると、X と Y が両方とも正であるかどうかによって、B がどの象限にあるかをテストできるはずです。このアプローチを機能させることができれば、1 つの行列乗算が 2 つの内積よりも高速であり、どちらの側が最小の角度であるかを心配する必要がないため、おそらく最適です。

問題は、私のテストでは、単純に A と C を基数として使用し、それを通常どおり乗算して正しい動作を得ることができないことです。ここで何が間違っているのか本当にわかりません。「ベクトル空間」という用語に何度か出くわしましたが、これは、直交基底または正規直交基底を必要としない行列変換と非常によく似た概念のように思えます。マトリックスと同じですか?そうでない場合、より良いアプローチがあるかもしれません。それをどのように使用しますか?

私が話していることをより視覚的に説明するために:

大まかな例

@Aki Suihkonen私はそれがうまくいかないようです。実行できるモックケースをコーディングして、何かを理解できないかどうかを確認しました

この場合、

斧 2.9579773 エイ 3.315979

Cx 2.5879822 Cy 5.1630249

4 つの象限を中心に回転する BI の場合、ベクトルは空間を分割します。

私が得た兆候: - Q1 の-- 場合 - Q2+- の場合 - Q3+- の場合 - Q4 の場合--

環境内で画像と同じ方向に回転したと仮定すると、回転したと確信しています。

象限

4

3 に答える 3

6

これを考える 1 つの方法は、これらのベクトル A、B、C をすべて複素数と見なすことです。

A、C をすべて B の複素共役である B* で乗算すると、両方の結果のベクトルが複素平面で回転するため、参照軸 (B*Conj(B)) は実軸 (または y = 0) になります。 ) -- そして、その軸を計算する必要はありません。この場合、「y」または虚数成分の符号が異なるかどうかを確認するだけで済みます。また、この場合、両方の結果のベクトルは同じ長さ |B| でスケーリングされています。

`return sign(Imag(A * Conj(B))) != sign(Imag(C * Conj(B)));`

A = ax + i * ay; B = bx + i * by; C = cx + i * cy;
Conj(B) = bx - i * by; 
A * B = (ax * bx - ay * by) + i * (ax * by + ay * bx);

乗算の虚数成分のみが必要なため、この方程式はさらに優れたパフォーマンスにつながると思います。

完全な解決策として、これは次のように変換されます。

return (ay * bx - ax * by) * (ay * cx - ax * cy) < 0;

中間の乗算は、次のショートカットです。

return Sign(ay * bx - ax * by) != Sign(ay * cx - ax * cy);

複素数がない場合、問題はベクトル B が { R cos beta, R sin beta } であると見なすこともでき、これは回転行列として表すことができます。

R*[  cb -sb ]    [ bx -by ],   cb = cos(beta), sb = sin(beta)
  [  sb  cb ] =  [ by  bx ]    cos(-beta) = cos(beta), sin(-beta) = -sin(beta)

[ax,ay], [cx,cy] にスケーリングされた行列 [bx by, -by bx] の転置を掛けると、[ax, ay] * rotMatrix(-beta), [cx, cy] * rotMatrix の長さに影響します。 (-beta) まったく同じ方法で。

于 2012-11-30T07:52:34.663 に答える
0

極座標では、 θ A < θ B < θ Cかどうかを尋ねるだけです。したがって、最初に極座標に変換します。

a_theta = ax ? atan(ay / ax) : sign(ay) * pi
于 2012-11-30T10:33:18.533 に答える