判断一个点是否在多边形内&GIS LBS 系统中的应用说明
如何判断一个点是否在多边形内部?
- 面积和判别法:判断目标点与多边形的每条边组成的三角形面积和是否等于该多边形,相等则在多边形内部。
- 夹角和判别法:判断目标点与所有边的夹角和是否为360度,为360度则在多边形内部。
- 引射线法:从目标点出发引一条射线,看这条射线和多边形所有边的交点数目。如果有奇数个交点,则说明在内部,如果有偶数个交点,则说明在外部。
1.2.都非常好理解,但是1.2. 并不适合所有的多边形,比如说凹多边形。关于射线算法,好像没有公式证明,不过网上很多论文可以google到.
图一:点延伸出的射线穿过不规则多边形,往左射线交5点,往右射线交3点,所以判断点在多边形内
多边形要规避一些极端情况,比如自我闭合等情况,具体可以参考Determining Whether A Point Is Inside A Complex Polygon
关于GIS/LBS上的应用,问,该算法是否可以判断经纬度坐标是否在一个标记的地图围栏中(任意多边形),答案是可以,但是需要注意两个问题:
- 如果你的多边形有一个在地球上穿越一个大距离的单侧,那么多边形中的点将沿着一条明显弯曲的路径朝那个方向(特别是靠近两极),而不是一个真实的,最短的距离路径。如果你的多边形没有一个侧面穿过很远的距离,你就可以避免这个问题
- 如果你的多边形穿过国际日期变更线,然后算法都会经突然重置完全乱了。它可能需要添加或减去360°一些点的经度来防止这种情况的发生。(但如果多边形完全围绕南北极,这个解决办法就行不通了。)
也就是地图是球形的,而且经纬度是对标国际日期变更线设定,这两个原因导致多边形最终并不处于一个平面坐标内。所以如果应用在中国一定规模区域范围内(比如汽车、自行车的活动范围),完全没问题。在中联,我们就将其广泛应用到一系列车辆产品上,例如 中联环卫车、餐厨回收车、搅拌车、泵车、干粉运输车等等,用来判断车辆是否驶离/驶入工厂工地和监控车辆是否处于合理范围内/外
文章包括三部分
- 算法原理
- 代码实现(csharp)
- 实际应用举例对比(图)
算法
从目标点出发引一条射线,看这条射线和多边形所有边的交点数目。如果有奇数个交点,则说明在内部,如果有偶数个交点,则说明在外部
代码实现(csharp)
几年前用 c# 封装的一个关于地图的工具包,包含 道格拉斯普克抽稀算法-用于 历史轨迹回放;点面射线算法-用于电子围栏,判断点是否在不规则平面多边形内;各种地图的经纬度纠偏-用于火星坐标和真实坐标的转换(可能存在最近几年地图供应商算法已经改变了);下面给出平面内点在复杂多边形内外的射线算法,上一篇给到用于gis 系统中的轨迹回放,下一篇几个地图服务商的经纬度纠偏算法;
工具包源码已开源到github
还是坐标对象GeometryModels,包含点,线,多边形的定义
1 | using System; |
PolygonUtil.cs ,射线算法的实现,其中有考虑到算法的优化,和几种特殊情况的规避(如点在边上),注释还算详细,就不多解释
1 |
|
实际应用
以中联搅拌车调度系统的电子围栏功能为例(环卫车、餐厨垃圾回收车、泵车、干粉砂浆运输车、罐等等都有应用,只是年代久远找不到几个截图了…)。因为搅拌车的活动轨迹,一般处于以搅拌站为中心,周边50公里范围内。作用在于1)判断车辆是否离场; 2)车辆是否进入工地(同时可以统计在途时间); 3)车辆是否进入活动禁区(比如白天进x环,城市管理条例。。。); 4)车辆是否驶离活动范围
时代久远,没找到图了,只好在用户手册中截取…