将 K 个共面点旋转到平行于 x,y 平面的平面 [英] Rotate K coplanar points to a plane parallel to x,y plane
问题描述
我正在使用带有 3D 几何图形的 php(这不是最佳选择,我知道...).我有 K 个共面 3D 点,也有 x、y、z 值.它们一起形成一个多边形.我需要对这个多边形进行三角测量.我已经有一个适用于 2D 多边形的工作 delaunay traingulation 函数.所以我想旋转给定的点,使它们位于平行于 x,y 平面的平面上.之后,我可以使用 x,y 值对其进行三角剖分.下面的伪代码将描述我想如何达到这个目标.
I'm working in php with 3D geometries(not the best choice,I know...). I have K coplanar 3D points, also with x,y,z value. Together they form a polygon. I need to triangulate this polygon. I have already a working delaunay traingulation function which works for 2D Polygons. So I want to rotate the given points, so that they lay on a plane parallel to the x,y plane. After that I can triangulated it using the x,y values. The following pseudocode shall describe how I want to get to this goal.
我参考此构建了以下代码(我使用了从 OP 接受的答案):https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d,但它不像我预期的那样工作.为了知道它是否有效,每个映射点都应具有相同的z"值.这是问题,我如何获得正确的旋转矩阵?还是我在概念上犯了一个错误?
I build up the following code with reference on this (I'm usign the answer accepted from the OP): https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d, but it doesn't work as I expected. In order to know if it worked, every mapped point shall then have the same 'z' value. Here is the question, how do I get the correct rotation matrix? Or did I made a conceptual mistake?
function matrixRotationMapping(Point $p, Point $q, Point $r)
{
$normalPolygon =calculatePlaneNormal($p, $q, $r);
$v = crossProduct($normalPolygon, new Point(0, 0, 1));
$c = dotProduct($normalPolygon, new Point(0, 0, 1));
$matrix = buildRotationMatrix($v, $c);
return $matrix;
}
function buildRotationMatrix($v, $c)
{
$R2 = new Matrix(array(array(1, -$v->z, $v->y), array($v->z, 1, -$v->x), array(-$v->y, $v->x, 1)));
$costant = 1/(1+$c);
$R3 = multiplyMatrices($R2, $R2);
$R3 = multiplyMatricesWithFactor($R3, $costant);
$finalMatrix = sumMatrices($R2, $R3);
return $finalMatrix;
}
function calc2DMapping($points)
{
$rotationMatrix = matrixRotationMapping($points[0], $points[1], $points[2]);
foreach($points as $point)
{
$mappedPoint = $rotationMatrix->multiplyWithPoint($point);
$mappedPoints[] = new MappedPoint($mappedPoint);
}
}
我发现了另一个有用的问题描述,但我无法实现它:将坐标从法向量给出的平面映射到 XY 平面
I found another helpful description of the problem, but I wasn't able to implement it: Mapping coordinates from plane given by normal vector to XY plane
预先感谢您的关注.
推荐答案
你首先需要基向量 X,Y,Z
.因此,让我们首先从您的数据集中取中点 A
和两个远处的点 B,C
(不是单行).X,Y
应该在平面上,Z
应该与平面垂直,所以:
You need basis vectors X,Y,Z
first. So let take the mid point A
and two distant points to it B,C
(not on single line) from your data set first. The X,Y
should lie in the plane and Z
should be normal to it so:
X = B-A // any non zero vector inside plane
X = X / |X| // unit in size
Y = C-A // any non zero vector inside plane
(X.Y) != 0 // but not parallel to X !!!
Y = Y / |Y| // unit in size
计算点所在平面的法线并校正 Y 轴.
Compute normal to the plane your points lie in and correct Y axis.
Z = X x Y // cross product gives you perpendicular vector
Y = Z x X // now all vectors are perpendicular and unit
因此将这 3 个向量提供给 变换矩阵 的旋转部分并将原点设置为 A
.但是当您需要从数据集到平面局部坐标时,您需要逆矩阵(或使用基于转置的伪逆)
So feed these 3 vectors to rotation part of your transform matrix and set origin to A
. But as you need to go from your data set to the plane local coordinate you need inverse matrix (or use pseudo inverse based on transposing)
无论如何,现在有了基向量,您可以像这样参数化地映射您的平面:
Anyway now with the basis vectors you can map your plane parametrically like this:
P(u,v) = A + u*X + v*Y
其中 u,v = <-inf,+inf>
是在 X,Y
方向上形成 A 的表面距离.这有时会派上用场.如果你需要从 P
计算 u,v
然后利用点积:
Where u,v = <-inf,+inf>
are surface distances form A in X,Y
directions. That can get handy sometimes. If you need to compute u,v
from P
then exploit dot product:
u = ((P-A).X) = dot(P-A,X)
v = ((P-A).Y) = dot(P-A,Y)
也可用于转换为 2D 而不是使用矩阵 ...
Which can be also used to transform to 2D instead of using matrix ...
这篇关于将 K 个共面点旋转到平行于 x,y 平面的平面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!