Math 展开三维凸多边形

Math 展开三维凸多边形,math,3d,geometry,Math,3d,Geometry,我有一个由点和三角形组成的凸多面体(三角形的法线在多边形之外): 输入结构为: class Vector { float X, Y, Z; }; class Triangle { int pointIndexes[3]; Vector normal; }; class Polyhedron{ vector<Vector> points; vector<Triangle> triangles; }; 类向量{ 浮动X,Y,Z; }; 阶级三角{ in

我有一个由点和三角形组成的凸多面体(三角形的法线在多边形之外):

输入结构为:

class Vector {
  float X, Y, Z;
};
class Triangle {
  int pointIndexes[3];
  Vector normal;
};
class Polyhedron{
  vector<Vector> points;
  vector<Triangle> triangles;
};
类向量{
浮动X,Y,Z;
};
阶级三角{
int点索引[3];
向量正态分布;
};
类多面体{
矢量点;
矢量三角形;
};
我想通过沿三角形法线移动一定距离来扩展多边形。 如何计算性能良好的移动点的新三维坐标

=>我在O(n^3)中有一个实现:我沿着法线移动所有平面(三角形),然后通过测试所有平面的交点(3个不平行的平面给出一个交点)找到所有点。此解决方案可以工作,但会产生非常糟糕的性能结果


=>我还尝试将该点按顺序移动到他所附着三角形的所有法线,但没有给出正确的结果。

我很好奇,所以我尝试在C++中编写此代码。以下是一些见解:

  • 结构

    struct\u pnt
    {
    int i0,i1,i2;//相邻三角形(非平行)
    双位置[3];//位置
    _pnt(){}
    _pnt(_pnt&a){*this=a;}
    ~\u pnt(){}
    _pnt*运算符=(常量pnt*a){*this=*a;返回this;}
    //_pnt*运算符=(常量pnt&a){…复制…返回此;}
    };
    结构工厂
    {
    int i0,i1,i2;//三角形
    双nor[3];//正常
    双中点[3],d;//中点x,y,z和法线d
    _fac(){}
    _fac(_fac&a){*this=a;}
    ~\u fac(){}
    _fac*运算符=(常量fac*a){*this=*a;返回this;}
    //_fac*运算符=(常量fac&a){…复制…返回此;}
    };
    
    因此,我在每个点上添加了3个相邻非平行三角形的索引
    i0、i1、i2
    。我还添加了每个三角形的
    mid
    点和
    d
    法线偏移,以加快计算速度,但这两个都可以在需要时进行计算,因此不需要将它们添加到网格本身

  • 预计算

    因此,您需要为每个采用
    O(n)
    的面预先计算
    nor、d、mid
    ,假设
    n
    三角形和
    m
    点。每个点的邻接指数都是在
    O(m)
    中计算的,所以整个过程就是
    O(n+m)
    邻接指数的计算很容易首先清除所有点的
    i0,i1,i2
    。然后循环遍历所有面,如果法线少于3条且没有法线与之平行,则为每个面将其索引添加到其每个点

  • 偏移量

    现在只需通过对所有面重新计算
    d
    ,通过
    normal*offset\u步骤对
    mid
    点进行偏移即可完成偏移。之后,你们循环通过所有的点,并计算你们得到的3个平面的交点。这也是O(n+m)

    我懒得推导求交方程,所以我用了3x3逆矩阵。由于我的矩阵是4x4,最后一行和最后一列未使用。注意我的矩阵像OpenGL一样,所以它们是转置的。。。这就是法线被如此奇怪地加载到其中的原因

  • <强>这里我的C++源:< /强>

    //---------------------------------------------------------------------------
    结构
    {
    int i0,i1,i2;//相邻三角形(非平行)
    双位置[3];//位置
    _pnt(){}
    _pnt(_pnt&a){*this=a;}
    ~\u pnt(){}
    _pnt*运算符=(常量pnt*a){*this=*a;返回this;}
    //_pnt*运算符=(常量pnt&a){…复制…返回此;}
    };
    //---------------------------------------------------------------------------
    结构工厂
    {
    int i0,i1,i2;//三角形
    双nor[3];//正常
    双中点[3],d;//中点x,y,z和法线d
    _fac(){}
    _fac(_fac&a){*this=a;}
    ~\u fac(){}
    _fac*运算符=(常量fac*a){*this=*a;返回this;}
    //_fac*运算符=(常量fac&a){…复制…返回此;}
    };
    //---------------------------------------------------------------------------
    类网格
    {
    公众:
    列表pnt;
    列表fac;
    网格(){}
    网格(网格&a){*this=a;}
    ~mesh(){}
    mesh*运算符=(常量mesh*a){*this=*a;返回this;}
    //mesh*运算符=(常量mesh&a){…复制…返回此;}
    void二十面体(双r)//半径为r的二十面体的初始网格
    {
    //要点
    双a=r*0.525731112119133606;
    双b=r*0.850650883520392;
    _pnt p;p.i0=-1;p.i1=-1;p.i2=-1;pnt.num=0;
    向量(p.pos,-a,0.0,b);pnt.add(p);
    向量(p.pos,a,0.0,b);pnt.add(p);
    向量(p.pos,-a,0.0,-b);pnt.add(p);
    向量(p.pos,a,0.0,-b);pnt.add(p);
    向量(p.pos,0.0,b,a);pnt.add(p);
    向量ld(p.pos,0.0,b,-a);pnt.add(p);
    向量(p.pos,0.0,-b,a);pnt.add(p);
    向量(p.pos,0.0,-b,-a);pnt.add(p);
    向量(p.pos,b,a,0.0);pnt.add(p);
    向量ld(p.pos,-b,a,0.0);pnt.add(p);
    向量ld(p.pos,b,-a,0.0);pnt.add(p);
    向量ld(p.pos,-b,-a,0.0);pnt.add(p);
    //三角形
    _fac f;fac.num=0;向量(f.nor,0.0,0.0);
    f、 i0=0;f.i1=4;f.i2=1;因子加(f);
    f、 i0=0;f.i1=9;f.i2=4;因子加(f);
    f、 i0=9;f.i1=5;f.i2=4;因子加(f);
    f、 i0=4;f.i1=5;f.i2=8;因子加(f);
    f、 i0=4;f.i1=8;f.i2=1;因子加(f);
    f、 i0=8;f.i1=10;f.i2=1;因子加(f);
    f、 i0=8;f.i1=3;f.i2=10;因子加(f);
    f、 i0=5;f.i1=3;f.i2=8;因子加(f);
    f、 i0=5;f.i1=2;f.i2=3;因子加(f);
    f、 i0=2;f.i1=7;f.i2=3;因子加(f);
    f、 i0=7;f.i1=10;f.i2=3;因子加(f);
    f、 i0=7;f.i1=6;f.i2=10;因子加(f);
    f、 i0=7;f.i1=11;f.i2=6;因子加(f);
    f、 i0=11;f.i1=0;f.i2=6;因子加(f);
    f、 i0=0;f.i1=1;f.i2=6;因子加(f);
    f、 i0=