画一架飞机

时间:2011-01-25 14:26:19

标签: math graphics planerotation

我想绘制一个由等式给出的平面:Ax + By + Cz + D = 0。 我首先尝试通过设置x,y来绘制他,然后从等式中得到z。这不能正常工作,因为有一些平面,如0x + 0y + z + 0 = 0等......

我目前的解决方案是: - 通过给出无限远的4个坐标在ZY平面上绘制平面。 - 找出应该完成的旋转,以便使给定平面(a,b,c)的法线平躺   在z轴上。 - 找到应该完成的平移,以使该平面位于x轴上。 - 对这些旋转进行完全相反的转换,然后我将得到这个转换   飞机在他的位置。

确定

这是一件很棒的事情,但我可以使用点积等进行正确的数学计算(尝试了很多次......)。

有人可以帮助我理解它应该做的确切方式吗?或者给我一些公式,我将把它放到ABCD并获得正确的转换?

2 个答案:

答案 0 :(得分: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非常小但只是与零不同,导致您的原点是,{{{ 1}}这可能是不可取的。所以像x=0, y=0, z=10e100这样的测试可能更可取。然而,您当然可以在平面中采用完全不同的点来放置原点,也许是最接近原始坐标系原点的点,即:

(abs(c) > threshold)

然后最后我们需要弄清楚x0和y0。这可能是任何两个与z0正交的线性无关矢量。

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

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

现在,如果您的z0恰好是(0,0,z0_z)形式,则会失败,因此我们需要一个特殊情况:

x0 = normalize(z0_y, -z0_x, 0)

最后让我们说我们不要歪斜并选择y0与x0和y0正交,然后使用交叉产品

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

现在你需要填写转换矩阵。

免责声明:对您的号码使用浮点表示时应该采取适当的措施,在这些情况下,简单(foo == 0)测试是不够的。在开始实现之前,请先阅读浮点数学。

编辑:为了清晰起见重命名了一些变量

答案 1 :(得分: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}是单一的时,这才有效。所以你可能需要将A B和C除以sqrt(A ^ 2 + B ^ 2 + C ^ 2)。

只旋转两个轴可以让你从任何方向到任何其他方向,所以我们将选择x和y;

这里是旋转矩阵,用于围绕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]}

这是你的A B C值。

A = -Cos [a] Sin [b]

B = Sin [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

因此,我们将Ax + By + Cz = 0中的z转换为-D / C,得到:

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

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

这两个角度会给你A,B和C.要获得D你只需从你拥有的那里复制它。

希望能提供一些帮助,但我并不完全确定你计划如何实际绘制飞机......

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