我目前正在寻找具有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;
}
答案 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;
}