1.需求与既有方案
本文需求来源于基础地理信息服务,需要将用户设备采集的经纬度信息转换为所处的行政区域。以往的方式是有以下几种
-
1)直接使用高德web api 中的逆编码方式获取
此方法问题在于高度依赖网络调用,难以实现高并发、快速查询。且高德web api有调用次数限制,无法做到无限使用。 -
2)从网络上搜集行政区域数据,并且查询其中心坐标,计算用户传入坐标与中心坐标最近的区域作为逆编码结果
此方法的问题在于,数据陈旧,无法有效更新,其次,以中心点坐标距离作为判断依据,对于行政区不规则边界而言,精度不高,极易出现误判情况。 -
3)从高德获取行政区域 & 区域边界数据,通过算法计算逐一计算坐标点位于哪个行政区域的边界内
此方法的好处在于结果准确。问题在于计算性能受边界坐标点数量影响。高德共有3200+行政区域,所有边界点数量约百万(约640万)级别,若每次用户请求均实时比较计算,明显无法满足性能需求。
2. 方案
该方法依赖于高德行政区域完整数据源,可以通过web api统一一次性拉取后,定期更新基础数据即可。
2.1 拉取基本信息
数据来源接口: 高德行政区域查询
STEP 1: 行政区信息
在这里传入keywords=&subdistrict=3&extensions=base
即可获取国家 -> 省 -> 市 -> 区 四级基本行政区的树结构。
STEP 2: 边界信息
遍历行政区树节点,在这里传入keywords=${行政区adcode}&subdistrict=0&extensions=all
即可获取该节点的边界坐标列表(即 polyline )。
⚠️有的行政区域由多个独立的地块组成,polyline之间用|
分割。坐标和坐标间用;
分割。
2.2 逆编码实现
借助java原生工具包 java.awt.geom
即可。
该实现方案即为上节内容的3)
方案
/* Point2D.Double 是java.awt.geom.Point2D.Double , 记录x,y 二维坐标,此处直接填入经纬度 */
public boolean pointInPolygon(double latitude, double longitude, List<Point2D.Doubl