找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 52577|回复: 0

CAD与GIS集成说明 (2022-08-19)

[复制链接]
发表于 2023-1-6 15:50:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
mapbox地图与cad图纸的集成示例代码说明
点击演示示例查看效果点击下载示例源码
mapbox-gl.js是通过webgl渲染交互式地图的js库 利用mapbox提供的自定义图层实现渲染mxdraw中的CAD图纸(three.js 场景)。
如果不了解mapbox-gl.js可以参考中文官方文档/ 国际站什么是mxdraw?https://mxcadx.gitee.io/mxdraw_docs/
mxdraw是基于three.js进行二次开发实现在线CAD图纸的预览,所以本质上我们还是是以mapbox-gl为主,将three.js中的物体对象显示在mapbox-gl的一个自定义图层中。
下面代码是mapbox和mxdraw结合使用的示例代码,先安装对应的依赖包:
  1. npm install mapbox-gl mxdraw three@0.113.2
复制代码
  1. <div id="map"></div>
复制代码
  1. import mapboxgl from "mapbox-gl";
  2. import Mx from "mxdraw"
  3. import * as THREE from "three"

  4. // token需要自己在mapbox官网申请
  5. mapboxgl.accessToken = "pk.eyJ1IjoibWFvcmV5IiwiYSI6ImNqNWhrenIwcDFvbXUyd3I2bTJxYzZ4em8ifQ.KHZIehQuWW9AsMaGtATdwA"

  6. // 北京位置的经纬度
  7. const center = [116.391305, 39.90553]

  8. const map = new mapboxgl.Map({
  9.      // Mapbox GL JS 进行地图渲染的 HTML 元素,或该元素的字符串 id 。该指定元素不能有子元素。
  10.     container: 'map',
  11.     // 地图位置
  12.     center,
  13.     // 地图样式
  14.     style: 'mapbox://styles/mapbox/streets-v11',
  15.     zoom: 16
  16. })

  17. // 图纸或者模型的高度
  18. const modelAltitude = 100;

  19. // 将 LngLat 投影转换为 墨卡托投影坐标
  20. const point = mapboxgl.MercatorCoordinate.fromLngLat(
  21.     center,
  22.     modelAltitude
  23. );
  24. // 返回在此纬度上以墨卡托坐标单位表示的1米距离。
  25. // 对于现实世界中使用米单位的坐标,这自然提供了转换为墨卡托投影坐标的比例尺
  26. const lDistForM = point.meterInMercatorCoordinateUnits();

  27. // 当前决定该cad图纸在现实中的范围是1公里
  28. const lCADArea = 1000 * lDistForM * 1;

  29. // 提供一些必要的mapbox信息,并且赋予了一些mxdraw提供的核心方法
  30. let mxMap = {
  31.     // mapbox生成的canvas元素
  32.     canvas: null,
  33.     // 自定义图层提供的gl上下文
  34.     gl: void 0,
  35.     // cad图纸的位置1
  36.     cadLocation1: new THREE.Vector3(),
  37.     // cad图纸的位置2
  38.     cadLocation2: new THREE.Vector3(),
  39.     // 海拔高度
  40.     elevation: 0,
  41.     // 自定义图层信息
  42.     customLayer: {},
  43.     // cad图纸控件对象
  44.     mxObj: null,
  45.     // 坐标系转换的矩阵1
  46.     matCadToMap: new THREE.Matrix4(),
  47.      // 坐标系转换的矩阵1
  48.     matMapToCad: new THREE.Matrix4(),
  49.     // 自定义图层的矩阵
  50.     matrix: void 0,
  51.     // 渲染函数
  52.     render(gl, matrix){

  53.     },
  54.     /** 坐标系相互转换的方法 */
  55.     cadToMercatorCoord(pt) {
  56.         pt.applyMatrix4(this.matCadToMap);
  57.         return new mapboxgl.MercatorCoordinate(pt.x,pt.y,pt.z);
  58.     },
  59.    
  60.     mercatorCoordToCad(pt){
  61.         let ptRet = new THREE.Vector3(pt.x,pt.y,pt.z);
  62.         ptRet.applyMatrix4(this.matMapToCad);
  63.         return ptRet;
  64.     },

  65.     cadLongToMercatorCoord(len){
  66.         let pt1 = new THREE.Vector3(0,0,0);
  67.         let pt2 = new THREE.Vector3(len,0,0);
  68.         pt1.applyMatrix4(this.matCadToMap);
  69.         pt2.applyMatrix4(this.matCadToMap);
  70.         return pt1.distanceTo(pt2);
  71.     }

  72. }
  73. // 通过以上信息从而确定cad图上的具体位置
  74. mxMap.cadLocation1 = new THREE.Vector3(point.x - lCADArea / 2, point.y - lCADArea, point.z);
  75. mxMap.cadLocation2 = new THREE.Vector3(point.x + lCADArea, point.y + lCADArea / 2, point.z);

  76. // 新增一个mapbox自定义图层
  77. const customLayer = {
  78.     id: "3d-model", // 任意不重复的ID
  79.     type: "custom",
  80.     renderingMode: "3d",
  81.     async onAdd(map, gl) {
  82.         // 同步加载mxdraw核心库
  83.         await Mx.loadCoreCode()
  84.         // 拿到mapbox的canvas元素
  85.         mxMap.canvas = map.getCanvas();
  86.         // 以及webgl上下文
  87.         mxMap.gl = gl
  88.         // 创建图纸控件对象
  89.         Mx.MxFun.createMxObject({
  90.             // mapBox 提供 mapbox的一些必要参数
  91.             mapBox: mxMap,
  92.             // 要打开的图纸
  93.             cadFile: "../../demo/buf/$hhhh.dwg",
  94.             callback: (mxObj) => {
  95.                 mxMap.mxObj = mxObj;
  96.                 mxObj.addEvent("loadComplete", () => {
  97.                     // 更新mapbox
  98.                     map.triggerRepaint()
  99.                 });
  100.             }
  101.         });
  102.   
  103.     },
  104.     render(gl, matrix) {

  105.         // 赋值矩阵信息
  106.         mxMap.matrix = matrix
  107.         // 在创建图纸后会提供一个渲染函数,用于更新图纸
  108.         mxMap.render(gl, matrix);

  109.         // 刷新mapbox
  110.         map.triggerRepaint()
  111.     }
  112. };
  113. // 赋值这个自定义图层的信息
  114. mxMap.customLayer = customLayer
  115. //  添加自定义图层

  116. map.on('style.load', ()=> {
  117.     // 添加自定义图层
  118.     map.addLayer(customLayer)
  119. })
