前言

在之前的几篇博客中分别介绍了

在Cesium中实现与CAD的DWG图叠加显示分析 https://www.cnblogs.com/vjmap/p/16541751.html 、

高德地图与CAD图叠加显示方法汇总及优缺点分析 https://www.cnblogs.com/vjmap/p/16694580.html 、

CAD图与互联网地图网页端相互叠加显示技术分析和实现 https://www.cnblogs.com/vjmap/p/16283337.html

不少朋友提出,他们的一些项目现在都是基于百度地图开发的,那能不能实现基于百度地图上加载CAD图形呢?

目前国内主要有以下三种坐标系:

WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。如高德地图、腾讯地图.

GCJ02:又称火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。如OpenStreetMap、天地图。

BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标。

主流瓦片地图的地理坐标系可分以下几类:

  • Web墨卡托投影, 主要有谷歌地图、高德地图、腾讯地图、搜狗地图、必应地图、OpenStreetMap、ArcGIS online、MapQuest、超图、360地图

  • 经纬度直投, 主要有谷歌地球、天地图(经纬直投)

  • 百度墨卡托, 如百度地图

    如上所述,百度地图独立采用了一个自己的坐标系,称为百度坐标系,与众不同。那么怎么样在百度地图上面加载CAD图呢?

实现

(1)百度地图叠加第三方标准图层

百度地图 JSAPI GL提供XYZLayer类支持加载EPSG3857 坐标系统的 WMS 图层、WMTS图层、TMS图层以及自定义栅格图层。 https://lbsyun.baidu.com/index.php?title=jspopularGL/guide/trilateralLayer

其中WMS图层的示例示例代码如下

// 创建位置点var map = new BMapGL.Map("allmap");var point = new BMapGL.Point(-99.41413316281799,39.82354027110903);map.centerAndZoom(point, 4);// tileUrlTemplate 包含OGC标准的WMS地图服务的GetMap接口的参数var wms = BMapGL.XYZLayer({tileUrlTemplate: 'https://ahocevar.com/geoserver/wms?REQUEST=GetMap&SERVICE=WMS&layers=topp:states&version=1.3.0&CRS=EPSG:3857&WIDTH=256&HEIGHT=256&FORMAT=image/png&TRANSPARENT=true&BBOX=[b] ',});map.addTileLayer(wms);

经过示例和文档发现,只要有服务支持EPSG3857的WMS服务就能通过百度地图的API把此图层做为一个第三方标准图层加载过来。

(2)CAD的WMS图层实现

这个在之前的博文中介绍过。

唯杰地图VJMAPCAD图或自定义地图格式WebGIS可视化显示开发提供的一站式解决方案,支持的格式如常用的AutoCADDWG格式文件、GeoJSON等常用GIS文件格式,它使用WebGL矢量图块自定义样式呈现交互式地图, 提供了全新的大数据可视化实时流数据可视化功能。

唯杰地图https://vjmap.com/无需转换可直接打开CAD的DWG格式的图形,并提供了WMS服务接口。

其接口文档为:


/*** wms服务url地址接口*/
export  interface IWmsTileUrl {/** 地图ID(为空时采用当前打开的mapid), 为数组时表时同时请求多个. */mapid?: string | string[];/** 地图版本(为空时采用当前打开的地图版本). */version?: string | string[];/** 图层名称(为空时采用当前打开的地图图层名称). */layers?: string | string[];/** 范围,缺省{bbox-epsg-3857}. (如果要获取地图cad一个范围的wms数据无需任何坐标转换,将此范围填cad范围,srs,crs,mapbounds填为空).*/bbox?: string;/** 当前坐标系,缺省(EPSG:3857). */srs?: string;/** cad图的坐标系,为空的时候由元数据坐标系决定. */crs?: string | string[];/** 地理真实范围,如有值时,srs将不起作用 */mapbounds?: string;/** 宽. */width?: number;/** 高. */height?: number;/** 是否透明. */transparent?: boolean;/** 四参数(x偏移,y偏移,缩放,旋转弧度),可选,对坐标最后进行修正*/fourParameter?: string | string[];/** 是否是矢量瓦片. */mvt?: boolean;/** 是否考虑旋转,在不同坐标系中转换是需要考虑。默认自动考虑是否需要旋转. */useImageRotate?: boolean;/** 旋转时图像处理算法. 1或2,默认自动选择(旋转时有用)*/imageProcessAlg?: number;/** 当前互联网底图地图类型 WGS84(84坐标,如天地图,osm), GCJ02(火星坐标,如高德,腾讯地图), BD09LL(百度经纬度坐标,如百度地图), BD09MC(百度墨卡托米制坐标,如百度地图)*/webMapType?: "WGS84" | "GCJ02" | "BD09LL" | "BD09MC";
}

