镶嵌点平面

时间:2012-07-24 15:47:19

标签: c++ algorithm math

我有一个填充了3d点的文件。这些点形成一个平面。这是一个示例文件:

25
1 -1 0
1 -0.5 0
1 0 0
1 0.5 0
1 1 0
0.5 -1 0
0.5 -0.5 0
0.5 0 0
0.5 0.5 0
0.5 1 0
0 -1 0
0 -0.5 0
0 0 0
0 0.5 0
0 1 0
-0.5 -1 0
-0.5 -0.5 0
-0.5 0 0
-0.5 0.5 0
-0.5 1 0
-1 -1 0
-1 -0.5 0
-1 0 0
-1 0.5 0
-1 1 0

编辑:由于我的示例点集太简单了,这里有一个更复杂的例子。

30
-0.298858 -0.816497 1.11536
0.0546949 -0.816497 0.761802
0.408248 -0.816497 0.408248
0.761802 -0.816497 0.0546949
1.11536 -0.816497 -0.298858
-0.462158 -0.489898 0.952056
-0.108604 -0.489898 0.598502
0.244949 -0.489898 0.244949
0.598502 -0.489898 -0.108604
0.952056 -0.489898 -0.462158
-0.625457 -0.163299 0.788756
-0.271904 -0.163299 0.435203
0.0816497 -0.163299 0.0816497
0.435203 -0.163299 -0.271904
0.788756 -0.163299 -0.625457
-0.788756 0.163299 0.625457
-0.435203 0.163299 0.271904
-0.0816497 0.163299 -0.0816497
0.271904 0.163299 -0.435203
0.625457 0.163299 -0.788756
-0.952056 0.489898 0.462158
-0.598502 0.489898 0.108604
-0.244949 0.489898 -0.244949
0.108604 0.489898 -0.598502
0.462158 0.489898 -0.952056
-1.11536 0.816497 0.298858
-0.761802 0.816497 -0.0546949
-0.408248 0.816497 -0.408248
-0.0546949 0.816497 -0.761802
0.298858 0.816497 -1.11536

这些点的绘制如下:

http://i.imgur.com/6zRrA.png

此文件表明飞机上有25个点,并列出了这些点。这些点是有规律的间隔。根据这些信息,我如何在点数据中形成三角形并将其存储在std::vector<Tri>中,Tri

struct Tri 
{
  double x1, y1, z1;
  double x2, y2, z2;
  double x3, y3, z3;
};

另请注意:问题限制:不允许使用外部库。不允许使用C ++ 0X(编译器:g ++ 4.5.2)。

5 个答案:

答案 0 :(得分:3)

阅读第一行,称之为N。将其余的点读入数组A

Point xdir = A[1] - A[0];
int xdim = 2;
while (A[xdim] - A[xdim-1] == xdir) xdim++;
int ydim = N / xdim;
for (int y = 0; y < ydim-1; y++) {
   for (int x = 0; x < xdim-1; x++) {
      addTriangle(A[y*xdim+x],A[(y+1)*xdim+x],A[(y+1)*xdim+(x+1)]);
      addTriangle(A[y*xdim+x],A[y*xdim+(x+1)],A[(y+1)*xdim+(x+1)]);
   }
}

当然,这假设您确实以网格顺序获得所有积分。如果没有,请先对它们进行排序。

答案 1 :(得分:0)

将平面上的网格分成一组线。通过在一条线上取每对相邻点并将相邻线中每对成员的最近点添加到该对中来给出细分。

您可以使用矢量算术将平面分成线条。将文件中的第一个点作为平面基础,将第二个点的矢量作为X轴。将矢量从第一个点投影到X轴矢量上的任意点,并使用投影的长度作为X坐标。由于您假设是常规网格,因此这些值应为0,1,2,3等,直接将点分割为线。

答案 2 :(得分:0)

也许Delaunay Triangulation可以帮到你?这个link提供了一些获取Delaunay三角剖分的算法

另一种算法是here

答案 3 :(得分:0)

对于tesselation算法,尝试创建并推动向量,相邻点的直角三角形(不重叠它们)。假设您已按正确的顺序将所有点存储在m x n矩阵中,则可以创建这组三角形:

  • {(i,j),(i+1,j),(i+1,j+1)}代表0 < i < m-10 < j < n-1
  • {(i,j+1), (i+1,j+1), (i,j)代表0 < i < m-10 < j < n-1

我使用形式{p1,p2,p3}表示三角形,使用(x,y)表示矩阵中点的索引对。在您的情况下,这些 m n 变量等于5.

答案 4 :(得分:0)

当然有许多不同的方法可以从一组顶点获取一组三角形,所以我不确定我是否理解整个问题要求。

但我的方法可能看起来像这样:

  1. 考虑到浮点舍入和/或数据准确性问题,我首先使用最小二乘拟合算法确定平面的法向量。 (虽然你不需要飞机本身,只需要方向。)

  2. 编写算法以使用该法向量来确定一些常见的平面问题,例如“三角形ABC内部的点D?”和“段AB和CD是否相交?” (在平面投影中)。

  3. 如果你有一些已知的输入结构使得从这一点开始变得容易,或者你想要使用现有的平面算法,那就太棒了。

    如果你只是想得到任何一组非重叠的三角形,那就是凸出的凸包:

    1. 从任意三个点和一个三角形开始。还要记住一个有序的顶点循环,形成到目前为止所覆盖区域的边界多边形。然后一次添加其余一个点。

    2. 如果要添加的新点位于现有三角形的内部,请将该三角形替换为三个子三角形。

    3. 否则,确定从边界多边形顶点到新点的哪些N(N> = 2)个线段不与边界多边形相交。添加(N-1)个新三角形。新点将(N-2)个旧点替换为边界多边形中的新顶点。

    4. 假设避免接近共线的三角形和不必要的长段是一件好事:在不在边界上的三角形边上循环,并检查两个相邻三角形所覆盖的四边形是否是凸的,以及是否它的另一条对角线(显着地)比正在研究的普通三角形边缘短。如果是这样,请替换这两个三角形。重复直到不再进行这样的替换。 (这个循环必须终止,因为边的总长度总是在减少,并且有一定数量的镶嵌。)