我想绘制一个由等式给出的平面:Ax + By + Cz + D = 0。 我首先尝试通过设置x,y来绘制他,然后从等式中得到z。这不能正常工作,因为有一些平面,如0x + 0y + z + 0 = 0等......
我目前的解决方案是: - 通过给出无限远的4个坐标在ZY平面上绘制平面。 - 找出应该完成的旋转,以便使给定平面(a,b,c)的法线平躺 在z轴上。 - 找到应该完成的平移,以使该平面位于x轴上。 - 对这些旋转进行完全相反的转换,然后我将得到这个转换 飞机在他的位置。
确定
这是一件很棒的事情,但我可以使用点积等进行正确的数学计算(尝试了很多次......)。
有人可以帮助我理解它应该做的确切方式吗?或者给我一些公式,我将把它放到ABCD并获得正确的转换?
答案 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你只需从你拥有的那里复制它。
希望能提供一些帮助,但我并不完全确定你计划如何实际绘制飞机......
编辑修复一些可怕的格式。希望现在好多了。