当前位置: 首页 > news >正文

基于Leaflet的高德AOI数据在天地图底图可视化纠偏实践

目录

前言

一、高德地图中的AOI数据

1、数据查询

2、服务接口简介

二、在天地图中展示AOI数据

1、对面数据的处理

三、Javascript坐标纠偏

1、纠偏实现

四、总结


前言

        之前有朋友咨询,他有一份从高德地图获取的数据,原本在高德地图上展示时,空间位置都是没有问题的。但是在底图切换到天地图时,发现好好的空间范围面,居然神奇的发生了偏移。然后想咨询怎么解决这个问题。关于地图中的坐标系,感觉可以写很多的知识。这里不讲述过多的理论知识,关于坐标系的内容,大家可以自行查找一些互联网的资料来进行学习。国内的地图提供商,比如高德、百度、腾讯等等,基本上都会做一些偏移。这也是符合相关部门的安全规范。关于偏移的效果如下所示:

        选择天地图作为在线底图是一种常见的做法,也是我们推荐的做法。如前文所述,在进行一些在线数据的采集时,会将不同的矢量数据在底图中进行展示,因此发生的矢量数据和底图有偏移的情况。如上图中的红色是从高德中采集的原始数据,即偏移的数据,白色范围是对应的在天地图中的准确数据。当然,如果您的底图也是采用高德的底图的话,那么则无需处理这种情况,因此本文您也不必要看了。

        本文即在此需求背景下产生,博客内容主要讲述如何从高德地图中查找我们需要的AOI边界数据,同时讲解如何将采集回来的AOI数据如何在Leaflet地图中展示,其次讲述如何使用JavaScript在前端进行高德数据到WGS84坐标的转换,最后综合展示纠偏前和纠偏后的数据,让您对当前的场景有一个综合的了解和熟悉。如果您当前也遇到了这类问题,不妨来这里看看博文。

一、高德地图中的AOI数据

        AOI数据是兴趣面数据,对应的是POI即兴趣点数据。在空间点的分布当中,通过POI可以找到对应的AOI数据,比如一个小区,可以构建成一个AOI。这里也不深入的讲解什么是AOI,这里以高德地图为例,重点讲解如何在高德地图中查询我们需要的AOI数据,同时可以将高德的AOI数据进行相应的抓取。

1、数据查询

        首先我们在浏览器中打开高德地图,将弹出如下界面:

        以上是高德地图的首页,跟我们之前自己实现的Leaflet地图功能类似,可以做地图的缩放,非常清晰的,可以在地图的左上角可以看到可以支持关键词检索。比如在地址检索框中输入“梅溪湖步步高”,可以看到系统做了以下检索:

        可以看到,它在查询检索界面不仅将目标地址进行了列出,同时还在地图中展示了一个空间边界的范围,就是一个商场的外围边界。而这个外围边界就是指的AOI数据。 我们可以在控制台来看一下它的主要请求过程是怎么发生的。

2、服务接口简介

        为了能准确的获取目标兴趣点的边界数据,我们还需要对相关的接口进行介绍。主要分为两个接口。一个是获取目标兴趣点的列表信息,第二个是通过详情id获取坐标信息详情的接口。先来看下检索的过程是怎么处理的,打开网页的调试模式,如下图所示:

        可以在监控窗口可以看到,系统访问的后台服务地址如下:

https://www.amap.com/service/poiInfo?query_type=TQUERY&pagesize=20&pagenum=1&qii=true&cluster_state=5&need_utd=true&utd_sceneid=1000&div=PC1000&addr_poi_merge=true&is_classify=true&zoom=16.74&city=430100&geoobj=112.855343%7C28.196778%7C112.866758%7C28.200526&keywords=%E6%AD%A5%E6%AD%A5%E9%AB%98%E6%A2%85%E6%BA%AA%E6%96%B0%E5%A4%A9%E5%9C%B0

        其携带的请求参数如下所示:

        在响应中可以看到有以下的数据列表: 

        返回的是一个POI的数据列表,打开具体的一条记录,请记住里面的ID字段,这个字典就是后面的数据关联对象。 尤其是打开详情的时候的信息。

