Java判断gps点是否在中国,如何判断一个指定的位置点坐标(GPS上的经纬度)是否落在一个多边形区域内?...

本文介绍如何使用Java判断一个GPS点是否位于一个多边形区域内,主要涉及射线法和坐标轴法,特别是X轴射线法。通过创建坐标点抽象类和位置关系判断工具类,实现点与多边形的关系判断,适用于快递配送、电子围栏等场景。

业务场景举例:快递选择收获区域、车辆电子围栏、运动轨迹路线、地理位置信息检测范围和地图等过滤等等。

比方说地图上有一块区域(抽象成多边形),然后里面每一个位置点(像素点)都有对应的GPS的经纬度坐标值,题目要求的就是判断任意点(用户输入的信息)与多边形的位置关系(是否在里面还是在图形区域外面)。

30209d473a0d32c512c436f2891696a2.png

具体有一个需求为:每一个店维护多个可配送的地址,配送地址为地图中的多边形区域,用户选择收货地址的时候需要判断该收货地址在不在多边形区域内。(给定一个点的坐标以及一个多边形的所有顶点坐标。要求能够判断这个点是在多边形内,还是在多边形外?)

验证地址:Map Polygon/Polyline Tool https://www.keene.edu/campus/maps/tool/

f777c7f38c8f34fbcb4c31e46549e83f.png

以上的ABCDE,分别是以下数组里面的数据

[java]  view plain

copy

Point[] ps =newPoint[] {newPoint(120.2043,30.2795),newPoint(120.2030,30.2511),newPoint(120.1810,30.2543),newPoint(120.1798,30.2781),newPoint(120.1926,30.2752) };

那么问题来了:如何判断一个指定的经纬度点是否落在一个多边形区域内?

这个是算法和判断的依据也是解答本题的关键。(保证准确率和速度的关键)

网络上有很多算法和第三库来实现这类功能,但本文着重讲原理和自己实现写程序。

话不多说,直接抛出写程序通常用的流程模型图,如下;

7e66d35f77e989fc09288390154c2868.png

经过在网上的一番搜索,

发现目前比较通用的就是射线法和坐标轴法,而我采用的就是X轴射线法。

主要理论来源于西安交大的一篇论文(即参考文献的第二条)

判断一个点向左的射线跟一个多边形的交叉点有几个,如果结果为奇数的话那么说明这个点落在多边形中,反之则不在。

1、理论支持:如果从需要判断的点出发的一条射线与该多边形的焦点个数为奇数,则该点在此多边形内,否则该点在此多边形外。(射线不能与多边形顶点相交)2、编程思路:该程序的思路是从A点出发向左做一条水平射线(平行于x轴,向X轴的反方向),判断与各边是否有焦点。dLon1, dLon2, dLat1, dLat2分别表示边的起点和终点的经度和纬度(x轴和y轴)。先判断A点是否在边的两端点d1和d2的水平平行线之间,不在则不可能有交点,继续判断下一条边。在之间则说明可能与A点向左的射线有交点,接下来利用几何方法得到A点的水平直线与该边交点的x坐标。然后判断交点的x坐标在A点的左侧还是右侧,左侧则总交点数加一,右侧则不在A点左射线上,继续判断下一条边。

代码讲解:主要的类有两个↓↓

一个是坐标点的抽象类(点的坐标位置),另一个是位置关系判断工具类(判断点和多边形的关系)。

因为坐标描点要涉及到坐标以及小数点的经纬关系,故要用到浮点型运算,也就是要使用到double双精度。而地图涉及到很多个像素点构成的图形区域,故要用到list数组。结果要展示需要用到js代码。

def IsPtInPoly(aLon, aLat, pointList):

'''''

:param aLon: double 经度

:param aLat: double 纬度

:param pointList: list [(lon, lat)...] 多边形点的顺序需根据顺时针或逆时针,不能乱

'''

iSum = 0

iCount = len(pointList)

if(iCount < 3):

return False

for i in range(iCount):

pLon1 = pointList[i][0]

pLat1 = pointList[i][1]

if(i == iCount - 1):

pLon2 = pointList[0][0]

pLat2 = pointList[0][1]

else:

pLon2 = pointList[i + 1][0]

pLat2 = pointList[i + 1][1]

if ((aLat >= pLat1) and (aLat < pLat2)) or ((aLat>=pLat2) and (aLat < pLat1)):

if (abs(pLat1 - pLat2) > 0):

pLon = pLon1 - ((pLon1 - pLon2) * (pLat1 - aLat)) / (pLat1 - pLat2);

if(pLon < aLon):

i

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值