我有几个平面多边形,由它们在3D空间中的顶点定义。这些多边形在3维中随机旋转。
现在我想在它们自己的局部2D空间中处理这些多边形顶点中的每一个。我真的不在乎这个地方空间的中心在哪里。我只需要x& y轴与多边形法线正交。
例如,如果我有一个宽度为&n的矩形的多边形。高度1,顶点可能看起来像:
v1 = [-0.558013, -0.0334937, -0.433013]
v2 = [0.308013, 0.466506, -0.433013]
v3 = [-0.308013, -0.466506, 0.433013]
v4 = [0.558013, 0.0334937, 0.433013]
但我希望他们看起来像这样:
v1 = [0, 0]
v2 = [0, 1]
v3 = [1, 1]
v4 = [1, 0]
所以我的问题是,如何将每个顶点3D坐标转换为局部2D坐标?
答案 0 :(得分:7)
首先考虑多边形p0
,p1
和p2
的三个非共线点,然后计算
loc0 = p0 # local origin
locx = p1 - loc0 # local X axis
normal = cross(locx, p2 - loc0) # vector orthogonal to polygon plane
locy = cross(normal, locx) # local Y axis
其中cross
是叉积运算符:
def cross(a, b):
return P3d(a.y*b.z - a.z*b.y,
a.z*b.x - a.x*b.z,
a.x*b.y - a.y*b.x)
然后规范化计算的局部轴locx
和locy
locx /= locx.length()
locy /= locy.length()
最后点的本地坐标只是
local_coords = [(dot(p - loc0, locx), # local X coordinate
dot(p - loc0, locy)) # local Y coordinate
for p in points]
其中dot
是标量乘积运算符:
def dot(a, b):
return a.x*b.x + a.y*b.y + a.z*b.z
要从本地坐标(Lx, Ly)
返回到3D,转换是
p = loc0 + Lx*locx + Ly*locy
答案 1 :(得分:3)
对于一个多边形,您需要在多边形平面中找到局部2D基础,并在此2D基础上投影多边形的每个顶点的3D坐标以获得2D坐标。在下文中,我还假设您正在寻找正交二维基础(多边形平面上的单位长度和正交二维基矢量)。
一步一步:
计算多边形的(单位)法线n,假设顶点确实是共面的,
获取多边形的第一条边并使用它来定义2D基础的第一个轴u(单位矢量),
使用u和n(v = n x u)
在(u,v,n)3D基础上投影每个顶点,这将在多边形平面中给出其2D坐标。
例如,使用以下具有五个顶点的多边形:
M1 +----+ M3
| \
| + M4
| /
M2 +----+ M5
其中M1
有3D坐标v1 = (x1, y1, z1)
而M2
有3D坐标v2 = (x2, y2, z2)
等等......
与飞机垂直的单位为:n = (v2 - v1) x (v3 - v1) / |(v2 - v1) x (v3 - v1)|
2D基础的第一个轴是:u = (v2 - v1) / |(v2 - v1)|
2D基础的第二个轴是:v = n x u
获取多边形的顶点(或多边形平面中的任意点),例如M5
。
然后,它的3D坐标可以(u, v, n)
基础与原始v1
一起编写。
v5 = v1 + r5 * u + s5 * v + t5 * n
( ) ( r5 ) ( xu xv xn ) ( r5 ) ( ) ( r5 )
v5 - v1 = ( u v n ) ( s5 ) = ( yu yv yn ) ( s5 ) = ( B ) ( s5 )
( ) ( t5 ) ( zu zv zn ) ( t5 ) ( ) ( t5 )
其中t5
应为0(它是沿平面法线的点的坐标,因此如果该点位于多边形的平面上,则它为0)。
因此,求解(r5, s5, t5)
会产生:
( r5 ) ( u )
( s5 ) = B^-1 (v5 - v1) = B^T (v5 - v1) = ( v ) ( v5 - v1 )
( t5 ) ( n )
因为B是正交矩阵(所以B ^ -1 = B ^ T)。
最后,简单地说:
r5 = u . (v5 - v1)
s5 = v . (v5 - v1)
其中.
是矢量点积。