多边形内的点(不包括边界)

时间:2013-05-07 14:51:18

标签: c++ polygon

我目前正在寻找具有12个顶点的特定形状内的坐标。

          (3,7)  (5,7)
            #######
            #     #
            #  X  #
       (3,5)#     #(5,5)
 (1,5)#######  X  #######(7,5)
      #                 #
      #  X  X  X  X  X  #
      #                 #
 (1,3)#######  X  #######(7,3)
       (3,3)#     #(5,3)
            #  X  #
            #     #
            #######
          (3,1)  (5,1)

我想找出形状内的坐标(标记为“X”),不包括构成形状的坐标。

我曾尝试过W. Randolph Franklin(http://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html)的pnpoly,但它也认为构成形状的坐标是“在形状内”。

请注意,上述形状只是一个例子。坐标可以在任何地方。

如何修改代码,使其不允许包含形状的边界?

int pnpoly(int vertx[], int verty[], int testx, int testy) {
    int nvert = 12;
    int i, j, c = 0;
    for (i = 0, j = nvert-1; i < nvert; j = i++) {
        if ( ((verty[i]>testy) != (verty[j]>testy)) && (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) ) {
            c = !c;
        }
    }
    return c;
}

2 个答案:

答案 0 :(得分:2)

按要排除的边框缩小形状,然后使用现有算法。

顺便说一句:不要使用int vertx[],这是一个危险的谎言。相当明显的代码是int* vertx,这很明显它缺少const

答案 1 :(得分:1)

由于您有代码来测试点是否在给定多边形内,您只需要排除那些 on 多边形的点。 注意:只有使用整数坐标(不是浮点数)时,此测试才可靠。

struct Point {
  int X;
  int Y;
};

bool PointOnLineSegment(const Point pt, const Point linePt1, const Point linePt2)
{
  return ((pt.X == linePt1.X) && (pt.Y == linePt1.Y)) ||
    ((pt.X == linePt2.X) && (pt.Y == linePt2.Y)) ||
    (((pt.X > linePt1.X) == (pt.X < linePt2.X)) &&
    ((pt.Y > linePt1.Y) == (pt.Y < linePt2.Y)) &&
    ((pt.X - linePt1.X) * (linePt2.Y - linePt1.Y) ==
      (linePt2.X - linePt1.X) * (pt.Y - linePt1.Y)));
}

bool PointOnPolygonEdge(const Point pt, Point *poly, int vertexCnt)
{
  if (vertexCnt < 2) return false;
  vertexCnt--;
  for (int i = 0; i < vertexCnt; ++i)
    if (PointOnLineSegment(pt, poly[i], poly[i+1])) 
      return true;
  if (PointOnLineSegment(pt, poly[vertexCnt], poly[0])) return true;
  return false;
}


编辑(2018年12月8日):

我的(旧)答案可以在...上得到很大改善 参考Hormann&amp ;;的“任意多边形的多边形问题中的点”。 Agathos
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf

struct Point { int X; int Y; };
typedef std::vector< Point > Path;

int PointInPolygon(const Point &pt, const Path &path)
{
  //returns 0 if false, +1 if true, -1 if pt ON polygon boundary
  int result = 0;
  size_t cnt = path.size();
  if (cnt < 3) return 0;
  Point ip = path[0];
  for(size_t i = 1; i <= cnt; ++i)
  {
    Point ipNext = (i == cnt ? path[0] : path[i]);
    if (ipNext.Y == pt.Y)
    {
        if ((ipNext.X == pt.X) || (ip.Y == pt.Y && 
          ((ipNext.X > pt.X) == (ip.X < pt.X)))) return -1;
    }
    if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y))
    {
      if (ip.X >= pt.X)
      {
        if (ipNext.X > pt.X) result = 1 - result;
        else
        {
          int d = (ip.X - pt.X) * (ipNext.Y - pt.Y) - 
            (ipNext.X - pt.X) * (ip.Y - pt.Y);
          if (!d) return -1;
          if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result;
        }
      } else
      {
        if (ipNext.X > pt.X)
        {
          int d = (ip.X - pt.X) * (ipNext.Y - pt.Y) - 
            (ipNext.X - pt.X) * (ip.Y - pt.Y);
          if (!d) return -1;
          if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result;
        }
      }
    }
    ip = ipNext;
  } 
  return result;
}