复制代码


Mapbox集成更多其他GIS库的能力
Mapbox 与 L7框架
我们可以在mapbox基础上扩展 L7框架的能力,使mapbox的功能更加强大
L7是由蚂蚁金服 AntV 数据可视化团队推出的基于 WebGL 的开源大规模地理空间数据可视分析开发框架
点击[AntV L7 官方文档]查看使用L7提供的功能
以下是简单的L7结合mapbox的集成代码:
  1. <div id="map"></div>
复制代码
  1. import { Scene, Mapbox } from "@antv/l7"
  2. import mapboxgl from "mapbox-gl";
  3. // 首先创建mapbox地图
  4. mapboxgl.accessToken = "pk.eyJ1IjoibWFvcmV5IiwiYSI6ImNqNWhrenIwcDFvbXUyd3I2bTJxYzZ4em8ifQ.KHZIehQuWW9AsMaGtATdwA"
  5. const map = new mapboxgl.Map({
  6.     container: 'map',
  7.     center,
  8.     style: 'mapbox://styles/mapbox/streets-v11',
  9.     zoom: 16
  10. })

  11. // 实例化L7提供的场景
  12. const l7Scene = new Scene({
  13.     id: 'map',
  14.     logoVisible: false,
  15.     // 这里提供mapbox的地图
  16.     map: new Mapbox({
  17.         mapInstance: map
  18.     })
  19. })
复制代码

按照上述代码,在mapbox地图上就可以使用L7提供的能力了。
更加详细的代码请参考源码示例中  src/L7 文件夹的代码,点击查看:[github]/ [gitee]
mapbox 与 deck.gl
deck.gl是一个webgl支持的框架,用于对大型数据集进行可视化探索性数据分析。
点击 [deck.gl文档]查看使用说明deck.gl 可以做到与mapbox无缝衔接,集成方法可以看[@deck.gl/mapbox模块的使用文档]
也可以通过查看示例源码中的src/deckgl文件夹 查看deck.gl是如何在mapbox-gl 中使用的(每一个TS文件代表一个单独的示例),
前往[github]/  [gitee]查看源码。
mapbox 与 three.js
因为mxdraw库是基于three@0.113.2进行二次开发的(因为对源代码进行了一些修改,建议只使用three@0.113.2这个版本)。
添加的CAD图纸本质上是由three.js的物体对象构成的,所有我们也可以添加其他的three.js的物体对象。
点击 [three.js中文文档] 或者 [three.js官方文档] 查看具体API使用说明
在示例源码中的src/mxthree 文件夹中也提供了一些写好的物体对象加载到mapbox地图中的示例代码
可以通过在 [github]或者[gitee] 查阅具体的代码实现



