将三维平面上的点转换为二维坐标

12

我有一个点云,所有的点都在三维空间中的一个平面上。我需要将每个点转换为二维坐标和反向转换。

坐标系A中的(x,y,z) => 转换矩阵(T1) => 坐标系B中的(x,y)

坐标系B中的(x,y) => 转换矩阵(T2) => 坐标系A中的(x,y,z)

我需要T1T2。 坐标系B可以是任意的参考框架。


你是在谈论将点投影到屏幕上吗?这个3D平面是否具有随机旋转、平移和/或缩放,还是静态的? - TomTsagk
1
不,我不是在谈论投影。假设我们有一些点位于三维平面上。这个平面可以任意旋转、平移。 - Ujjwal
2个回答

18

据我所知,所有点都在同一平面上,您想要降低维度,然后恢复坐标。

获取三个非共线点A、B、C。构建向量AB和AC。
该平面的法向量是

 N = AB x AC //cross product

现在对向量AB和N进行归一化,得到单位向量U = uABuN。构建第二个基向量(它是单位向量并且位于平面内)

 V = U x uN

现在你有四个基础点 A,u = A + U,v = A + V,n = A + uN

变换应将这些点相应地映射到四元组(0,0,0), (1,0,0), (0,1,0), (0,0,1)

现在关于仿射变换矩阵用于进行此映射:

      [Ax ux vx nx]   [0 1 0 0]
 M *  [Ay uy vy ny] = [0 0 1 0]
      [Az uz vz nz]   [0 0 0 1]
      [1  1  1  1 ]   [1 1 1 1]

或者

  M * S = D
  M * S * Sinv = D * Sinv
  M = D * Sinv

计算矩阵S=[Ax ux...]的逆矩阵,得到所需矩阵M。

将矩阵M应用于平面中的任意一点,可得到具有零z分量的新坐标。

将矩阵M的逆矩阵应用于(x,y,0),可在给定平面中得到3D坐标。


Maple表格显示出点A=1,1,1 B=2,1,1 C=1,1,2(在平面Y=1上)

新坐标AA、BB、CC都具有零z分量。

对于同一平面中的任意点,在映射后的z分量也为零。

 P:=vector([-2,1,7,1]);
 > PP := multiply(M, P);
 PP := [-3, 6, 0, 1]

那样做会改变原始点的几何形状。举个例子,原始点的凸包将与投影点不同。我不想要任何剪切效果,尽管投影点的比例可以不同。 - Ujjwal
好的,所以您需要定义平面上的坐标系。选择两个任意点作为原点O和U方向向量,令V方向为-cross(U, Normal),并在U-V基础上表示点坐标。 - MBo
那么我可能需要计算这个本地坐标系和原始3D点所在的坐标系之间的转换? - Ujjwal
是的,我稍后会写关于矩阵计算的内容。 - MBo
查看新描述 - MBo
谢谢,伙计,这正是我在寻找的。 - Ujjwal

0
为了帮助澄清在Visual Studio和DxMath中从3D到2D再从2D到3D的转换过程,以及将3D坐标变换到2D坐标的过程。例如,在3D世界中使用2D三角剖分算法。

XMVECTOR pt1;  // A
XMVECTOR pt2;  // B
XMVECTOR pt3;  // C

pt1 = XMLoadFloat3((const XMFLOAT3*) &lpPoints[0]);
pt2 = XMLoadFloat3((const XMFLOAT3*) &lpPoints[1]);
pt3 = XMLoadFloat3((const XMFLOAT3*) &lpPoints[2]);

TRACE("A = [  %g    %g    %g  ]  \n", XMVectorGetX(pt1), XMVectorGetY(pt1), XMVectorGetZ(pt1));
TRACE("B = [  %g    %g    %g  ]  \n", XMVectorGetX(pt2), XMVectorGetY(pt2), XMVectorGetZ(pt2));
TRACE("C = [  %g    %g    %g  ]  \n", XMVectorGetX(pt3), XMVectorGetY(pt3), XMVectorGetZ(pt3));

