简体   繁体   English

帮助这个算法

[英]Help with this algorithm

I have an algorithm that can find if a point is inside a polygon. 我有一个算法,可以找到一个点是否在多边形内。

 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;
 }

My only issue with it is it assumes an odd winding rule. 我唯一的问题是假设一个奇怪的缠绕规则。 What I mean by this is that if the polygon is self intersecting, certain parts that it would considered to be 'empty' will return as false. 我的意思是,如果多边形是自相交的,那么它被认为是“空”的某些部分将返回false。 What I'd need in even if it self intersects, anything inside the polygon will return true. 我需要的是即使它自相交,多边形内的任何东西都会返回true。

Thanks 谢谢

Beware : this answer is wrong . 小心 :这个答案是错误的 I have no time to fix it right now, but see the comments. 我现在没时间修复它,但看到评论。

This casts a ray from the point to infinity, and checks for intersections with each of the polygon's edges. 这会将光线从点投射到无穷远,并检查每个多边形边缘的交点。 Each time an intersection is found, the flag c is toggled: 每次找到一个交叉点时,都会切换标志c

c = !c;

So an even number of intersections means an even number of toggles, so c will be 0 at the end. 所以偶数个交叉点意味着偶数个切换,所以c会为0。 An odd number of intersections means an odd number of toggles, so c will be 1. 奇数个交叉点意味着奇数个切换,因此c将为1。

What you want instead is to set the c flag if any intersection occurs: 你想要的是在发生任何交叉时设置c标志:

c = 1;

And for good measure, you can then eliminate c entirely, and terminate early: 为了更好的衡量,您可以完全消除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;
 }

To translate your original algorithm to english: You're determining if the number of polygon segments to the right of your point are even or odd. 要将原始算法转换为英语:您要确定点右侧的多边形线段数是偶数还是奇数。 If it's even (including zero) your point is outside, if it's odd your point is inside. 如果它是偶数(包括零)你的观点在外面,如果奇怪你的观点在里面。 This means if there are two segments to the right and also two segments to the left, the point is not considered inside the polygon. 这意味着如果右侧有两个段,左侧有两个段,则该点不在多边形内部。

What you need to do is change the algorithm so that it checks for segments on both sides; 您需要做的是更改算法,以便检查两侧的段; if there's a segment on both sides of the point, then the point is within the polygon. 如果该点的两侧都有一个线段,则该点在多边形内。

 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; 
 }

PS that for statement construct is a very clever way of dealing with a circular list that wraps around to the beginning; PS是for语句结构是处理与回绕到开始循环链表的一个非常聪明的方式; I'd never seen it before. 我以前从未见过它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM