我有一个算法可以找到一个点是否在多边形内。
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j, c = 0;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))) &&
(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
c = !c;
}
return c;
}
我唯一的问题是假设一个奇怪的缠绕规则。我的意思是,如果多边形是自相交的,那么它被认为是“空”的某些部分将返回false。我需要的是即使它自相交,多边形内的任何东西都会返回true。
由于
答案 0 :(得分:5)
小心:此答案错误。我现在没时间修复它,但看到评论。
这会将光线从点投射到无穷远,并检查每个多边形边缘的交点。每次找到交集时,都会切换标记c
:
c = !c;
所以偶数个交叉点意味着偶数个切换,所以c
最后会为0。奇数个交叉点意味着奇数个切换,因此c
将为1。
如果任何交叉点发生,你想要的是设置c
标志:
c = 1;
为了更好的衡量,您可以完全消除c
,并提前终止:
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))) &&
(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
return 1;
}
return 0;
}
答案 1 :(得分:1)
将原始算法转换为英语:您要确定点右侧的多边形线段数是偶数还是奇数。如果它是偶数(包括零)你的观点在外面,如果奇怪你的观点在里面。这意味着如果右侧有两个段,左侧有两个段,则多边形内的点不。
您需要做的是更改算法,以便检查两侧的段;如果点的两边都有一个段,则该点在多边形内。
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j;
bool hasSegmentLeft = false;
bool hasSegmentRight = false;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))))
{
if (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i])
{
hasSegmentRight = true;
if (hasSegmentLeft) // short circuit early return
return true;
}
else
{
hasSegmentLeft = true;
if (hasSegmentRight) // short circuit early return
return true;
}
}
return hasSegmentLeft && hasSegmentRight;
}
P.S。 for
语句构造是一种处理循环列表的非常聪明的方法,它包含在开头;我以前从未见过它。