XMVECTOR AB = XMVectorSubtract(pt2, pt1);
TRACE("AB = [  %g    %g    %g  ]  \n", XMVectorGetX(AB), XMVectorGetY(AB), XMVectorGetZ(AB));

XMVECTOR AC = XMVectorSubtract(pt3, pt1);
TRACE("AC = [  %g    %g    %g  ]  \n", XMVectorGetX(AC), XMVectorGetY(AC), XMVectorGetZ(AC));

XMVECTOR N = XMVector3Cross(AB, AC);
XMVECTOR Nnormal = XMVector3Normalize(N);
XMVECTOR ABnormal = XMVector3Normalize(AB);
XMVECTOR V = XMVector3Cross(ABnormal, Nnormal);

TRACE("Nnormalized =  [  %g    %g    %g  ]  \n", XMVectorGetX(Nnormal), XMVectorGetY(Nnormal), XMVectorGetZ(Nnormal));
TRACE("ABnormalized = [  %g    %g    %g  ]  \n", XMVectorGetX(ABnormal), XMVectorGetY(ABnormal), XMVectorGetZ(ABnormal));
TRACE("V=AB cross N = [  %g    %g    %g  ]  \n\n", XMVectorGetX(V), XMVectorGetY(V), XMVectorGetZ(V));

XMMATRIX D;
D._11 = 0;
D._12 = 1.0F;
D._13 = 0;
D._14 = 0;
D._21 = 0;
D._22 = 0;
D._23 = 1.0F;
D._24 = 0;
D._31 = 0;
D._32 = 0;
D._33 = 0;
D._34 = 1.0F;
D._41 = 1.0F;
D._42 = 1.0F;
D._43 = 1.0F;
D._44 = 1.0F;

XMMATRIX S;
S._11 = XMVectorGetX(pt1);
S._12 = XMVectorGetX(pt1) + XMVectorGetX(ABnormal);
S._13 = XMVectorGetX(pt1) + XMVectorGetX(V);
S._14 = XMVectorGetX(pt1) + XMVectorGetX(Nnormal);
S._21 = XMVectorGetY(pt1);
S._22 = XMVectorGetY(pt1) + XMVectorGetY(ABnormal);
S._23 = XMVectorGetY(pt1) + XMVectorGetY(V);
S._24 = XMVectorGetY(pt1) + XMVectorGetY(Nnormal);
S._31 = XMVectorGetZ(pt1);
S._32 = XMVectorGetZ(pt1) + XMVectorGetZ(ABnormal);
S._33 = XMVectorGetZ(pt1) + XMVectorGetZ(V);
S._34 = XMVectorGetZ(pt1) + XMVectorGetZ(Nnormal);
S._41 = 1.0F;
S._42 = 1.0F;
S._43 = 1.0F;
S._44 = 1.0F;

TRACE("S           =  [  %g    %g    %g    %g  ]  \n", S._11, S._12, S._13, S._14);
TRACE("               [  %g    %g    %g    %g  ]  \n", S._21, S._22, S._23, S._24);
TRACE("               [  %g    %g    %g    %g  ]  \n", S._31, S._32, S._33, S._34);
TRACE("               [  %g    %g    %g    %g  ]  \n\n", S._41, S._42, S._43, S._44);

TRACE("D           =  [  %g    %g    %g    %g  ]  \n", D._11, D._12, D._13, D._14);
TRACE("               [  %g    %g    %g    %g  ]  \n", D._21, D._22, D._23, D._24);
TRACE("               [  %g    %g    %g    %g  ]  \n", D._31, D._32, D._33, D._34);
TRACE("               [  %g    %g    %g    %g  ]  \n\n", D._41, D._42, D._43, D._44);

XMMATRIX Sinv;
XMVECTOR det;
Sinv = XMMatrixInverse(&det, S);

