商业地图纠偏接口次数限制的处理策略
商业地图纠偏接口次数限制的处理策略
现在的地图服务提供商,都会有自己的坐标系统,这样就存在坐标转换相关的处理,然而有些坐标转换会在服务端有一定的次数限制,不能满足一些应用场景。本文从纠偏出现的缘由出发,以百度地图为例,给出服务端纠偏的一些通用的处理策略。
相关坐标系
目前国内主要有以下三种坐标系:
WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。
GCJ02:又称火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。
BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标。
非中国地区地图,服务坐标统一使用WGS84坐标。
那么为什么会有火星坐标这一说,是因为国家测绘局为了信息安全原因,对WGS84坐标进行加偏的结果,其实我们口口声声所说的纠偏,其实是加偏,国家认为地理信息数据是保密数据,不应该这么容易就被获取。真正显示在地图服务上的也是经过加偏处理,显示的内容也是经过过滤的。同样的原因,只有一定的测绘资质的公司,才可以有权采集处理地理信息数据。
总而言之,百度地图对应的是BD09坐标系,我们采集来的WGS84坐标下的数据必须经过加偏才能准确的展示在地图上。
坐标转换
百度对于JavaScript和移动端的坐标转换没有次数限制,然而有些场景我们需要在服务端进行坐标转换,然而服务端的接口调用会有次数限制:
| 分类 | 未认证 | 个人认证 | 企业认证 |
|---|---|---|---|
| 日配额(次) | 100,000 | 300,000 | 3000,000 |
| 分钟并发量(次/分钟) | 6,000 | 12,000 | 30,000 |
这样它并不能满足所有的需求。这样我们可以通过升级为企业认证来解决这个问题,但是对于量的上限还是解决不了问题,或者申请多个用户同样存在瓶颈。难道我们我们要申请个测绘资质,自己搞个地图服务,替换掉百度,成本太高哦。我们可以基于样本采集来解决这个问题。
原理
首先按照一定的间隔调用百度坐标转换接口进行采样,获取采样点的偏移量;然后根据需要纠偏点的坐标,获取该点的周围的采样点,根据采样点计算该点的偏移值,进而获得该点的百度坐标。
采样
前端代码如下
<#import "common/spring.ftl" as spring />
<#assign base=request.contextPath />
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
"http://www.w3.org/1999/xhtml">
"viewport" content="initial-scale=1.0, user-scalable=no"/>"Content-Type" content="text/html; charset=utf-8"/>"stylesheet" href="${base}/css/midlay/v6/midlay_mw_transport.css" type="text/css"/>纠偏采集 #include "script/locale/messages.ftl">
<#include "script/custom/transportGrid.ftl">
<#include "script/layer/layer.ftl">
<#include "midlay/v6/mwtransport/function/tempModel.ftl">
"map_canvas">
选择城市"南京市" id="city"/>
采样间隔"0.001" id="interval"/>度
采集范围:"0" id="startCol"/>列-》"10000" id="endCol"/>
断点处行:"0" id="interruptRow"/>行
采集信息 "collectInfo">
本次采集信息 "collectInfoSingle">
百分比 "percent">个数 "exeNum">耗时"consumeTime">当前执行"nowExe">
经度范围"" id="startLng"/>-》"" id="endLng"/>纬度范围"" id="startLat"/>-》"" id="endLat"/>测试个数"1000" id="testNum"/>
后端代码如下
public void upsert(PosDiffGrid posDiffGrid) {String id = this.formGridId(posDiffGrid);tlCriteria.set(Criteria.where("id").is(id));PosDiffGrid oldPosDiffGrid = (PosDiffGrid)this.get();if(oldPosDiffGrid == null) {posDiffGrid.setId(id);posDiffGrid.setTsCreate(new Date());posDiffGrid.setTsUpDate(new Date());posDiffGrid.setDiffLon(posDiffGrid.getBaiduPoint().getLongitude() - posDiffGrid.getRealPoint().getLongitude());posDiffGrid.setDiffLat(posDiffGrid.getBaiduPoint().getLatitude() - posDiffGrid.getRealPoint().getLatitude());List diffs = new ArrayList();diffs.add(posDiffGrid);this.insertList(diffs);} else {Update update = new Update();update.set("diffLon", Double.valueOf(posDiffGrid.getBaiduPoint().getLongitude() - posDiffGrid.getRealPoint().getLongitude()));update.set("diffLat", Double.valueOf(posDiffGrid.getBaiduPoint().getLatitude() - posDiffGrid.getRealPoint().getLatitude()));update.set("tsUpdate", new Date());update.set("province", posDiffGrid.getProvince());update.set("city", posDiffGrid.getCity());update.set("district", posDiffGrid.getDistrict());update.set("address", posDiffGrid.getAddress());tlUpdate.set(update);this.update();}}
纠偏
纠偏代码如下
public PosDiffGrid near(PosDiffGrid posDiffGrid) {PosDiffGrid result = new PosDiffGrid();Point point = new Point(posDiffGrid.getRealPoint().getLongitude(), posDiffGrid.getRealPoint().getLatitude());Criteria criteria = Criteria.where("realPoint").near(point).maxDistance(0.0013498920086393088D);tlCriteria.set(criteria);List grids = this.list();double minDis = 2000.0D;if(CollectionUtils.isEmpty(grids)) {return null;} else {PosDiffGrid st = null;Iterator var9 = grids.iterator();while(var9.hasNext()) {PosDiffGrid pdg = (PosDiffGrid)var9.next();double dis = GeoUtil.calcDistance(posDiffGrid.getRealPoint().getLongitude(), posDiffGrid.getRealPoint().getLatitude(), pdg.getRealPoint().getLongitude(), pdg.getRealPoint().getLatitude());if(minDis > dis) {minDis = dis;st = pdg;}}if(st == null) {return null;} else {GiPoint baiduPt = new GiPoint();baiduPt.setLongitude(posDiffGrid.getRealPoint().getLongitude() + st.getDiffLon());baiduPt.setLatitude(posDiffGrid.getRealPoint().getLatitude() + st.getDiffLat());result.setRealPoint(posDiffGrid.getRealPoint());result.setBaiduPoint(baiduPt);result.setProvince(st.getProvince());result.setCity(st.getCity());result.setDistrict(st.getDistrict());result.setAddress(st.getAddress());return result;}}}public PosDiffGrid distanceRight(PosDiffGrid posDiffGrid, double n) {PosDiffGrid result = new PosDiffGrid();Point point = new Point(posDiffGrid.getRealPoint().getLongitude(), posDiffGrid.getRealPoint().getLatitude());Criteria criteria = Criteria.where("realPoint").near(point).maxDistance(0.0010799136069114472D);tlCriteria.set(criteria);List grids = this.list();if(CollectionUtils.isEmpty(grids)) {return null;} else if(grids.size() == 1) {result = this.near(posDiffGrid);return result;} else {double minDis = 2000.0D;double sumDis = 0.0D;PosDiffGrid st = null;Iterator var13 = grids.iterator();double latDiff;while(var13.hasNext()) {PosDiffGrid pdg = (PosDiffGrid)var13.next();latDiff = GeoUtil.calcDistance(posDiffGrid.getRealPoint().getLongitude(), posDiffGrid.getRealPoint().getLatitude(), pdg.getRealPoint().getLongitude(), pdg.getRealPoint().getLatitude());sumDis += Math.pow(latDiff, n);if(minDis > latDiff) {minDis = latDiff;st = pdg;}}double lngDiif = 0.0D;latDiff = 0.0D;PosDiffGrid pdg;double dis;for(Iterator var17 = grids.iterator(); var17.hasNext(); latDiff += Math.pow(dis, n) / sumDis * pdg.getDiffLat()) {pdg = (PosDiffGrid)var17.next();dis = GeoUtil.calcDistance(posDiffGrid.getRealPoint().getLongitude(), posDiffGrid.getRealPoint().getLatitude(), pdg.getRealPoint().getLongitude(), pdg.getRealPoint().getLatitude());lngDiif += Math.pow(dis, n) / sumDis * pdg.getDiffLon();}GiPoint baiduPt = new GiPoint();baiduPt.setLongitude(posDiffGrid.getRealPoint().getLongitude() + lngDiif);baiduPt.setLatitude(posDiffGrid.getRealPoint().getLatitude() + latDiff);result.setRealPoint(posDiffGrid.getRealPoint());result.setBaiduPoint(baiduPt);result.setProvince(st.getProvince());result.setCity(st.getCity());result.setDistrict(st.getDistrict());result.setAddress(st.getAddress());return result;}}private String formGridId(PosDiffGrid posDiffGrid) {return posDiffGrid.getRealPoint().getLongitude() * 1000.0D + "_" + posDiffGrid.getRealPoint().getLatitude() * 1000.0D;}
前端页面
采集量级及纠偏结果
对于南京这样的城市,采用100m*100m的网格,大概采集了120W条数据。采用最近距离算法误差会在1m以内,然而对于民用的GPS采集端,定位精度也就是几米,这样完全可以满足需求。同时可以扩大采样间隔来满足不同需求,用户可以自己测试。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