{"rating": "4.0","tel": "","typecode": "060000","areacode": "0731","address": "东方红路657号","cityname": "长沙市","display_brand": "","shape_region": "","longitude": "112.862798","review_total": "","cinemazuo_flag": "0","diner_flag": "0","id": "B0KADSUQ7M","name": "步步高梅溪新天地假日广场","group_flag": "0","distance": "0","entrances": [],"recommend_flag": "3","exits": [],"adcode": "430104","domain_list": [{"type": "html","id": "1015","name": "poiclosed"},{"type": "img","id": "1003","name": "icon"},{"type": "html","id": "1011","name": "traffic"},{"type": "text","id": "1014","name": "roadaoi"},{"type": "button","id": "1012","name": "ext_btn"},{"type": "webimg","id": "1009","value": "http://store.is.autonavi.com/showpic/c399c8adab0448847bfa1b8d698fd252","name": "pic_info"},{"type": "img","id": "1008","name": "overbooked"},{"type": "img","id": "1007","name": "moreservice"},{"type": "html","id": "1006","name": "tag"},{"type": "text","id": "1005","name": "parent_info"},{"type": "array","name": "parent_other_rel","id": "1004"},{"type": "text","id": "1010","name": "business_area"},{"type": "html","id": "1002","name": "deepinfo"},{"type": "html","id": "1001","name": "price"},{"type": "text","id": "1013","name": "aoi"}],"newtype": "060000","disp_name": "步步高梅溪新天地假日广场","cpdata": "","latitude": "28.196510","discount_flag": "0"
}

        在最后打开详情页面,可以找到AOI详情数据。如下图所示:

        访问连接如下:

https://www.amap.com/detail/get/detail?id=B0FFHRXORE

        在返回的值中就可以找到对应的AOI数据,查看data节点下的spec,再打开mining_shape字段,如下:

        到这里,基本就可以获取到高德的AOI数据。下面我们结合天地图来讲解如何进行web展示以及纠偏展示。 

二、在天地图中展示AOI数据

        我们将面的坐标点导到本地后,我们其实就可以将坐标位置展示出来。本节结合天地图和Leaflet来看一下如何将这些面展示出来。

1、对面数据的处理

        首先我们来一个真实的AOI输入,数据样例如下所示:

"112.869683,28.191884;112.868807,28.191039;112.86821,28.190464;112.867508,28.189842;112.867465,28.189826;112.867417,28.189832;112.867366,28.189852;112.867218,28.189914;112.867173,28.189945;112.86708,28.190037;112.866052,28.191339;112.865927,28.191468;112.865743,28.191696;112.865561,28.19198;112.86546,28.192143;112.864943,28.193369;112.864461,28.194713;112.864407,28.194901;112.863687,28.198129;112.863535,28.198951;112.86354,28.198996;112.863564,28.199039;112.863605,28.199068;112.86367,28.199087;112.864193,28.199117;112.864551,28.199109;112.864858,28.199091;112.866598,28.199148;112.867201,28.199252;112.868416,28.199481;112.868517,28.199511;112.868986,28.199696;112.869025,28.199704;112.86906,28.199706;112.869095,28.199697;112.869139,28.199679;112.870409,28.198994;112.870438,28.198966;112.870451,28.198938;112.870463,28.198907;112.87052,28.198537;112.870597,28.198195;112.870866,28.197445;112.870891,28.197386;112.871148,28.196907;112.871583,28.196115;112.871695,28.195868;112.872088,28.195;112.872085,28.194965;112.872075,28.194937;112.872056,28.194919;112.872032,28.194904;112.870381,28.194416;112.870349,28.194398;112.870313,28.194379;112.87029,28.194356;112.870269,28.194334;112.870255,28.194275;112.87023,28.194178;112.870231,28.194067;112.870262,28.193956;112.870301,28.193888;112.870388,28.193776;112.87045,28.193705;112.870515,28.193636;112.870627,28.193523;112.87066,28.193483;112.870677,28.193449;112.870686,28.193396;112.870689,28.193341;112.870653,28.192904;112.870648,28.192846;112.870631,28.192802;112.870606,28.192773;112.870267,28.192485;112.870243,28.192456;112.870236,28.192425;112.870223,28.192318;112.870218,28.192292;112.870212,28.192266;112.870194,28.192244;112.869794,28.191969;112.869683,28.191884";