(3) 实现

我们只要确定CAD图是哪个坐标系即可。因为百度wms的坐标系是EPSG3857,所以上面WMS图层的webMapType参数采用默认的WGS84坐标就可以了。


let cadEpsg = "EPSG:4544";// cad图的espg代号
// 增加cad的wms图层
let wmsUrl = svc.wmsTileUrl({mapid: mapId, // 地图idlayers: layer, // 图层名称bbox: '', // bbox这里不需要srs: "EPSG:3857", crs: cadEpsg
})
// tileUrlTemplate 包含OGC标准的WMS地图服务的GetMap接口的参数
wmsLayer = BMapGL.XYZLayer({tileUrlTemplate: wmsUrl + '&BBOX=[b] ',useThumbData: false
});
map.addTileLayer(wmsLayer);

效果如下图:

从叠加效果来看,和百度地图能按实际坐标叠加到一起。

踩坑记

(1) 没有坐标系的CAD图怎么叠加

上面叠加的图是有坐标系的。然而实际中有些图是没有坐标系的。如一个小区或商铺的平面图,那这种没有坐标系的CAD图怎么叠加到百度地图上呢?就这需要人为的指定公共点。步骤为在CAD图找二个及以上的点,同时在百度地图上相对应的位置也找同样的位置点,通过这些公共点计算出坐标转换的关系去进行叠加。而在唯杰地图的WMS图层中是支持四参数计算的。

根据公共点提供的WMS图层的示例代码为:


