1

次の方程式で与えられる平面を描きたい:Ax + By + Cz + D=0。私は最初にx、yを設定して彼を描画しようとし、次に方程式からzを取得しました。0x + 0y + z + 0 = 0などの平面があるため、これはうまく機能しませんでした。

私の現在の解決策はこれです:-無限大になる4つの座標を与えることによってZY平面上に平面を描きます。-与えられた平面(a、b、c)の法線をz軸上に置くために行われるべき回転を見つけます。-その平面がx軸上にあるために実行する必要がある平行移動を見つけます。-これらの回転とこの平行移動とは正反対の変換を行うため、
彼の代わりに飛行機を取得します。

わかった

これは素晴らしいことですが、内積などを使用して適切な数学計算を行うことができます(何度も試行されました...)。

誰かがそれが行われるべき正確な方法を理解するのを手伝ってくれるか、または私がABCDを入れて正しい変換を得る式を教えてくれますか?

4

2 に答える 2

1

次の変換行列が必要になります。

    [ x0_x y0_x z0_x o_x ]
M = [ x0_y y0_y z0_y o_y ]
    [ x0_z y0_z z0_z o_z ]
    [    0    0    0   1 ]

ここで、z0は平面の法線であり、oは平面の原点であり、x0とy0は、投影の回転とスキューを定義するz0に直交する平面内の2つのベクトルです。

次に、XY平面上の任意の点(x、y)を、次のようにして新しい平面の点(p_x、p_y、p_z)に投影できます。

(p_x, p_y, p_z, w) = M * (x, y, 0, 1)

これで、変換行列のz0は簡単になりました。これは平面の法線であり、単純にn = normalize(a,b,c)です。

ただし、残りを選択する際には、明らかにより多くの自由があります。原点の場合、もちろん平面がZ軸に平行でない限り、平面がZ軸と交差する点を取ることができます。その場合、何か他のものが必要になります。

だから例えば

if (c != 0) { //plane intersects Z axis
  o_x = 0;
  o_y = 0;
  o_z = -d/c;
}
else if (b != 0) { // plane intersects Y axis
  o_x = 0;
  o_y = -d/b;
  o_z = 0;
}
else { // plane must intersect the X axis
  o_x = -d/a;
  o_y = 0;
  o_z = 0;
}

実際には、とは異なるテストを選択することをお勧めします。(c != 0)そのテストでは、cが非常に小さいがゼロとは異なる場合でも成功するため、原点は言うまでもなく、x=0, y=0, z=10e100おそらく望ましくありません。したがって、のようないくつかのテスト(abs(c) > threshold)がおそらく望ましいです。ただし、もちろん、平面内のまったく異なる点を使用して原点を配置することもできます。おそらく、元の座標系の原点に最も近い点です。これは次のようになります。

o = n * (d / sqrt(a^2 + b^2 + c^2))

そして最後に、x0とy0を把握する必要があります。これは、z0に直交する任意の2つの線形独立ベクトルである可能性があります。

したがって、最初に、x0ベクトルのXY平面内のベクトルを選択しましょう。

x0 = normalize(z0_y, -z0_x, 0)

ここで、z0がたまたま(0、0、z0_z)の形式である場合、これは失敗するため、そのための特別なケースが必要です。

if (z0_x == 0 && z0_y == 0) {
  x0 = (1, 0, 0)
}
else {
  x0 = normalize(z0_y, -z0_x, 0)
}

最後に、スキューを望まず、y0をx0とy0の両方に直交するように選択し、外積を使用するとします。

y0 = normalize(x0_y*y0_z-x0_z*y0_y, x0_z*y0_x-x0_z*y0_z, x0_x*y0_y-x0_y*y0_x)

これで、変換行列を埋める必要があります。

免責事項:数値に浮動小数点表現を使用する場合は、適切な注意を払う必要があります。そのような場合、単純な(foo == 0)テストでは不十分です。実装を開始する前に、浮動小数点演算をよく読んでください。

編集:わかりやすくするためにいくつかの変数の名前を変更しました

于 2011-01-25T15:50:48.387 に答える
0

これはあなたが求めていることですか?

xy平面のような単純な平面を平面に変換するのはかなり簡単です。

あなたの平面はAx+By + Cz + D=0です

xy平面は単純にz=0です。つまり、A = B = D = 0であり、C=必要なものは何でもです。簡単にするために1と言います。

この形式の平面がある場合、平面の法線はベクトル(A、B、C)によって定義されます。

したがって、(0,0,1)から(A、B、C)*に移動する回転が必要です。

*これは、{A、B、C}がユニタリである場合にのみ機能することに注意してください。したがって、ABとCをそれぞれsqrt(A ^ 2 + B ^ 2 + C ^ 2)で除算する必要がある場合があります。

2つの軸を中心に回転すると、任意の方向から他の方向に移動できるため、xとyを選択します。

これは、x軸を中心にa、y軸を中心にb回転するための回転行列です。

Rx:= {{1、0、0}、{0、Cos [a]、Sin [a]}、{0、-Sin [a]、Cos [a]}}

Ry:= {{Cos [b]、0、-Sin [b]}、{0、1、0}、{Sin [b]、0、Cos [b]}}

xy平面(0,0,1)に垂直なベクトルのxを中心に回転し、続いてyを中心に回転すると、次のようになります。

Ry.Rx. {0,0,1} = {-Cos [a] Sin [b]、Sin [a]、Cos [a] Cos [b]}

これはあなたのABC値です。

すなわち

A = -Cos [a] Sin [b]

B=罪[a]

C = Cos [a] Cos [b]

ここからは簡単です。

a = aSin [B]

つまり、A = -Cos [aSin [B]] Sin [b]

Cos [aSin [x]] = sqrt(1-x ^ 2)なので:

A = -Sqrt [1-B ^ 2] * Sin [b]

b = aSin [-A / sqrt [1-B ^ 2]]

a = aSin [B](x軸を中心とした回転)

b = aSin [-A / sqrt [1-B ^ 2]](y軸を中心とした回転)

これで、回転する必要のあるx軸とy軸の周りの角度がわかりました。

この後、あなたはそれがあなたがすでに持っているものと一致するまであなたの飛行機を上下に動かす必要があります。

現在の平面(これらの2つの回転後)は、Ax + By + Cz=0になります。

必要な平面はAx+Bx + Cz + D=0です。dを見つけるために、z軸が平面と交差する場所を確認します。

つまり、Cz + D = 0-> z = -D / C

したがって、Ax + By + Cz=0のzを-D/Cで変換して、次のようにします。

Ax + By + C(z + D / C)= Ax + By + Cz + D=0。ああ、それを見てくれませんか!

回転する角度が決まったら、余分な計算をする必要はありません。

2つの角度でA、B、Cが得られます。Dを取得するには、持っていたものからコピーするだけです。

それがお役に立てば幸いですが、実際に飛行機を描く計画がどのようになっているのか完全にはわかりません...

いくつかの恐ろしいフォーマットを修正するために編集されました。うまくいけば、今は良くなっています。

于 2011-01-25T15:20:02.660 に答える