我正在寻找一种完美的C#算法,该算法确定是否在多边形内找到位置(经/纬度)。
在Google地图上,我创建了多边形的不同区域。每个区域可以由一组坐标表示。例如,以下是牙买加蒙特哥湾(A区)的坐标(经度,纬度组合):
-77.9531479,18.4565699,-77.9482339,18.4579542,-77.9443393,18.4615874,-77.9399726,18.4627373,-77.933943,18.4653526,-77.931272,18.4652763,-77.9282138,18.46578,-77.9267121,18.4645891,-77.924619,18.4625118,-77.923131,18.4689837,-77.924646,18.4727285,-77.924112,18.4763919,-77.9255882,18.4793735,-77.927573,18.4833522,-77.9234638,18.4888979,-77.92363,18.492311,-77.914973,18.4951459,-77.918355,18.4971759,-77.972733,18.4985953,-77.916291,18.527569,-77.8997725,18.56178,-77.8962851,18.58578,-77.873843,18.517512,-77.8772736,18.5228297,-77.9253387,18.521568,-77.9531479,18.4565699
现在让我们说,我们需要确定坐标为(长/纬):-95.030710、29.148650的牙买加蒙特哥湾日落海滩酒店是否属于A区?
我已经测试了很多可用的算法,但是没有一个能完美地工作。它适用于某些酒店,但不适用于所有酒店。
将寻求任何帮助。
答案 0 :(得分:1)
我使用绕组编号http://geomalgorithms.com/a03-_inclusion.html
获得成功第1步:定义多边形的绘制方向。
从根本上讲,多边形是静态的,没有方向。但是,请考虑在一张纸上绘制多边形时执行的移动。您从一个位置开始,然后移动笔为多边形的每一侧画一条线。如果不将笔从纸上移开,则多边形的每一边将全部沿顺时针方向绘制,或者全部沿逆时针方向绘制。
我们可以使用此“方向”来确定多边形的边如何围绕点(顺时针缠绕或逆时针缠绕)缠绕。
对于所讨论的真实多边形(尚未在一个方向上绘制),您认为已绘制哪个方向并不重要,但重要的是将每一边都视为在同一方向上绘制
第2步:将多边形的每一边视为具有两个顶点的单个对象。
如果我们知道多边形的顶点,就可以确定多边形各边的端点。
第3步:确定每边与该点相交的方向(如果两边确实与该点相交)。
使用顺时针缠绕查找多边形是否围绕point
的示例:
定义一个counter
来跟踪绕组编号。
对于多边形的每一边,取第一顶点vertex1
和第二顶点vertex2
(这些点定义了每一边的末端)。
如果vertex1.x
<point.x
,则边开始于point.x
的左侧。
如果vertex2.x
> point.x
,则边在point.x
的右侧结束。
如果该边开始于左侧,而结束于右侧,则该线穿过该点。
如果侧面越过point
,我们需要确定其越过的方向。
使用顺时针方向作为正方向,该边必须在point
上方交叉才能视为正。如果在point
的x位置的线的y值大于point
的y值,则该线越过point
。否则,它会越过该点。
如果从上方穿过,请增加counter
。如果在下方穿过,请减小counter
。
注意:请注意,如果直线从左向右穿过,则正方向会看到该线在该点上方通过,但是如果直线从右向左(绕回该点下方),则正方向会看到该线通过以下的点。正方向是顺时针方向。
现在对多边形的下一面执行相同的操作,其中vertex1
将是多边形的下一面vertex2
,而新的vertex2
是多边形在行驶时的下一角顺时针方向。
对多边形的所有面执行此操作。
最后,您将获得一个带有正,负或0值的计数器。
如果计数器的值为0,则多边形不包含点,否则包含点。
这是因为包含点的多边形始终具有偶数个通过该点的边。无论是2面,还是4面,等等。在这些面中,一半将在该点上方从左到右,而另一半将在该点下方从右到左。
结果为0表示没有边通过该点(因此多边形永远不会穿过该点的轴),或者该多边形在两个方向上(例如,从左到右的点上方)通过该点的一侧,然后从右到左指向上方)。因此,绕组号相互抵消。