// cad上面的点坐标
let cadPoints = [vjmap.geoPoint([587464448.8435846, 3104003685.208661,]),vjmap.geoPoint([587761927.7224838, 3104005967.655292]),vjmap.geoPoint([587463688.0280377, 3103796743.3798513]),vjmap.geoPoint([587760406.0913897, 3103793700.1176634])
];// 在互联网图上面拾取的与上面的点一一对应的坐标(百度坐标)
let webPoints = [vjmap.geoPoint([116.49738632967344,39.969244215079016]),vjmap.geoPoint([116.50000171663382,39.96753915494187]),vjmap.geoPoint([116.49843968869915,39.96613594214925]),vjmap.geoPoint([116.49581440721418,39.967790723887404])
]// 通过坐标参数求出四参数
let epsg3857Points = webPoints.map(w => vjmap.geoPoint(vjmap.transform.convert(w, vjmap.transform.CRSTypes.BD09, vjmap.transform.CRSTypes.EPSG3857)));
let param = vjmap.coordTransfromGetFourParamter(epsg3857Points, cadPoints , false); // 这里考虑旋转
let fourparam = [param.dx, param.dy, param.scale, param.rotate]// wms图层地址
const getCadWmsUrl = (transparent) => {let wmsUrl = svc.wmsTileUrl({mapid: mapId, // 地图idlayers: layer, // 图层名称bbox: '', // bbox这里不需要srs: "EPSG:3857", //fourParameter: fourparam,transparent: transparent,backgroundColor: 'rgba(240, 255, 255)' // 不透明时有效})return wmsUrl
}

通过上面的示例我们发现,其实只要有公共点,使用方法与有坐标系的WMS是差不多的。只是多了一个公共点计算完后成的得到的四参数 fourParameter这个属性。

我们对一个没有坐标系的CAD图,随便在百度地图上叠加了几个公共点,叠加效果如下

(2) 百度地图叠加的WMS图层如果是透明色,则颜色会发生变化

在叠加WMS到百度地图的过程中,发现叠加的CAD图和之前的CAD图颜色不太一致,如下图所示

而在之前和高德和cesium中通过WMS叠加,没有发现这个问题。真是百思不得其解。翻阅了百度地图的文档也没有发现原因。个人感觉和百度地图的渲染绘制有关,百度地图在线提供的WMS示例都是没有透明度叠加的。没办法,只能采用下策,把WMS图层做为一个不透明的图层叠加到百度地图中。具体代码为:

let wmsUrl = svc.wmsTileUrl({mapid: mapId, // 地图idlayers: layer, // 图层名称bbox: '', // bbox这里不需要srs: "EPSG:3857", //fourParameter: fourparam,transparent: false, // 这里透明度要改成false,表示不透明背景backgroundColor: 'rgba(240, 255, 255)' // 不透明时有效,设置不透明背景色
})

最终叠加的效果如下图所示

设置成不透明色后,CAD图的颜色确实和原来的颜色一样的了。美中不足的是因为设置了不透明,所以看不到CAD图覆盖的百度地图下面区域的内容了。

(3) GIS数据和WMS图层对应问题

因为上面的原因,如果设置了不透明,无法看到CAD图覆盖的百度地图下面区域的内容,所以想通过另外一个办法,就是把CAD的数据做为GIS中的geojson数据格式,通过百度地图SDK来进行前端绘制。

在百度地图SDK中提供了加载GeoJSON图层的方法。

地理数据多使用GeoJSON形式存储表达,百度地图JS API GL提供两种不同的方式支持开发者加载自己的GeoJSON数据:
1.提供GeoJSONParse类,满足用户将geojson数据解析为符合百度地图坐标的Overlay数据,用户可得到Overlay属性、坐标数据,进行覆盖物实例化或者其他处理。
2.提供GeoJSONLayer类,满足用户将geojson数据直接解析为覆盖物的图层,并进行交互操作

https://lbsyun.baidu.com/index.php?title=jspopularGL/guide/geoJsonLayer

而在唯杰地图中也可以通过查询的方式,把CAD的数据转为geojson数据,再把geojson转成百度地图所要求的坐标格式即可。

最后代码如下

// 在唯杰地图中通过查询获取CAD图的geojson数据
async function queryData(svc, cadPrj) {let res = await svc.conditionQueryFeature({condition: ``, // 只需要写sql语句where后面的条件内容,字段内容请参考文档"服务端条件查询和表达式查询"fields: "",includegeom: true, // 是否返回几何数据,为了性能问题,realgeom为false时,如果返回条数大于1.只会返回每个实体的外包矩形,如果条数为1的话,会返回此实体的真实geojson;realgeom为true时每条都会返回实体的geojsonrealgeom: true,limit: 100000 //设置很大,不传的话,默认只能取100条}, pt => {// 查询到的每个点进行坐标处理回调let cadPoint = cadPrj.fromMercator(pt);// 转成cad的坐标return cadToWebCoordinate(cadPoint); // 把cad的坐标转成当前地图的经纬度坐标})if (res && res.result && res.result.length > 0) {let features = [];for (let ent of res.result) {if (ent.geom && ent.geom.geometries) {let clr = vjmap.entColorToHtmlColor(ent.color);for (let g = 0; g < ent.geom.geometries.length; g++) {features.push({id: ent.id,type: "Feature",properties: {objectid: ent.objectid + "_" + g,color: clr},geometry: ent.geom.geometries[g]})}}}let geom = {type: "FeatureCollection",features: features};return geom;}
}
// 通过百度地图的sdk加载Geojson图层
function addGeoJsonData(map, data) {var region = data;// https://lbsyun.baidu.com/index.php?title=jspopularGL/guide/geoJsonLayervar cadLayer = new BMapGL.GeoJSONLayer('cad-child', {reference: 'WGS84',dataSource: region,level: -10,polygonStyle: function (properties) {var index = properties.join || 0;return {fillColor: properties.color}},polylineStyle: function (properties) {return {strokeColor: properties.color}},markerStyle: function (properties) {return {}}});map.addGeoJSONLayer(cadLayer, {maxZoom: 24});return cadLayer;
}

最终效果如下

通过GeoJSON的方式,不光能实现透明显示,还能在前端进行交互,如悬浮高亮,点击查询等。缺点就是geojson数据量大,加载速度慢,同时前端渲染也费性能。

最后把WMS图层和GeoJson同时显示,看下什么效果呢?按理说应该是完全叠加在一起才对。

通过WMS图层和GeoJson同时显示,我们发现这两个图层之间存在偏移,当地图移动后级别放大后,又差不多能对应到一起。而在高德(GCJ02火星坐标系)和天地图(WGS84坐标系)的叠加中,WMS图层和GeoJson是能完全叠加对应上的。所以具体原因也百思不得其解,难道是百度地图对WMS图层做了什么特殊处理吗?

结论

通过上面的测试,我们实现了在百度地图中通过WMS的方式加载CAD图,对于无坐标系的CAD图,也可以通过四参数进行叠加。同时也可以通过GeoJSON图层的方式来加载CAD的GIS数据展示。在线体验地址为

百度地图SDK中加载CAD图 https://vjmap.com/demo/#/demo/map/web/09baiduCadLayer

百度地图SDK公共点加载CAD图 https://vjmap.com/demo/#/demo/map/web/09baiduCadLayerFourparam

遇到的坑至今没找到原因的有:

(1)如果把CAD图层通过WMS做为透明图层叠加的时候,颜色会发生变化,原因未知。

(2)同样的坐标转换,通过WMS叠加CAD图和通过Geojson展示CAD图存在偏移,当地图移动后级别放大后,又差不多能对应到一起。原因未知。

如有哪位大神知道原因或有解决方法,敬请告知指导。感谢!

在百度地图中叠加CAD图及GIS数据展示踩坑记相关推荐

  1. echarts地图文字重叠解决方案_ECharts 和百度地图的叠加示例(下)

    前言 汇总了几个 ECharts 地图和百度地图在可视化展示时的综合示例. 主要是在 ECharts 地图和百度地图上叠加展示一些数字.图片.其它图表和轨迹动画. 另外因为每个示例的代码配置项比较繁琐 ...

  2. 基于ECharts+百度地图开发散点扩散图

    基于ECharts+百度地图开发散点扩散图 用ECharts和百度地图,开发散点扩散图,显示TOP5的点. 1.引入Echarts3.2.3 js文件 下载地址为:http://echarts.bai ...

  3. 百度地图中绘制多个点例子

    水平有限,欢迎指正.交流!! <!DOCTYPE html> <html lang="en"><head><meta charset=&q ...

  4. (更新源码)AndroidStudio新手开发:天气app(百度地图api+和风天气api+城市查询+折线展示)

    AndroidStudio新手开发:天气app(百度地图api+和风天气api+城市查询+折线展示) 1.内容简介 2.环境配置 3.导入他人demo 4.AS项目分析 5.天气项目流程 6.数据探寻 ...

  5. 百度地图Javascript使用海量点加载数据并自定义图标

    ** 百度地图Javascript使用海量点加载数据并自定义图标 由于数据量较大时使用Marker点在地图上标点会造成浏览器卡死,点聚合的形式可以解决数据量大浏览器卡死问题,但是移除点时点聚合不太好用 ...

  6. 百度地图 osm地图 leaflet echarts webapck的组合使用时的踩坑记录

    webpack+百度地图 创建 script标签进行加载 export function MP(ak){ return new Promise(function (resolve, reject){ ...

  7. 【百度地图API】如何利用自己的数据制作社交地图?只显示可视区域内的标注...

    原文:[百度地图API]如何利用自己的数据制作社交地图?只显示可视区域内的标注 摘要:如果你自己的数据已经超过1万个,如何进行合理的显示?除了聚合marker外,还有一个办法.那就是,只显示可视区域内 ...

  8. 【百度地图API】如何利用自己的数据制作社交地图?只显示可视区域内的标注

    [百度地图API]如何利用自己的数据制作社交地图?只显示可视区域内的标注 摘要:如果你自己的数据已经超过1万个,如何进行合理的显示?除了聚合marker外,还有一个办法.那就是,只显示可视区域内的标注 ...

  9. Typora+PicGo-core+SMMS图床踩坑记

    Typora+PicGo-core+SMMS图床踩坑记 一.安装PicGo-Core 二.安装smms v2 API插件 三.配置PicGo-Core 四.最终效果 五.总结 最近把Typora更新后 ...

最新文章

  1. mysql数据库常用命令
  2. 一张图说明 函数, 实例(对象), 原型之间的关系
  3. 别拒绝生命中偶尔的初恋
  4. Spark机器学习MLlib系列1(for python)--数据类型,向量,分布式矩阵,API
  5. 快速排序时间复杂度为O(n×log(n))的证明
  6. 小功能 获取一段汉字的拼音首字母
  7. PHP关于VC11,VC9,VC6以及Thread Safe和Non Thread Safe版本选择
  8. 【视觉项目】【day5】8.25号实验记录(修完BUG,28张测试图,13个样本,四张测试图误判,这比之前效果好很多了)
  9. 安卓手机阅读器_乐应用|安卓手机本地阅读的不二之选
  10. 交付仅一周!售价超百万的特斯拉新车当街起火,马斯克曾狂夸其安全性
  11. oracle日期相减工作日_oracle 日期相减 转载
  12. 系统分析师资料_软考 系统分析师考试通过总结
  13. Face alignment at 3000 FPS via Regressing Local Binary Features
  14. HD2做Windows Phone 7开发机小记(上)
  15. react package.json 修改proxy进行前端跨域,通过修改homepage,更改打包路径
  16. python编程语言图解_Python程序运行原理图文解析
  17. 国家制图标准适用于手工制图和计算机制图,机械制图国家标准与计算机绘图
  18. ROS1 noetic + depthai_ros教程
  19. 编程珠玑第三章笔记加习题解答
  20. ROS2机器人资料21-11-02(全面升级)

热门文章

  1. 蓝桥杯-打印菱形/字符串截断
  2. 裴蜀定理(详细定义+应用+模板)
  3. Cobalt Strike 域内渗透
  4. ListView双击的行
  5. python 微博自动点赞_用 Python 自动定时发微博
  6. 新入手Seagate希捷1TB移动硬盘1t USB3.0一个
  7. 黄金分割法求函数最小值
  8. linux执行脚本提示文件忙,linux定时执行脚本文件fgo 封号吗
  9. PostOffice
  10. kotlin入门,Android快速转战Kotlin教程,重难点整理