VueMapboxMxdraw示例源码的详细说明
概述
首先,示例源码是基于Vue3和mapbox-gl实现的一个交互式地图示例展现页面,比如上述与各其他由webgl封装的各种可以和mapbox-gl集成的前端库的使用示例,以及CAD图纸展现在mapbox-gl地图中的示例,我们可以理解为mxdraw是专注处理CAD图纸的渲染,而mapbox-gl 是地图的渲染,其他展示的库也都是围绕mapbox-gl展开的。
初始化
整个初始化流程是: Vue-> mapbox-gl -> mxdraw -> 示例入口函数
所有的初始化函数都叫 init
1. 首先可以我们应该找到src/components 文件夹中的HelloWorld.vue 在其中就可以找到 init 方法, 就是执行mapbox的初始化工作。
2. mapbox-gl 的初始化就包含了mxdraw 的初始化工作,我们可以在 src/mapbox/init.ts 中找到init 方法 在地图样式加载完成的事件中可以找到如下代码,其中mxDrawInit就是 mxdraw 的初始化 (该函数可以在src/mxdraw/init 方法中找到)
  1. // ...
  2. map.on("style.load", async () => {
  3.     // ...
  4.     let kilometers = param.kilometers ? param.kilometers: 1;

  5.     // 初始化图纸显示
  6.     mxMap = await mxDrawInit(map, ptCADOrigin,kilometers, cadFile);
  7.     // ...
  8. });
复制代码
3. 在mxdraw的初始化中,
cmdInit
通过命令模式注册,各种示例的入口函数. 在src/mxdraw/cmdInit.ts 可以看见所有的示例入口函数,可以根据文件引入位置查看对应的示例代码文件,如下代码所示:
  1. import { addMinMpaContorl } from "@/mapbox/control/addMinMpaContorl"
  2. // ...
  3. MxFun.addCommand('addMinMpaContorl', addMinMpaContorl)
  4. // ...
复制代码
示例切换
示例切换就是执行对应的在初始化时注册的命令, 在src/components/MyMenu.vue  中可以看到每个菜单按钮数据都有个cmd属性,就表示其对应的命令。
每次执行一个命令前都会删掉当前mapbox-gl 的Map对象 重新初始化mapbox, 在整个删除过程中会涉及到mxdraw绘制three的资源没有得到释放的问题, 可以在 src/mxdraw/init.ts  中找到如下代码:

可以在 src/mxdraw/ResourceTracker.ts 中就专门为three的资源释放和追踪提供的方法类, 这样在删除地图,资源得到释放后,就不会造成页面卡顿现象了。
其他目录(mapbox为主)文件简要说明:
* src/mapbox/Map 是对mapbox-gl中的Map类的一次封装, 重构或者新增了一些方法, 在如给标记点设置高度、线段3D拉伸等地方可能会用到这些方法。
* src/animate.ts 利用了"d3-ease"提供的线性插值的能力封装了对应的方法, 提供了创建线性动画的方法以及添加动画等。
* src/mapbox/graphics 是对mapbox 使用图层展示 geojson数据的一个封装,可以创建一个自由操作的不同类型的不同形状的图形,以及基于这个去图形类去实现更多图形的示例。
* src/mapbox/draw 主要是对mapbox-gl-draw 提供的绘制能力进行了封装,其中主要是绘制工具条和绘制能力的封装, 展示了如何扩展mapbox-gl-draw的绘制功能, 对杂乱且不兼容的各种扩展的绘制能力进行了一定程度的整合兼容。
* src/mapbox/animate 是一些动画效果的示例。
* src/mapbox/calculate 是结合 turf 这个库 使用geojson数据参与计算的示例。
* src/mapbox/control 是mapbox 的各种控件使用示例,如上说的mapbox-gl-draw就是一个控件。  
* src/mapbox/demo 是mapbox的一些demo示例,如mapbox加载three.js的3D城市、地图中加载对应位置的CAD图纸等等。
* src/mapbox/layer 是mapbox的一些常见使用图层的示例。
* src/mapbox/plugins 是一些常见的插件, 如city 就是加载3d城市,InternetMap就是加载各种第三方地图...
* src/mapbox/pointTag 就是实现各种点标记的效果的示例。
* src/mapbox/style 提供了各种mapbox的地图样式的配置信息。
* patches文件夹中是修改node_modules 中一些依赖包的记录, 都是一些小改动,主要是解决一些整合功能出现的兼容性问题。

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-11-17 19:49 , Processed in 0.187349 second(s), 33 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表