按所需顺序对一组共面3d点进行排序

时间:2016-09-30 16:54:57

标签: c++ sorting 3d

我有一组三维点,都在同一个平面上。这些要点只是" x y z"文本文件中的条目。 我想找到一种方法来对这些点进行排序,以便我可以通过所有点绘制一个简单的多边形。我有几个想法:

想法1:选择一个已知位于由该组点定义的多边形内的点,并将光线绘制到该集合中的任意点。然后使用某种角度函数找到最接近的点按角度到第一个点,然后依此类推。这个想法的问题在于我不知道如何找到一个保证在该区域内的点。我想使用质心,但并非所有这些都是凸的。它们可能看起来像以下两个图像之一:

enter image description here

正如你在第二张图片中看到的那样,质心可能不在多边形内,实际上如果拐角处的转折点太陡,那么我想到的角度函数也可能不起作用。

想法2:这似乎是根据旅行推销员问题可以解决的更容易解决的问题之一。但是我知道解决TSP有很多不同的特殊解决方案和近似值,我对从哪里开始有点生疏。

想法3:使用一个简单的距离函数,该函数以任意点开始并找到最接近它的点,然后找到最接近那等等。这似乎是最容易做到的事情,但我想知道我是否不会怀疑任何出现的问题。

我很感激任何关于解决这个问题的最佳方法的输入,以及我是否忽略了一个更简单的方法。我用C ++编程,所以另一个好的答案将包括可以执行诸如查找3d质心或解决TSP等问题的库或函数。提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

这是一个棘手的问题如果你添加约束,凹/凸间隙总是更大,那么任何2个相邻点之间的最大距离

gaps

然后你应该:

  1. 为每个点添加2个索引

    我会用点存储这样的东西:

    struct point
     {
     float x,y,z; // point coordinates
     int i0,i1; // index to 2 closest neighbors
     int tmp; // temp for computation purposes 
     };
    point pnt[n]; // n is number of points you got
    

    并清除它们i0,i1=-1;最好还添加临时变量,以便在后续处理过程中获得标志空间

  2. 找到最近邻居

    因此,对于每个点,遍历所有点并记住2个最接近的点。将其索引设置为i0,i1。请注意这是O(n^2),除非您的积分是空间有序的。我觉得这样:

    for (i=0;i<n;i++) pnt[i].tmp=0;
    for (i=0;i<n;i++)
     {
     i0=-1; l0=-1;
     i1=-1; l1=-1;
     for (j=0;j<n;j++)
      if (i!=j)
       {
       x=pnt[i].x-pnt[j].x; x*=x;
       y=pnt[i].y-pnt[j].y; y*=y;
       z=pnt[i].z-pnt[j].z; z*=z;
       l=x+y+z;
            if ((l0<0.0)||(l<=l0)) { i1=i0; l1=l0; i0=j; l0=l; }
       else if ((l1<0.0)||(l<=l1)) {               i1=j; l1=l; }
       }
     pnt[i].i0=i0; pnt[i0].tmp++;
     pnt[i].i1=i1; pnt[i1].tmp++;
     }
    

    现在所有有效积分的i0,i1>=0temp==2。所有的点应该是有效的,如果没有那么约束没有得到满足,或者你错误地对点进行分组(点的一侧是高密度,另一侧是低,所以两个邻居都在一边)

    < / LI>
  3. 形成折线

    所以从您找到的第一个有效点开始,并将其用作折线/多边形的第一个点。然后查看使用其i0依此类推,直到您点击起点或无效i0。这样的事情(假设所有点都有效):

     for (i0=0,i=0;;i++)
      {
      if (i<0) break; // not valid point
      // here add pnt[i] to polyline
      i=pnt[i].i0;
      if (i==i0) break; // end of polyline/polygon
      }
    
  4. 如果您还得到了无效点,那么您应该在剩余的点(不包括已经有效的点)上递归执行此操作,并且还使用一些距离的最大限制,这样您就不会合并彼此不属于的点。在此之后你应该得到很少的折线,所以如果它们的端点很接近就加入它们......

    要改善#2 ,您可以添加相邻方向不相似但可能影响锐边的条件。

    如果没有任何帮助,您可以使用凸包,然后删除与您的采样点(凹陷部分)不对应的所有顶点,并递归地执行缺少的部分。最后将折线连接到单个多边形