TRACE("Sinv        =  [  %g    %g    %g    %g  ]  \n", Sinv._11, Sinv._12, Sinv._13, Sinv._14);
TRACE("               [  %g    %g    %g    %g  ]  \n", Sinv._21, Sinv._22, Sinv._23, Sinv._24);
TRACE("               [  %g    %g    %g    %g  ]  \n", Sinv._31, Sinv._32, Sinv._33, Sinv._34);
TRACE("               [  %g    %g    %g    %g  ]  \n\n", Sinv._41, Sinv._42, Sinv._43, Sinv._44);

XMMATRIX M;
M = XMMatrixMultiply(D, Sinv); 

TRACE("M           =  [  %g    %g    %g    %g  ]  \n", M._11, M._12, M._13, M._14);
TRACE("               [  %g    %g    %g    %g  ]  \n", M._21, M._22, M._23, M._24);
TRACE("               [  %g    %g    %g    %g  ]  \n", M._31, M._32, M._33, M._34);
TRACE("               [  %g    %g    %g    %g  ]  \n\n", M._41, M._42, M._43, M._44);

M = XMMatrixTranspose(M);  // DxMath, without this XMVector4Transform below won't work

XMMATRIX Minverse;
Minverse = XMMatrixInverse(&det, M);

list<MyPoly> testpolys;

MyPoly polystwod;
polystwod.Init(nPoints);
XMVECTOR twod;
for (int p = 0; p < nPoints; p++)
{
    XMVECTOR pt = XMLoadFloat3((const XMFLOAT3*)&lpPoints[p]);
    pt = XMVectorSetW(pt, 1.0F);
    twod = XMVector4Transform(pt, M);
    TRACE("Initial   %g   %g    %g    ", XMVectorGetX(pt), XMVectorGetY(pt), XMVectorGetZ(pt));
    TRACE("Initial * M =  %g   %g    %g \n", XMVectorGetX(twod), XMVectorGetY(twod), XMVectorGetZ(twod));
    // pass 2D data
    polystwod[p].x = XMVectorGetX(twod);
    polystwod[p].y = XMVectorGetY(twod);

}
testpolys.push_back(polystwod);

// pass to your 2d triangulation routine
// then back solve 2d points into the original 3d coordinate system

XMVECTOR threed;

list<MyPoly>::iterator iter;
for (iter = testpolys.begin(); iter != testpolys.end(); iter++)
{
    MyPoly w;
    w = *iter;
    ThreeFloats w3;
    int i, cntpoints;
    cntpoints = w.GetSize();
    for (i = 0; i < cntpoints; i++)
    {
        w3.X = w[i].x;  // initialize a 2d point 
        w3.Y = w[i].y;
        w3.Z = 0.0F;
        XMVECTOR pt = XMLoadFloat3((const XMFLOAT3*)&w3);  pt = XMVectorSetW(pt, 1.0F);
        threed = XMVector4Transform(pt, Minverse);
        TRACE("Back Solving Back    %g   %g    %g    ", w3.X, w3.Y, w3.Z);
        TRACE("Back * Minverse =    %g   %g    %g   \n", XMVectorGetX(threed), XMVectorGetY(threed), XMVectorGetZ(threed));
        // variable threed is now back in original 3d coordinate system 
    }
}


IMMEDIATE WINDOW OUTPUT



A = [  0.3    -0.45    0.5  ]  
B = [  0.1    -0.45    0.5  ]  
C = [  -0.1    0.15    0.5  ]  
AB = [  -0.2    0    0  ]  
AC = [  -0.4    0.6    0  ]  
Nnormalized =  [  0    0    -1  ]  
ABnormalized = [  -1    0    0  ]  
V=AB cross N = [  -0    -1    -0  ]  

S           =  [  0.3    -0.7    0.3    0.3  ]  
               [  -0.45    -0.45    -1.45    -0.45  ]  
               [  0.5    0.5    0.5    -0.5  ]  
               [  1    1    1    1  ]  

D           =  [  0    1    0    0  ]  
               [  0    0    1    0  ]  
               [  0    0    0    1  ]  
               [  1    1    1    1  ]  

Sinv        =  [  1    1    1    0.65  ]  
               [  -1    0    0    0.3  ]  
               [  0    -1    0    -0.45  ]  
               [  0    0    -1    0.5  ]  

