明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 837|回复: 2

(在线编辑DWG)网页CAD与Mapbox结合实现在线地图CAD编辑

[复制链接]
发表于 2025-8-15 09:58:53 | 显示全部楼层 |阅读模式
本帖最后由 MxDraw 于 2025-8-15 10:04 编辑

一、项目概述
MxCAD Mapbox 结合项目是一个创新性的解决方案,在线CAD编辑功能与地图服务无缝集成。该项目通过自定义的 Mapbox 版本支持中国国家大地坐标系(CGCS2000),并结合MxCAD 强大的在线CAD编辑能力,实现了在地图上直接加载、编辑和管理CAD图纸的功能。

核心技术栈包括:
- 修改版 Mapbox GL JS(支持 CGCS2000
- MxCAD 在线 CAD 编辑引擎
- WebAssembly 技术
- TypeScript/JavaScript



二、Mapbox 修改版支持 CGCS2000 坐标系
2.1、CGCS2000 坐标系介绍
CGCS2000China Geodetic Coordinate System 2000)是中国国家大地坐标系,是中国测绘基准的重要组成部分,用于替代原有的北京 54 坐标系和西安 80 坐标系,在国内GIS 应用中,支持CGCS2000是必不可少的功能。

2.2基于@cgcs2000/mapbox-gl 的坐标系扩展
项目使用了自定义的`@cgcs2000/mapbox-gl`包,这是对标准 Mapbox GL JS 的扩展,主要增加了对 CGCS2000 坐标系的支持。在代码中的引用方式:
  1. <font size="3">import {
  2.   type AnyLayer,
  3.   Map as _Map,
  4.   type AnySourceData,
  5.   LngLat,
  6.   Point,
  7. } from "@cgcs2000/mapbox-gl";
  8. import mapboxgl from "@cgcs2000/mapbox-gl";</font>
复制代码
我们对修改后的 js 进行了处理,使其支持 CGCS2000 坐标系和 mxcad 的交互。


2.3坐标转换与投影实现
在使用时我们依然要扩展了 Map 类,扩展的方法都是必须的,用于配合 mxcad 实现坐标的转换和交互:
  1. <font size="3">// 扩展重写Map类
  2. export class Map extends _Map {
  3.   public dom_mousePos(event: any) {
  4.     return this.dom_mousePos_imp(this.getCanvasContainer(), event);
  5.   }
  6.   public lnglat_to_mercator(lng: any, lat: any): any {
  7.     let pt = mapboxgl.MercatorCoordinate.fromLngLat([lng, lat], 0);
  8.     return pt;
  9.   }
  10.   public mercator_to_lnglat(x: number, y: number, z: number): any {
  11.     let mecatorcoord = new mapboxgl.MercatorCoordinate(x, y, z);
  12.     return mecatorcoord.toLngLat();
  13.   }
  14.   public mercatorCoordinate_from_LngLat(
  15.     lngLat: number[],
  16.     modelAltitude: number
  17.   ): any {
  18.     return mapboxgl.MercatorCoordinate.fromLngLat(lngLat as any, modelAltitude);
  19.   }
  20.   protected getScaledPoint(
  21.     el: HTMLElement,
  22.     rect: ClientRect,
  23.     e: MouseEvent | WheelEvent | Touch
  24.   ) {
  25.     const scaling =
  26.       el.offsetWidth === rect.width ? 1 : el.offsetWidth / rect.width;
  27.     return new Point(
  28.       (e.clientX - rect.left) * scaling,
  29.       (e.clientY - rect.top) * scaling
  30.     );
  31.   }
  32.   protected dom_mousePos_imp(el: HTMLElement, e: MouseEvent | WheelEvent) {
  33.     const rect = el.getBoundingClientRect();
  34.     return this.getScaledPoint(el, rect, e);
  35.   }
  36. }</font>
复制代码

