11

3D 空間に一連のデータ ポイントがあり、それらはすべて特定の平面にあるようです。PCA を使用してプレーン パラメーターを計算します。PCA の 3 番目のコンポーネントは、平面の法線ベクトル (最も弱いコンポーネント) を示します。

次にやりたいことは、すべてのポイントを上記の平面に変換し、それを 2D で見ることです。

私の考えは、次のことをすることでした:

  • 平面上の中心点 (平均点) を見つける
  • すべてのデータ ポイントからそれを減算して、原点の周りに配置します
  • (0,0,-1)になるように法線を回転させます
  • この回転をすべてのデータ ポイントに適用します
  • 正射影を使用する (基本的には z 軸をスキップする)

今、私は正しい回転操作を見つけることに行き詰まっています。acos または atan を使用して、2 つの回転行列を設定してみました。両方の方法 (acos を使用、atan を使用) で間違った結果が得られるようです。ここで私を助けてくれるかもしれません!

Matlab コードは次のとおりです。

b = atan(n(1) / n(2));
rotb = [cos(b) -sin(b) 0; sin(b) cos(b) 0; 0 0 1];
n2 = n * rotb;
a = atan(n(1) / n(3));
rota = [cos(a) 0 sin(a); 0 1 0; -sin(a) 0 cos(a)];
n3 = n2 * rotaows:

n2私はゼロのy成分を持つことを期待しています。ただし、ベクトル (-0.6367、0.7697、0.0467) では既に失敗しています。

4

4 に答える 4

12

平面がある場合、法線ベクトルと原点があります。私は「回転」をまったくしません。あなたは答えから離れたほんの数ベクトル操作です。

  • 平面の法線ベクトルを新しい z 軸と呼びましょう。
  • 古い x 軸を新しい z 軸 (平面の法線) と交差させることで、新しい y 軸を生成できます。
  • 新しい z と新しい y を交差させて、新しい x 軸を生成します。
  • すべての新しい軸ベクトルを単位ベクトル (長さ 1) にします。
  • 持っているすべてのポイントについて、新しい原点からポイントまでのベクトルを作成します (ポイントのベクトル減算 - plane_origin)。新しい x と新しい y の単位ベクトルを点で打つだけで、プロットできるペア (x,y) が得られます!

交差関数と内積関数が既にある場合、これはほんの数行のコードです。私が書いたほとんどの 3D ビデオゲームがこのように機能したので、それが機能することはわかっています。

トリック:

  • ベクトルが指している方向に注意してください。それらが間違った方向を指している場合は、結果のベクトルを否定するか、外積の順序を変更します。
  • 平面の法線が元の x 軸とまったく同じである場合、問題が発生します。
于 2009-06-21T14:45:32.540 に答える
1

どうですか:

法線ベクトルを XY 平面のベクトルと Z ベクトルに分解します。次に、Z 軸を中心に回転を適用して、XY ベクトルを軸の 1 つに揃えます。次に、法線と Z 軸の内積を求め、X、Y のいずれかに沿って回転します。

アイデアは、法線ベクトルを Z に揃えることです。そうすることで、平面は XY 平面になります。

于 2009-06-21T14:27:11.050 に答える
0

他にも興味深い回答がありましたが、これは回答を待っている間に私たちが考え出した解決策です。

function roti = magic_cosini(n)
    b = acos(n(2) / sqrt(n(1)*n(1) + n(2)*n(2)));
    bwinkel = b * 360 / 2 / pi;
    if (n(1) >= 0)
        rotb = [cos(-b) -sin(-b) 0; sin(-b) cos(-b) 0; 0 0 1];
    else
        rotb = [cos(-b) sin(-b) 0; -sin(-b) cos(-b) 0; 0 0 1];
    end
    n2 = n * rotb;
    a = acos(n2(3) / sqrt(n2(2)*n2(2) + n2(3)*n2(3)));
    awinkel = a * 360 / 2 / pi;
    rota = [1 0 0; 0 cos(-a) -sin(-a); 0 sin(-a) cos(-a)];
    roti = rotb * rota;

(うまくいけば正しい二重回転行列を返します)

私たちが以前に持っていて、ここで修正した欠陥は、特にすることでした。正弦計算ではカバーされなかったX成分の符号を処理します。これにより、間違った方向に1回回転しました(180°の角度で回転)。

Nosrednaのソリューションを試す時間もあることを願っています!三角法を避けることは常に良いことです。

于 2009-06-21T15:13:04.840 に答える