M           =  [  -1    0    0    0.3  ]  
               [  0    -1    0    -0.45  ]  
               [  0    0    -1    0.5  ]  
               [  0    0    0    1  ]  

Initial   0.3   -0.45    0.5    Initial * M =  0   0    0 
Initial   0.1   -0.45    0.5    Initial * M =  0.2   0    0 
Initial   -0.1   0.15    0.5    Initial * M =  0.4   -0.6    0 
Initial   0.1   0.35    0.5    Initial * M =  0.2   -0.8    0 
Initial   0.3   0.35    0.5    Initial * M =  0   -0.8    0 
Back Solving Back    0   0    0    Back * Minverse =    0.3   -0.45    0.5   
Back Solving Back    0.2   0    0    Back * Minverse =    0.1   -0.45    0.5   
Back Solving Back    0.4   -0.6    0    Back * Minverse =    -0.1   0.15    0.5   
Back Solving Back    0.2   -0.8    0    Back * Minverse =    0.1   0.35    0.5   
Back Solving Back    0   -0.8    0    Back * Minverse =    0.3   0.35    0.5   



SWAPPING Z AND X  



A = [  0.5    -0.45    0.3  ]  
B = [  0.5    -0.45    0.1  ]  
C = [  0.5    0.15    -0.1  ]  
AB = [  0    0    -0.2  ]  
AC = [  0    0.6    -0.4  ]  
Nnormalized =  [  1    0    0  ]  
ABnormalized = [  0    0    -1  ]  
V=AB cross N = [  0    -1    0  ]  

S           =  [  0.5    0.5    0.5    1.5  ]  
               [  -0.45    -0.45    -1.45    -0.45  ]  
               [  0.3    -0.7    0.3    0.3  ]  
               [  1    1    1    1  ]  

D           =  [  0    1    0    0  ]  
               [  0    0    1    0  ]  
               [  0    0    0    1  ]  
               [  1    1    1    1  ]  

Sinv        =  [  -1    1    1    1.65  ]  
               [  0    0    -1    0.3  ]  
               [  0    -1    0    -0.45  ]  
               [  1    0    -0    -0.5  ]  

M           =  [  0    0    -1    0.3  ]  
               [  0    -1    0    -0.45  ]  
               [  1    0    0    -0.5  ]  
               [  0    0    0    1  ]  

Initial   0.5   -0.45    0.3    Initial * M =  0   2.98023e-008    0 
Initial   0.5   -0.45    0.1    Initial * M =  0.2   2.98023e-008    0 
Initial   0.5   0.15    -0.1    Initial * M =  0.4   -0.6    0 
Initial   0.5   0.35    0.1    Initial * M =  0.2   -0.8    0 
Initial   0.5   0.35    0.3    Initial * M =  0   -0.8    0 
Back Solving Back    0   2.98023e-008    0    Back * Minverse =    0.5   -0.45    0.3   
Back Solving Back    0.2   2.98023e-008    0    Back * Minverse =    0.5   -0.45    0.1   
Back Solving Back    0.4   -0.6    0    Back * Minverse =    0.5   0.15    -0.1   
Back Solving Back    0.2   -0.8    0    Back * Minverse =    0.5   0.35    0.1   
Back Solving Back    0   -0.8    0    Back * Minverse =    0.5   0.35    0.3   



ANOTHER TEST CONSTANT Y



A = [  -0.9    0.25    0.3  ]  
B = [  -0.9    0.25    0.1  ]  
C = [  0.3    0.25    -0.1  ]  
AB = [  0    0    -0.2  ]  
AC = [  1.2    0    -0.4  ]  
Nnormalized =  [  0    -1    0  ]  
ABnormalized = [  0    0    -1  ]  
V=AB cross N = [  -1    -0    -0  ]  

S           =  [  -0.9    -0.9    -1.9    -0.9  ]  
               [  0.25    0.25    0.25    -0.75  ]  
               [  0.3    -0.7    0.3    0.3  ]  
               [  1    1    1    1  ]  

D           =  [  0    1    0    0  ]  
               [  0    0    1    0  ]  
               [  0    0    0    1  ]  
               [  1    1    1    1  ]  