三、MxCAD Mapbox 的结合实践
3.1MxCAD在线CAD编辑引擎与Mapbox集成
MxCAD是一个功能强大的在线CAD 编辑引擎,通过WebAssembly 技术实现了高性能的CAD 渲染和编辑功能。在项目中,我们将 MxCAD Mapbox 无缝集成,实现了在地图上直接操作 CAD 图纸的能力关键集成代码:
  1. <font size="3">import { MxMap } from "mxcad";
  2. let mx_map = new MxMap();
  3. // 设置坐标点对齐,将CAD坐标系与地图坐标系对齐
  4. //  图纸中的中心在地址上的位置,单位经纬度
  5. let mapOrigin = [116.42787, 39.93232];
  6. // 小=右,大=下
  7. //  CAD图纸中的中心中,CAD图纸单位
  8. let cadOrigin = [506411.1543, 307348.2786];
  9. // 1 CAD单位与米的比例 这里 1 cad单位是1m
  10. let meterInCADUnits = 1;
  11. mx_map.setCoordinatePointAlignment(mapOrigin, cadOrigin, meterInCADUnits);
  12. const style = {
  13.   version: 8,
  14.   sources: {
  15.     tianditu: {
  16.       type: "raster",
  17.       tiles: [
  18.         "http://t0.tianditu.gov.cn/img_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=天地图的密钥",
  19.       ],
  20.       tileSize: 256,
  21.       maxzoom: 18,
  22.     },
  23.   },
  24.   layers: [
  25.     {
  26.       id: "tianditu-layer",
  27.       type: "raster",
  28.       source: "tianditu",
  29.       minzoom: 0,
  30.       maxzoom: 18,
  31.     }
  32.   ],
  33. };
  34. let map = new Map({
  35.   // Mapbox GL JS 进行地图渲染的 HTML 元素,或该元素的字符串 id 。该指定元素不能有子元素。
  36.   container: "map",
  37.   // crs: 'EGSP:4490',
  38.   // 地图最小缩放级别(0-24)。
  39.   minZoom: 0,
  40.   // 地图最大缩放级别(0-24)。
  41.   maxZoom: 24,
  42.   // 地图初始化时的地理中心点
  43.   center: mapOrigin,
  44.   // 地图初始化时的层级
  45.   zoom: 16,
  46.   // 地图的 Mapbox 配置样式
  47.   style: style,
  48. });
  49. // 你需要打开的图纸
  50. let cadFile = new URL("../../public/demo/line3.dwg.mxweb", import.meta.url).href;
  51. // 在地图加载完成后初始化MxCAD
  52. map.on("style.load", async function () {
  53.   // 设置canvas ID
  54.   map.getCanvas().id = "myCanvas";
  55.   // 创建MxCAD实例
  56.   mx_map.create(map, {
  57.     locateFile: (fileName: string) => {
  58.       return new URL(
  59.         `../../node_modules/mxcad/dist/wasm/${mode}/${fileName}`,
  60.         import.meta.url
  61.       ).href;
  62.     },
  63.     fileUrl: cadFile,
  64.     middlePan: true,
  65.     viewBackgroundColor: load_local_title
  66.       ? { red: 0, green: 0, blue: 0 }
  67.       : { red: 255, green: 255, blue: 255 },
  68.   });
  69. });</font>
复制代码

3.2坐标系统对齐实现
坐标系统对齐是 MxCAD Mapbox 结合的核心。我们通过`setCoordinatePointAlignment`方法将 CAD 坐标系与地图坐标系进行对齐:
  1. <font size="3">// 图纸中的中心在地址上的位置,单位经纬度
  2. let mapOrigin = [116.42787, 39.93232];
  3. // CAD图纸中的中心中,CAD图纸单位
  4. let cadOrigin = [506411.1543, 307348.2786];
  5. // CAD单位与米的比例
  6. let meterInCADUnits = 1;
  7. // 设置坐标点对齐
  8. mx_map.setCoordinatePointAlignment(mapOrigin, cadOrigin, meterInCADUnits);</font>
复制代码
这样设置后,当用户在地图上点击时,可以获取对应的 CAD 坐标:
  1. <font size="3">map.on("click", async function (e) {
  2.   let { lng, lat } = e.lngLat;
  3.   // 获取墨卡托坐标
  4.   let pt = mapboxgl.MercatorCoordinate.fromLngLat([lng, lat], 0);
  5.   // 转换为CAD坐标
  6.   let ptCAD = mx_map.mercatorCoord2CAD(pt.x, pt.y);
  7.   console.log("CAD坐标:", JSON.stringify(ptCAD));
  8. });</font>
复制代码

四、天地图 CGCS2000 加载实现
4.1 天地图服务介绍
天地图是中国国家测绘地理信息局主办的国家地理信息公共服务平台,提供了基于 CGCS2000 坐标系的地图服务。在本项目中,我们集成了天地图作为底图服务。


4.2 天地图key 申请流程
1. 访问天地图开发者平台:http://lbs.tianditu.gov.cn/
2. 注册并登录开发者账号
3. 选择地图API
4. 申请key
5. "控制台"页面选择"创建应用"
6. 填写应用名称、应用类型等信息
7. 提交后获取应用 key
8. 使用获取的 key 替换代码中的 tk 参数



4.3 天地图 CGCS2000 图层配置
在项目中,我们通过以下方式配置天地图图层:
  1. <font size="3">const style = {
  2.   version: 8,
  3.   sources: {
  4.     tianditu: {
  5.       type: "raster",
  6.       tiles: [
  7.         "http://t0.tianditu.gov.cn/img_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=",
  8.       ],
  9.       tileSize: 256,
  10.       maxzoom: 18,
  11.     },
  12.   },
  13.   layers: [
  14.     {
  15.       id: "tianditu-layer",
  16.       type: "raster",
  17.       source: "tianditu",
  18.       minzoom: 0,
  19.       maxzoom: 18,
  20.     }
  21.   ]
  22. } as mapboxgl.Style;</font>