可以看到,这是一个由多个坐标点连续而成的面。两个坐标点之间用;号隔开。而坐标点的经纬度则用逗号隔开。因此我们在Javascript中只需要先按分号分隔字符串,再用逗号分隔就可以形成一个连续的面坐标。关键代码如下:

function convertStr2DataArrayNoTrans(strInfo){var resultData = new Array();var dataArray = strInfo.split(";");for(var i = 0;i< dataArray.length;i++){var _tempLatLon = dataArray[i].split(",");resultData.push([_tempLatLon[1],_tempLatLon[0]]);}return resultData;
}

        最后调用Leaflet的API实现展示,代码如下:

L.polygon([convertStr2DataArrayNoTrans(diyishifanStr)],style).addTo(map).bindPopup("湖南第一师范学院东方红校区原始数据");

        然后来看空间数据的展示情况,为了方便对比,这里选取了一些附近的面数据包括学校和楼盘信息。方便让大家理解偏移情况。以下标红的即表示在天地图下高德的数据展示情况。

        可以看到上面的面信息在高德底图中展示良好,但是在天地图中都发生了偏移。有的小的面几乎都偏移了很远,具体情况不一。 这表明,高德采取了偏移算法。下面来看一下如何在Javascript中进行纠偏操作,让坐标按照原来的设置进行展示。

三、Javascript坐标纠偏

        前面讲解了在地图展示的时候会遇到坐标偏移的情况,本节主要来讲解如何在Javascript中进行高德坐标转WGS84坐标,然后在天地图中进行展示。

1、纠偏实现

        关于如何进行纠偏的算法设计,这里不再进行赘述。这里直接贴出代码,经过实战验证,这些代码完全是可以正确运行的。如果您也需要从高德的坐标转为WGS84坐标,可以直接复制即可。

//定义一些常量
var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
var PI = 3.1415926535897932384626;
var a = 6378245.0;
var ee = 0.00669342162296594323;/*** 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换* 即 百度 转 谷歌、高德* @param bd_lon* @param bd_lat* @returns {*[]}*/
function bd09togcj02(bd_lon, bd_lat) {var x_pi = 3.14159265358979324 * 3000.0 / 180.0;var x = bd_lon - 0.0065;var y = bd_lat - 0.006;var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);var gg_lng = z * Math.cos(theta);var gg_lat = z * Math.sin(theta);return [gg_lng, gg_lat]}/*** 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换* 即谷歌、高德 转 百度* @param lng* @param lat* @returns {*[]}*/function gcj02tobd09(lng, lat) {var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);var bd_lng = z * Math.cos(theta) + 0.0065;var bd_lat = z * Math.sin(theta) + 0.006;return [bd_lng, bd_lat]}/*** WGS84转GCj02/谷歌、高德* @param lng* @param lat* @returns {*[]}*/function wgs84togcj02(lng, lat) {if (out_of_china(lng, lat)) {return [lng, lat]}else {var dlat = transformlat(lng - 105.0, lat - 35.0);var dlng = transformlng(lng - 105.0, lat - 35.0);var radlat = lat / 180.0 * PI;var magic = Math.sin(radlat);magic = 1 - ee * magic * magic;var sqrtmagic = Math.sqrt(magic);dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);var mglat = lat + dlat;var mglng = lng + dlng;return [mglng, mglat]}}/*** GCJ02/谷歌、高德 转换为 WGS84 gcj02towgs84* @param lng* @param lat* @returns {*[]}*/function gcj02towgs84(lng, lat) {if (out_of_china(lng, lat)) {return [lng, lat]}else {var dlat = transformlat(lng - 105.0, lat - 35.0);var dlng = transformlng(lng - 105.0, lat - 35.0);var radlat = lat / 180.0 * PI;var magic = Math.sin(radlat);magic = 1 - ee * magic * magic;var sqrtmagic = Math.sqrt(magic);dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);mglat = lat + dlat;mglng = lng + dlng;return [lng * 2 - mglng, lat * 2 - mglat]}}function transformlat(lng, lat) {var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;return ret}function transformlng(lng, lat) {var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;return ret}/*** 判断是否在国内,不在国内则不做偏移* @param lng* @param lat* @returns {boolean}*/function out_of_china(lng, lat) {return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false)}

        接下来,我们将面坐标的构建进行一个简单的封装,跟之前的无转换不同,这里包含了坐标的转换。