Sinv        =  [  1    1    1    1.35  ]  
               [  0    2.98023e-008    -1    0.3  ]  
               [  -1    0    0    -0.9  ]  
               [  0    -1    0    0.25  ]  

M           =  [  0    2.98023e-008    -1    0.3  ]  
               [  -1    0    0    -0.9  ]  
               [  0    -1    0    0.25  ]  
               [  0    0    0    1  ]  

Initial   -0.9   0.25    0.3    Initial * M =  -2.23517e-008   0    0 
Initial   -0.9   0.25    0.1    Initial * M =  0.2   0    0 
Initial   0.3   0.25    -0.1    Initial * M =  0.4   -1.2    0 
Initial   0.7   0.25    0.1    Initial * M =  0.2   -1.6    0 
Initial   0.7   0.25    0.3    Initial * M =  -2.23517e-008   -1.6    0 
Back Solving Back    -2.23517e-008   0    0    Back * Minverse =    -0.9   0.25    0.3   
Back Solving Back    0.2   0    0    Back * Minverse =    -0.9   0.25    0.1   
Back Solving Back    0.4   -1.2    0    Back * Minverse =    0.3   0.25    -0.1   
Back Solving Back    0.2   -1.6    0    Back * Minverse =    0.7   0.25    0.1   
Back Solving Back    -2.23517e-008   -1.6    0    Back * Minverse =    0.7   0.25    0.3   



ONE FINAL TEST



A = [  1    1    1  ]  
B = [  2    1    1  ]  
C = [  1    1    2  ]  
AB = [  1    0    0  ]  
AC = [  0    0    1  ]  
Nnormalized =  [  0    -1    0  ]  
ABnormalized = [  1    0    0  ]  
V=AB cross N = [  0    0    -1  ]  

S           =  [  1    2    1    1  ]  
               [  1    1    1    0  ]  
               [  1    1    0    1  ]  
               [  1    1    1    1  ]  

D           =  [  0    1    0    0  ]  
               [  0    0    1    0  ]  
               [  0    0    0    1  ]  
               [  1    1    1    1  ]  

Sinv        =  [  -1    1    1    0  ]  
               [  1    0    0    -1  ]  
               [  0    0    -1    1  ]  
               [  0    -1    0    1  ]  

M           =  [  1    0    0    -1  ]  
               [  0    0    -1    1  ]  
               [  0    -1    0    1  ]  
               [  0    0    0    1  ]  

Initial   1   1    1    Initial * M =  0   0    0 
Initial   2   1    1    Initial * M =  1   0    0 
Initial   1   1    2    Initial * M =  0   -1    0 
Initial   -2   1    7    Initial * M =  -3   -6    0 
Back Solving Back    0   0    0    Back * Minverse =    1   1    1   
Back Solving Back    1   0    0    Back * Minverse =    2   1    1   
Back Solving Back    0   -1    0    Back * Minverse =    1   1    2   
Back Solving Back    -3   -6    0    Back * Minverse =    -2   1    7   


此时我看到向量方向在开始时被反转了:应该是AB = B - A,AC = C - A。它改变了AC、u、vnorm的分量符号,保留了n。但是我认为这不应该对结果产生重大影响。点A的结果(它在新坐标系中作为原点)必须是**(0,0,0)。看起来XMVector3Transform只使用了三列,重新排列了A的分量(由于后对角线上的1),但没有与右列相加**。 - MBo
你在使用4维向量A的齐次坐标 [.5 -.45 .3 1.0] 与4x4矩阵相乘吗? - MBo
Zero x AB组件与(1,0,0)无关,因为后者是新系统中的坐标。新系统有自己的方向向量。 - MBo
是的,有两个起点 - 自然起点和第二个起点是A点。这在我的回答中已经描述了:M将A映射到(0,0,0),A + U映射到(1,0,0)(因此B具有新坐标(length(AB), 0, 0)),依此类推。 - MBo
看看我的常数y平面的例子。它按照需要工作。 - MBo
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接