C++ 排序点:凹多边形

C++ 排序点:凹多边形,c++,geometry,C++,Geometry,我有一组点,我试着从它们的角度按ccw顺序或cw顺序排序。我希望这些点的排序方式能够使它们形成一个在其区域或交点中没有分裂的多边形。这是困难的,因为在大多数情况下,它将是一个凹多边形 point centroid; int main( int argc, char** argv ) { // I read a set of points into a struct point array: points[n] // Find centroid double sx = 0; doub

我有一组点,我试着从它们的角度按ccw顺序或cw顺序排序。我希望这些点的排序方式能够使它们形成一个在其区域或交点中没有分裂的多边形。这是困难的,因为在大多数情况下,它将是一个凹多边形

point centroid;
int main( int argc, char** argv )
{
  // I read a set of points into a struct point array: points[n]

  // Find centroid
  double sx = 0; double sy = 0;
  for (int i = 0; i < n; i++)
  {
    sx += points[i].x;
    sy += points[i].y;
  }
  centroid.x = sx/n;
  centroid.y = sy/n;

  // sort points using in polar order using centroid as reference
  std::qsort(&points, n, sizeof(point), polarOrder);
}

// -1 ccw, 1 cw, 0 collinear
int orientation(point a, point b, point c)
{
   double area2 = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
   if      (area2 < 0) return -1;
   else if (area2 > 0) return +1;
   else                return  0;
}

// compare other points relative to polar angle they make with this point
// (where the polar angle is between 0 and 2pi)
int polarOrder(const void *vp1, const void *vp2)
{
  point *p1 = (point *)vp1;
  point *p2 = (point *)vp2;

  // translation
  double dx1 = p1->x - centroid.x;
  double dy1 = p1->y - centroid.y;

  double dx2 = p2->x - centroid.x;
  double dy2 = p2->y - centroid.y;

  if      (dy1 >= 0 && dy2 < 0) { return -1; }  // p1 above and p2 below
  else if (dy2 >= 0 && dy1 < 0) { return  1; }  // p1 below and p2 above
  else if (dy1 == 0 && dy2 ==0) {               // 3-collinear and horizontal
      if      (dx1 >= 0 && dx2 < 0) { return -1; }
      else if (dx2 >= 0 && dx1 < 0) { return  1; }
      else                          { return  0; }
  }
  else return -orientation(centroid,*p1,*p2);   // both above or below
}
点形心;
int main(int argc,字符**argv)
{
//我将一组点读入结构点数组:点[n]
//找到质心
双sx=0;双sy=0;
对于(int i=0;i0)返回+1;
否则返回0;
}
//将其他点与它们与该点形成的极角进行比较
//(其中极角在0和2pi之间)
int-PolaroOrder(常数无效*vp1,常数无效*vp2)
{
点*p1=(点*)vp1;
点*p2=(点*)vp2;
//翻译
双dx1=p1->x-质心.x;
双dy1=p1->y-质心.y;
双dx2=p2->x-质心.x;
双dy2=p2->y-质心.y;
如果(dy1>=0&&dy2<0){return-1;}//p1在上面,p2在下面
else如果(dy2>=0&&dy1<0){return 1;}//p1在下面,p2在上面
如果(dy1==0&&dy2==0){//3-共线和水平
如果(dx1>=0&&dx2<0){return-1;}
如果(dx2>=0&&dx1<0){return 1;}
else{return 0;}
}
else返回方向(质心,*p1,*p2);//在上面或下面
}
看起来这些点被精确地排序(粉红色),直到它们“塌陷”,在这种情况下,算法跳过这些点,然后继续。。有人能给我指出正确的方向来对这些点进行排序,使它们形成我要寻找的多边形吗? 原始点绘图-蓝色、粉色点-已排序


点列表:(您可以忽略第三个组件,因为所有这些点都位于同一平面上。)

首先,我看到
centroid
main
中声明为局部变量。然而在
polariorder
中,您也在访问一些
centroid
变量

根据您发布的代码判断,第二个
centroid
是一个从未初始化为任何特定值的文件范围变量。因此,比较函数的结果毫无意义


代码中第二个奇怪的细节是,如果两个点都在上面或下面,则返回方向(质心,*p1,*p2)。由于
orientation
对于CCW返回
-1
,对于CW返回
+1
,因此它应该是
返回方向(质心,*p1,*p2)
。为什么您觉得有必要否定
定向的结果

首先,我看到
centroid
main
中声明为局部变量。然而在
polariorder
中,您也在访问一些
centroid
变量

根据您发布的代码判断,第二个
centroid
是一个从未初始化为任何特定值的文件范围变量。因此,比较函数的结果毫无意义


代码中第二个奇怪的细节是,如果两个点都在上面或下面,则返回方向(质心,*p1,*p2)
。由于
orientation
对于CCW返回
-1
,对于CW返回
+1
,因此它应该是
返回方向(质心,*p1,*p2)
。为什么您觉得有必要否定
定向的结果

原始点不会形成凸多边形,因此简单地按固定质心周围的角度对其排序不一定会产生干净的多边形。这是一个非常重要的问题,您可能需要研究和/或算法,尽管这两种算法都必须修改,因为您的多边形是凹的。答案是一个有趣的例子,修改了凹多边形的礼品包装算法。还有一个C++库,它可以做你需要的。 但是…如果你真的想做极性排序,你的排序功能似乎比必要的更复杂。我会先使用排序,然后在获得所需结果后进行优化(如有必要)。以下是使用lambda函数的示例:

#include <algorithm>
#include <math.h>
#include <vector>

int main()
{
    struct point
    {
        double x;
        double y;
    };

    std::vector< point > points;
    point centroid;

    // fill in your data...

    auto sort_predicate = [&centroid] (const point& a, const point& b) -> bool {
        return atan2 (a.x - centroid.x, a.y - centroid.y) <
                atan2 (b.x - centroid.x, b.y - centroid.y);
    };

    std::sort (points.begin(), points.end(), sort_predicate);
}
#包括
#包括
#包括
int main()
{
结构点
{
双x;
双y;
};
标准::向量<点>点;
点形心;
//填写您的数据。。。
自动排序_谓词=[¢roid](常量点&a,常量点&b)->bool{
返回atan2(a.x-形心.x,a.y-形心.y)<
atan2(b.x-质心x,b.y-质心y);
};
排序(points.begin()、points.end()、sort_谓词);
}

您的原始点不会形成凸多边形,因此仅按固定质心周围的角度对它们进行排序不一定会产生干净的多边形。这是一个非常重要的问题,您可能需要研究和/或算法,尽管这两种算法都必须修改,因为您的多边形是凹的。答案是一个有趣的例子,修改了凹多边形的礼品包装算法。还有一个C++库,它可以做你需要的。 但是…如果你真的想做极性排序,你的排序功能似乎比必要的更复杂。我会先使用排序,然后在获得所需结果后进行优化(如有必要)。以下是使用lambda函数的示例:

#include <algorithm>
#include <math.h>
#include <vector>

int main()
{
    struct point
    {
        double x;
        double y;
    };

    std::vector< point > points;
    point centroid;

    // fill in your data...

    auto sort_predicate = [&centroid] (const point& a, const point& b) -> bool {
        return atan2 (a.x - centroid.x, a.y - centroid.y) <
                atan2 (b.x - centroid.x, b.y - centroid.y);
    };

    std::sort (points.begin(), points.end(), sort_predicate);
}
#包括
#包括
#包括
int main()
{
结构点
{
双x;
双y;
};
标准::向量<点>点;
点形心;
//填写您的数据。。。
自动排序谓词=