复制代码
注意:在实际使用时,需要将上述代码中的`tk=`后面添加您申请的天地图key

天地图提供了多种图层类型,常用的包括:
- `img_c`: 影像底图
- `vec_c`: 矢量底图
- `cva_c`: 矢量注记
- `cia_c`: 影像注记
可以根据需求选择不同的图层类型。

MxCADMapbox 的结合为CAD图纸的在线编辑与地理位置关联提供了强大的解决方案。通过支持CGCS2000坐标系和集成天地图服务,该项目特别适合中国国内的 GIS 应用开发。项目的核心功能包括坐标系转换、CAD 图纸在地图上的精确定位与编辑、图层管理等,为城市规划、管网管理、不动产管理等领域提供了有力的技术支持。

4.4集成mxcad在线CAD项目地图模式
刚刚我们介绍了从01MxCADMapbox结合实现,但是所有CAD的功能都要从头开发, 所以我们提供了在线CAD项目集成方案, 同时可以启动地图模式, 简单开发一个扩展插件轻松集成 MxCAD Mapbox 结合实现在线地图 CAD 编辑系统。
开发前我们一定要下载[MxDraw云图开发包然后解压可以看到一个exe程序点击运行点击打开MxCAD代码开发目录就可以看到dist目录了,[查看详情

扩展插件开发
通过开发一个简单的插件,我们可以快速集成MxCADMapbox。以下是一个基本的插件代码示例:
  1. <font size="3">import { MxCADPluginBase, MxCADUI, MxMap } from "mxcad";
  2. import { MxFun } from "mxdraw";
  3. import * as mapboxgl from "mapbox-gl";
  4. import { Map } from "mapbox-gl";
  5. class MxCADPlugin extends MxCADPluginBase {
  6.     constructor() {
  7.         super()
  8.         this.map_default_data = {
  9.             /**  地图与CAD图纸的对齐位置 */
  10.             mapOrigin: [116.42787, 39.93232],
  11.             /** CAD图纸与地图的对齐点 */
  12.             cadOrigin: [506411.1543, 307348.2786],
  13.             meterInCADUnits: 1,
  14.             /** mapbox地图token */
  15.             mapbox_accessToken: '',
  16.             /** 需要打开的cad图纸 */
  17.             openFile: new URL("../demo/line3.dwg.mxweb", import.meta.url).href,
  18.             /** 栅格瓦片图层列表 */
  19.             rasterTileLayerList: []
  20.         }
  21.     }
  22. }
  23. let mxcadui;
  24. // cad应用加载开始
  25. MxFun.on("mxcadApplicationStart", (mxcaduiimp) => {
  26.     mxcadui = mxcaduiimp;
  27.     mxcadui.init(new MxCADPlugin());
  28. });
  29. let mx_map;
  30. let map;
  31. // 初始化gis
  32. MxFun.on("mxcadApplicationInitMap", () => {
  33.     mx_map = mxcadui.mxmap;
  34.     map = mx_map.getMapbox()
  35.     map.getCanvas().id = "mxcad"
  36.     // 可以在这里设置地图样式
  37.     // map.setStyle({
  38.     //     version: 8,
  39.     //     sources: {
  40.     //         tianditu: {
  41.     //             type: 'raster',
  42.     //             tiles: [
  43.     //                 'http://t0.tianditu.gov.cn/img_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=密钥'
  44.     //             ],
  45.     //             tileSize: 256,
  46.     //             maxzoom: 18
  47.     //         }
  48.     //     },
  49.     //     layers: [
  50.     //         {
  51.     //             id: 'tianditu-layer',
  52.     //             type: 'raster',
  53.     //             source: 'tianditu',
  54.     //             minzoom: 0,
  55.     //             maxzoom: 18
  56.     //         }
  57.     //     ]
  58.     // })
  59.     map.on("click", async function (e) {
  60.         let { lng, lat } = e.lngLat;
  61.         let pt = mapboxgl.MercatorCoordinate.fromLngLat(
  62.             [lng, lat],
  63.             0
  64.         );
  65.         console.log("经纬度坐标:", JSON.stringify([lng, lat]));
  66.         let ptCAD = mx_map.mercatorCoord2CAD(pt.x, pt.y);
  67.         console.log("CAD坐标:", JSON.stringify(ptCAD))
  68.     });
  69. });</font>
复制代码

插件部署与配置
1. 插件文件结构
   将上述JavaScript代码保存为一个index.js文件,放置在`dist/plugins/mapPlugin/`目录下(目录名可自定义)。

2. 配置config.json
   `dist/plugins/config.json`文件中添加插件配置:
  1. <font size="3">   {
  2.      "plugins": \[
  3.        "loginPlugin",
  4.        {"name": "pluginCodeEdit", "isAfterLoad": true, "dir": true, "version": "1.0.0"},
  5.        {"name": "pluginIdentifyPattern", "isAfterLoad": true, "dir": true, "version": "1.0.0"},
  6.        {"name": "pluginBaseTemplate", "isAfterLoad": false, "dir": true, "version": "1.0.0"},
  7.        {"name": "mapPlugin", "isAfterLoad": false, "dir": true, "version": "1.0.0"}
  8.      ]
  9.    }</font>
复制代码
注意:
   - 插件名称应与目录名一致
   - `isAfterLoad`表示是否在主应用加载完成后再加载插件
   - `dir`设置为true表示插件在独立目录中

启动地图模式
访问应用时,在URL后添加`?map=true`参数即可启动地图模式,例如:
http://your-domain.com/mxcad/?map=true

集成到现有项目
您可以通过以下方式将MxCAD地图模式集成到现有项目中:
1. 使用iframe嵌入
  1. <font size="3">   <iframe src="http://your-domain.com/mxcad/?map=true" width="100%" height="600px"></iframe>
  2. </font>
复制代码

2. 页面通信
通过postMessage实现父页面与iframe中的MxCAD应用通信:
  1. <font size="3">   // 父页面发送消息
  2.    const mxcadFrame = document.getElementById('mxcad-frame');
  3.    mxcadFrame.contentWindow\.postMessage({
  4.      type: 'COMMAND',
  5.      command: 'ZOOM\_TO',
  6.      data: { center: \[116.42787, 39.93232], zoom: 16 }
  7.    }, '\*');
  8.    // 在MxCAD插件中接收消息
  9.    window\.addEventListener('message', (event) => {
  10.      if (event.data.type === 'COMMAND') {
  11.        // 处理来自父页面的命令
  12.        handleCommand(event.data);
  13.      }
  14.    });
  15.    function handleCommand(data) {
  16.      if (data.command === 'ZOOM\_TO' && map) {
  17.        map.flyTo({
  18.          center: data.data.center,
  19.          zoom: data.data.zoom,
  20.          essential: true
  21.        });
  22.      }
  23.    }</font>
复制代码
通过这种方式,您可以在自己的项目中轻松集成MxCADMapbox结合的在线地图CAD编辑系统,同时保留对地图和CAD操作的完全控制能力,同时集成了mxcad在线CAD项目的各种功能。

4.5
坐标系统选择注意事项
在集成MxCADMapbox时,坐标系统的选择非常重要:
1. CGCS2000WGS84的区别
   - 本项目中采用的是CGCS2000坐标系
   - 默认的Mapbox使用的是WGS84坐标系
   - 两种坐标系在中国区域的偏差约为几米到几十米不等

2. 坐标系选择建议
   - 如果您的项目需要精确对应中国国内地理位置,建议使用修改版的Mapbox CGCS2000
   - 使用CGCS2000时,所有经纬度输入和输出都是CGCS2000坐标系下的值
   - 如果对精度要求不高或主要用于国际项目,可以使用默认的MapboxWGS84+ 补丁方式
   - 使用默认WGS84时,无需替换为修改版的Mapbox

3. 坐标转换
如果需要在两种坐标系统之间进行转换,可以使用相关转换工具或库,例如proj4js
  1. <font size="3">// 使用proj4js进行坐标转换示例
  2.    import proj4 from 'proj4';
  3.    // 定义坐标系
  4.    proj4.defs('EPSG:4326', '+proj=longlat +datum=WGS84 +no\_defs'); // WGS84
  5.    proj4.defs('EPSG:4490', '+proj=longlat +ellps=GRS80 +no\_defs'); // CGCS2000
  6.    // WGS84转CGCS2000
  7.    const wgs84Point = \[116.3912, 39.9073]; // 北京某点WGS84坐标
  8.    const cgcs2000Point = proj4('EPSG:4326', 'EPSG:4490', wgs84Point);
  9.    console.log('CGCS2000坐标:', cgcs2000Point);</font>
复制代码
选择合适的坐标系对于项目的精确定位至关重要,特别是在涉及到工程测量、规划设计等高精度应用场景中。


本帖子中包含更多资源

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

x

评分

参与人数 1明经币 +1 收起 理由
gzxl + 1 神马都是浮云

查看全部评分

回复

使用道具 举报

发表于 2025-8-15 16:37:20 | 显示全部楼层
你太强了吧,真的很牛逼
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-8-27 16:57:09 | 显示全部楼层
你有种再说一遍 发表于 2025-8-15 16:37
你太强了吧,真的很牛逼

感谢关注
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2026-1-9 04:28 , Processed in 0.199589 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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