function convertStr2DataArrayTrans(strInfo){var resultData = new Array();var dataArray = strInfo.split(";");for(var i = 0;i< dataArray.length;i++){var _tempLatLon = dataArray[i].split(",");//parseFloat() 这里一定要用parseFloat函数,否则+运算后会变成非数字,导致偏移失败。var pointJson = gcj02towgs84(parseFloat(_tempLatLon[0]),parseFloat(_tempLatLon[1]));resultData.push([pointJson[1],pointJson[0]]);}return resultData;
}

        在这里,请注意由于我们的坐标点都是用字符串来表示,因此在传参时一定要转成浮点型来计算,否则将无法正确的计算对应的值。接下来我们将转换后的值叠加到地图当中去:

L.polygon([convertStr2DataArrayTrans(diyishifanStr)],blueStyle).addTo(map).bindPopup("湖南第一师范学院东方红校区转换数据");

        然后在页面中查看一下具体的面数据,为了有所区别,我们将转换后的数据用白色来描述边界。效果如下:

        通过上图可以看到,根据面数据的大小不一,均进行一定的偏移。同时经过我们的数据纠偏操作,成功的将数据进行了天地图的吻合和叠加。通过以上的代码和教程,大家就能掌握具体的纠偏方法。

四、总结

        以上就是本文的主要内容,博客内容主要讲述如何从高德地图中查找我们需要的AOI边界数据,同时讲解如何将采集回来的AOI数据如何在Leaflet地图中展示,其次讲述如何使用JavaScript在前端进行高德数据到WGS84坐标的转换,最后综合展示纠偏前和纠偏后的数据,让您对当前的场景有一个综合的了解和熟悉。行文仓促,定有许多不足支持,如有不足还恳请各位专家朋友在评论区留言指正,不甚感激。

        博文编写过程,纠偏的算法来源于以下博主。

        1、python、js实现WGS84、高德(火星)、百度坐标转换。


http://www.mrgr.cn/news/50846.html

相关文章:

  • 视觉的边界填充、数值计算和腐蚀操作
  • jeston nano配置虚拟环境记录
  • 每日OJ题_WY3小易的升级之路_数学模拟_C++_Java
  • 离宝安羊台山登山口最近的停车场探寻
  • 港大和字节提出长视频生成模型Loong,可生成具有一致外观、大运动动态和自然场景过渡的分钟级长视频。
  • 百度地图怎么上传店铺定位?
  • RK3568平台开发系列讲解(调试篇)嵌入式必备技能:万用表使用指南
  • 99. UE5 GAS RPG 被动技能实现
  • 警惕勒索病毒的最新变种bixi,您需要知道的预防和恢复方法。
  • Java_EE(反射技术)
  • 标准IO:fread/fwrite
  • java真的正在越来越失去竞争力了吗
  • 前端入门学习之css盒子原则
  • 基于Verilog的汉明码编码器/解码器设计
  • 优选算法第一讲:双指针模块
  • 如何使用vllm在服务器上部署模型并调用
  • 高可用之限流-07-token bucket 令牌桶算法
  • [供应链] 库存盘点
  • 【中文注释】planning_scene_tutorial.cpp
  • page cache是怎么回写到存储设备的?