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 正交的两个向量,它们定义了投影的旋转和倾斜。

然后,您的 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 正交的任意两个线性独立向量。

所以首先,让我们在 XY 平面中为我们的 x0 向量选择一个向量:

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)。

仅围绕其中两个轴旋转可以使您从任何方向转到任何其他方向,因此我们将选择 x 和 y;

这里是 a 绕 x 轴旋转和 b 绕 y 轴旋转的旋转矩阵。

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]}}

如果我们绕 x 旋转,然后绕 y 旋转垂直于 xy 平面的向量 (0,0,1),我们得到:

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

这是你的 ABC 值。

IE

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 轴的角度。

在此之后,您只需向上或向下移动您的飞机,直到它与您已有的飞机相匹配。

您现在拥有的平面(在这两次旋转之后)将是 Ax+By+Cz=0。

你想要的飞机是Ax+Bx+Cz+D=0。要找出 d,我们将查看 z 轴与您的平面相交的位置。

即 Cz+D=0 -> z = -D/C

因此,我们通过 -D/C 将您的 z 在 Ax+By+Cz=0 中转换为:

Ax+By+C(z+D/C) = Ax+By+Cz+D=0。哦,你会看那个!

事实证明,一旦你有了旋转的角度,你就不必做任何额外的数学运算了!

这两个角度将为您提供 A、B 和 C。要获得 D,您只需从已有的内容中复制它。

希望这对您有所帮助,但我不完全确定您打算如何实际绘制飞机...

编辑以修复一些可怕的格式。希望现在好多了。

于 2011-01-25T15:20:02.660 回答