如何实现通过Leaflet加载dwg格式的CAD图

前言?在前面介绍了通过openlayers加载dwg格式的CAD图并与互联网地图叠加,openlayers功能很全面,但同时也很庞大,入门比较难,适合于大中型项目中 。而在中小型项目中,一般用开源的leaflet比较多, leaflet小而美,插件很多 。本文介绍如何用Leaflet来加载DWG格式的CAD图 , 并在上面做应用开发 , 如与互联网地图叠加显示等 。
Leaflet介绍? Leaflet 是领先的用于移动友好交互式地图的开源 JavaScript 库 。仅仅重约 39KB 的 JS,它拥有大多数开发者所需要的所有地图功能 。Leaflet 在设计时考虑到了简单性、性能和可用性 。它可以在所有主要的桌面和移动平台上高效地工作,可以通过大量的插件进行扩展 , 拥有一个漂亮的、易于使用的、记录良好的 API,以及一个简单的、可读的源代码 。。
Leaflet 官网地址 https://leafletjs.com/
Leaflet 源码地址 [https://github.com/Leaflet/
Leaflet中加载CAD栅格瓦片在leaflet中加载CAD图,需要建立一个由cad建立的坐标系 。可以由L.CRS.Simple来进行扩展 , 设置好坐标系的范围、分辨率及转换参数即可 。

如何实现通过Leaflet加载dwg格式的CAD图

文章插图
// 地图服务对象,调用唯杰地图服务打开地图,获取地图的元数据let svc = new vjmap.Service(env.serviceUrl, env.accessToken)// 打开地图let mapId = "sys_zp";let res = await svc.openMap({mapid: mapId, // 地图IDmapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开style: vjmap.openMapDarkStyle() // div为深色背景颜色时,这里也传深色背景样式})if (res.error) {// 如果打开出错message.error(res.error)}// 获取地图范围let mapBounds = vjmap.GeoBounds.fromString(res.bounds);// 建立一个基于CAD图范围的坐标系let CadCRS = L.Class.extend({includes: L.CRS.Simple,initialize: function (bounds) {// 当前CAD图的范围this.bounds = bounds;// 投影this.projection = L.Projection.LonLat;// 计算分辨率let r = (256 / Math.abs(this.bounds.getEast() - this.bounds.getWest()));// 设置转换参数 一个仿射变换:一组系数a, b, c, d,用于将一个形式为(x, y)的点变换为 (ax + b, cy + d)并做相反的变换this.transformation = new L.Transformation(r, -r * this.bounds.getWest(),- r,r * this.bounds.getNorth());}});// leaflet中坐标是反的,如果要用L.latLng传入坐标的时候要传[y,x],如果要传[x,y],官网建议如下方案// https://leafletjs.com/examples/crs-simple/crs-simple.htmlL.XY = function(x, y) {if (L.Util.isArray(x)) {// When doing XY([x, y]);return L.latLng(x[1], x[0]);}return L.latLng(y, x);// When doing XY(x, y);};// 当前CAD地图范围let bounds = new L.LatLngBounds([L.XY(mapBounds.min.toArray()), L.XY(mapBounds.max.toArray())]);let center = mapBounds.center(); // 地图中心点// 创建leaflet的地图对象let map = L.map('map', {// 坐标系crs: new CadCRS(bounds),attributionControl: false}).setView(L.XY([center.x, center.y]), 2); // 设置初始中心点和缩放级别// 如果要用L.latLng设置的话,x,y应写反进行设置 。如// map.setView(L.latLng([center.y, center.x]), 2);// 增加一个栅格瓦片图层let layer = L.tileLayer(svc.rasterTileUrl(),// 唯杰地图服务提供的cad的栅格瓦片服务地址{bounds: bounds // 当前CAD地图范围}).addTo(map);// 把图层增加至地图中layer.addTo(map);Leaflet中选择高亮CAD实体选择高亮的实现思路为:响应地图的点击事件,通过当前位置去后台查询当前的实体的数据 。通过返回的geojson数据,在前端用leaflet的geoJSON进行绘制即可 。
如何实现通过Leaflet加载dwg格式的CAD图

文章插图
let highlightLayer; // 高亮图层const highlight_ent = async co => {if (highlightLayer) {highlightLayer.remove(); // 先删除之前的高亮图层highlightLayer = null;}let res = await svc.pointQueryFeature({x: co[0],y: co[1],zoom: map.getZoom(),fields: ""}, pt => {// 查询到的每个点进行坐标处理回调return mapPrj.fromMercator(pt);// 转成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({type: "Feature",properties: {objectid: ent.objectid + "_" + g,color: clr,alpha: ent.alpha / 255,lineWidth: 1,name: ent.name,isline: ent.isline,layerindex: ent.layerindex},geometry: ent.geom.geometries[g]})}// 选择提示let content = `feature: ${ent.objectid}; layer: ${cadLayers[ent.layerindex].name}; type: ${ent.name}`message.info({ content, key: "info", duration: 3});}}let data = https://www.huyubaike.com/biancheng/{type:"FeatureCollection",features: features}if (data.features.length > 0) {highlightLayer = L.geoJSON(data, {style: function (feature) {const highlightColor = svc.currentMapParam().darkMode ? "#57FFC9" : "#11F";return {color: highlightColor, fillColor: highlightColor}; // feature.properties.color}})highlightLayer.addTo(map);}}};

推荐阅读