互动
最近评论
你好啊!我是
Leeon
最新评论
头像
111111
Administrator /
头像
11111
Administrator /
头像
11111
Administrator /
头像
11111
Administrator /
头像
11
Administrator /
最近发布
# Cesium与CAD图叠加显示 Cesium是一个非常优秀的三维地球GIS引擎, 开源且免费, 能够加载各种符合标准的地图图层,瓦片图、矢量图等都支持。在实际中经常会遇到需要将CAD的图纸叠加到cesium上面,与地表地形叠加显示查看。那如何实现在Cesium中实现与CAD的DWG图叠加显示分析呢? # 技术分析 业内一般的做法步骤为: ● (1) 在AutoCAD中把DWG图导出为DXF明码格式文件 ● (2) 利用第三方工具如GDAL,把dxf转为shp等GIS数据格式 ● (3) 利用开源的gis服务,如geoserver或mapserver把shp文件发布成gis服务 ● (4) 在cesium中加载gis服务的瓦片图层 上面的方案的优点很明显,基本上利用开源的方案能把流程跑通。但在实际项目中缺点也很明显,主要是在步骤 (1)(2), 因为dwg是私有格式,通过dwg转出成dxf再转化成shp文件时,会丢失图中的很多数据,CAD数据类型较为丰富,支持点、块符号、线、面、多段线、椭圆、块、文字等多种数据类型,而转换到GIS中,只转换为点、线、面、注记等类型,这使得CAD图形数据不能很好的满足GIS的要求,如:CAD中的Text数据类型,直接转换后只转换为GIS中的Point。通过这种转换去绘制,会导致和原始CAD图形绘制不太一样, 同时CAD里面有线型、字体也会导致绘制上的差异性。 唯杰地图vjmap完全兼容AutoCAD格式的DWG文件,无需通过转换可直接发布成gis的WMS格式,可有效解决上面问题。实现步骤为: ● (1) 上传DWG图形,利用唯杰地图发布为WMS图层 ● (2) 在cesium中加载wms瓦片图层 # 实现 先上效果图,(红色的线为cad图层)  # 具体步骤: ● 确定CAD图的坐标系 在打开的CAD图中,随便找了图中的一个点坐标,坐标为”614802.89177, 3257472.36997” 那怎么确定这个坐标是哪个坐标系呢? 如果已经知道坐标能不能倒推坐标系呢? 可以通过 通过CAD图中的坐标确定坐标系 这个工具。也可以用如下方法,这里我们只讨论高斯克吕格投影。 假设已经知道数据的投影是高斯克吕格,怎样判定是6°带还是3°带?怎样判定中央经线是多少呢? 如果坐标范围是6位,我们可以判定坐标系不带带号的。如果Y值范围在333000m~667000m,可能是3°分带法;如果Y值范围在166 000m~834000m,一定是6°分带法。如果取值范围重合的部分有可能3°分带法也可能在6°分带法。 如果坐标范围是8位,我们可以判定坐标系是以带号命名,并且根据带号可以知道是3°带还是6°带。我们国家的经度范围大致在73°33′E~105°05′E,所以如果是以带号命名,带号在13~23带之间的,说明是6°分带法;带号在25~45带之间的,说明是3°分带法。 在这个图中,坐标为”614802“为6位,大概率能确定为省去了带系的3°分带坐标。并且根据图中图框中坐标系写的为2000坐标系,同时地点为重庆附近。而重庆的经度差不多是以106开头。我们去epsg官网查询得知,该坐标系应该是"EPSG:4544".  ● 上传打开CAD图 在唯杰地图云端图纸管理平台(opens new window) 上传CAD图形。 ● 在cesium增加cad图层 let imageryProvider= new Cesium.WebMapTileServiceImageryProvider({ 			url: "http://t0.tianditu.gov.cn/img_w/wmts?tk=3346bb6ad29b5013c5952cf1117b80e9", 			layer: "img", 			style: "default", 			tileMatrixSetID: "w", 			format: "tiles", 			maximumLevel: 14, 		});  		let viewer = new Cesium.Viewer('cesiumContainer', { 			imageryProvider: imageryProvider, 			contextOptions: { 				webgl: { 					alpha: true 				} 			}, 			selectionIndicator: false, 			animation: false,  			baseLayerPicker: false,  			geocoder: false,  			timeline: false,  			sceneModePicker: false,  			navigationHelpButton: false,  			infoBox: false,  			fullscreenButton: false, 			shouldAnimate: true  		});  		var layers = viewer.scene.imageryLayers;  		layers.addImageryProvider( 			new Cesium.WebMapServiceImageryProvider({ 			     				url: `https://vjmap.com/server/api/v1/map/cmd/wms/ sys_cadcesium/v1?mapbounds=&format=image/png&service=WMS&version=1.1.1&request=GetMap&srs=EPSG:4326&transparent=true&width=256&height=256&layers=se92105f73&crs=EPSG:4544&fourParameter=&token=your token`, 			}) 		); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37   上面的代码好像简单明了,可实际中发现,在cesium中,cad可以和天地图影像叠加。但在放大的过程中,发现wms生成的瓦片有错开的问题。如下图所示:  # 问题分析 在cesium中,是WGS84坐标系,而CAD图是4544坐标系。两个不同的椭球体之间转换,在WMS中瓦片生成是根据坐标转换生成的瓦片数据,而由于坐标转换是非线性的,导致生成的图片内容不能完全对上。所以有错开的问题。 那怎么解决呢? 最终的方案是: ● 先通过四参数,把CAD与墨卡托3857的转换参数求出来 ● 再墨卡托3857转wgs4326 通过这样的转换,数据转换是线性转换了,就不会有错开的问题了。 具体代码如下: let svc = new vjmap.Service(env.serviceUrl, env.accessToken)  let mapId = "sys_cadcesium"; let res = await svc.openMap({     mapid: mapId,      mapopenway: vjmap.MapOpenWay.GeomRender,      style: vjmap.openMapDarkStyle()  }) if (res.error) {          message.error(res.error) } let layer = res.layer;  let mapBounds = vjmap.GeoBounds.fromString(res.bounds); let boundsArray = mapBounds.toPointArray();   let mktPoints = await svc.cmdTransform("EPSG:4544", "EPSG:3857", boundsArray.map(a => vjmap.geoPoint(a)));  let cadPoints = [...boundsArray];  let fourparam = vjmap.coordTransfromGetFourParamter(     mktPoints.map(a => vjmap.geoPoint(a)),     cadPoints.map(a => vjmap.geoPoint(a)),     true );  if (typeof Cesium !== "object") {          await vjmap.addScript([{         src: "js/Cesium/Cesium.js"     }, {         src: "js/Cesium/Widgets/widgets.css"     }]) }  let imageryProvider= new Cesium.WebMapTileServiceImageryProvider({     url: "https://t0.tianditu.gov.cn/img_w/wmts?tk=3346bb6ad29b5013c5952cf1117b80e9",     layer: "img",     style: "default",     tileMatrixSetID: "w",     format: "tiles",     maximumLevel: 14, });  let viewer = new Cesium.Viewer('map', {     imageryProvider: imageryProvider,     contextOptions: {         webgl: {             alpha: true         }     },     selectionIndicator: false,     animation: false,      baseLayerPicker: false,      geocoder: false,      timeline: false,      sceneModePicker: false,      navigationHelpButton: false,      infoBox: false,      fullscreenButton: false,     shouldAnimate: true  });   var layers = viewer.scene.imageryLayers;   layers.addImageryProvider(     new Cesium.UrlTemplateImageryProvider({         url: "https://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",     }) );    let wmsUrl = svc.wmsTileUrl({     mapid: mapId,      layers: layer,      bbox: '',      srs: "EPSG:4326",      crs: "EPSG:3857",      fourParameter: [fourparam.dx,fourparam.dy,fourparam.scale,fourparam.rotate]  }) layers.addImageryProvider(     new Cesium.WebMapServiceImageryProvider({         url: wmsUrl,     }) );    const cadToWebCoordinate = point => {               let ptMkt = vjmap.coordTransfromByInvFourParamter(vjmap.geoPoint(point), fourparam);     return vjmap.Projection.mercator2LngLat(ptMkt); }  const webTocadCoordinate = point => {          let ptMkt = vjmap.Projection.lngLat2Mercator(vjmap.geoPoint(point));     return vjmap.coordTransfromByFourParamter(ptMkt, fourparam); }  let cadCenter = mapBounds.center(); let webCenter = cadToWebCoordinate(cadCenter);  viewer.camera.flyTo({     destination: Cesium.Cartesian3.fromDegrees(webCenter[0], webCenter[1], 30000) }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118   出于对数据保密的需要,我们对CAD图进行了脱敏处理,叠加的效果如下  访问 https://vjmap.com/demo/#/demo/map/web/07cesiumCadWmsLayer(opens new window) ,查看效果和代码   来自: 唯杰地图-VJMAP-为CAD图WebGIS可视化显示开发提供的一站式解决方案
# Cesium与CAD图叠加显示 Cesium是一个非常优秀的三维地球GIS引擎, 开源且免费, 能够加载各种符合标准的地图图层,瓦片图、矢量图等都支持。在实际中经常会遇到需要将CAD的图纸叠加到cesium上面,与地表地形叠加显示查看。那如何实现在Cesium中实现与CAD的DWG图叠加显示分析呢? # 技术分析 业内一般的做法步骤为: ● (1) 在AutoCAD中把DWG图导出为DXF明码格式文件 ● (2) 利用第三方工具如GDAL,把dxf转为shp等GIS数据格式 ● (3) 利用开源的gis服务,如geoserver或mapserver把shp文件发布成gis服务 ● (4) 在cesium中加载gis服务的瓦片图层 上面的方案的优点很明显,基本上利用开源的方案能把流程跑通。但在实际项目中缺点也很明显,主要是在步骤 (1)(2), 因为dwg是私有格式,通过dwg转出成dxf再转化成shp文件时,会丢失图中的很多数据,CAD数据类型较为丰富,支持点、块符号、线、面、多段线、椭圆、块、文字等多种数据类型,而转换到GIS中,只转换为点、线、面、注记等类型,这使得CAD图形数据不能很好的满足GIS的要求,如:CAD中的Text数据类型,直接转换后只转换为GIS中的Point。通过这种转换去绘制,会导致和原始CAD图形绘制不太一样, 同时CAD里面有线型、字体也会导致绘制上的差异性。 唯杰地图vjmap完全兼容AutoCAD格式的DWG文件,无需通过转换可直接发布成gis的WMS格式,可有效解决上面问题。实现步骤为: ● (1) 上传DWG图形,利用唯杰地图发布为WMS图层 ● (2) 在cesium中加载wms瓦片图层 # 实现 先上效果图,(红色的线为cad图层) # 具体步骤: ● 确定CAD图的坐标系 在打开的CAD图中,随便找了图中的一个点坐标,坐标为”614802.89177, 3257472.36997” 那怎么确定这个坐标是哪个坐标系呢? 如果已经知道坐标能不能倒推坐标系呢? 可以通过 通过CAD图中的坐标确定坐标系 这个工具。也可以用如下方法,这里我们只讨论高斯克吕格投影。 假设已经知道数据的投影是高斯克吕格,怎样判定是6°带还是3°带?怎样判定中央经线是多少呢? 如果坐标范围是6位,我们可以判定坐标系不带带号的。如果Y值范围在333000m~667000m,可能是3°分带法;如果Y值范围在166 000m~834000m,一定是6°分带法。如果取值范围重合的部分有可能3°分带法也可能在6°分带法。 如果坐标范围是8位,我们可以判定坐标系是以带号命名,并且根据带号可以知道是3°带还是6°带。我们国家的经度范围大致在73°33′E~105°05′E,所以如果是以带号命名,带号在13~23带之间的,说明是6°分带法;带号在25~45带之间的,说明是3°分带法。 在这个图中,坐标为”614802“为6位,大概率能确定为省去了带系的3°分带坐标。并且根据图中图框中坐标系写的为2000坐标系,同时地点为重庆附近。而重庆的经度差不多是以106开头。我们去epsg官网查询得知,该坐标系应该是"EPSG:4544". ● 上传打开CAD图 在唯杰地图云端图纸管理平台(opens new window) 上传CAD图形。 ● 在cesium增加cad图层 let imageryProvider= new Cesium.WebMapTileServiceImageryProvider({ url: "http://t0.tianditu.gov.cn/img_w/wmts?tk=3346bb6ad29b5013c5952cf1117b80e9", layer: "img", style: "default", tileMatrixSetID: "w", format: "tiles", maximumLevel: 14, }); let viewer = new Cesium.Viewer('cesiumContainer', { imageryProvider: imageryProvider, contextOptions: { webgl: { alpha: true } }, selectionIndicator: false, animation: false, baseLayerPicker: false, geocoder: false, timeline: false, sceneModePicker: false, navigationHelpButton: false, infoBox: false, fullscreenButton: false, shouldAnimate: true }); var layers = viewer.scene.imageryLayers; layers.addImageryProvider( new Cesium.WebMapServiceImageryProvider({ url: `https://vjmap.com/server/api/v1/map/cmd/wms/ sys_cadcesium/v1?mapbounds=&format=image/png&service=WMS&version=1.1.1&request=GetMap&srs=EPSG:4326&transparent=true&width=256&height=256&layers=se92105f73&crs=EPSG:4544&fourParameter=&token=your token`, }) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 上面的代码好像简单明了,可实际中发现,在cesium中,cad可以和天地图影像叠加。但在放大的过程中,发现wms生成的瓦片有错开的问题。如下图所示: # 问题分析 在cesium中,是WGS84坐标系,而CAD图是4544坐标系。两个不同的椭球体之间转换,在WMS中瓦片生成是根据坐标转换生成的瓦片数据,而由于坐标转换是非线性的,导致生成的图片内容不能完全对上。所以有错开的问题。 那怎么解决呢? 最终的方案是: ● 先通过四参数,把CAD与墨卡托3857的转换参数求出来 ● 再墨卡托3857转wgs4326 通过这样的转换,数据转换是线性转换了,就不会有错开的问题了。 具体代码如下: let svc = new vjmap.Service(env.serviceUrl, env.accessToken) let mapId = "sys_cadcesium"; let res = await svc.openMap({ mapid: mapId, mapopenway: vjmap.MapOpenWay.GeomRender, style: vjmap.openMapDarkStyle() }) if (res.error) { message.error(res.error) } let layer = res.layer; let mapBounds = vjmap.GeoBounds.fromString(res.bounds); let boundsArray = mapBounds.toPointArray(); let mktPoints = await svc.cmdTransform("EPSG:4544", "EPSG:3857", boundsArray.map(a => vjmap.geoPoint(a))); let cadPoints = [...boundsArray]; let fourparam = vjmap.coordTransfromGetFourParamter( mktPoints.map(a => vjmap.geoPoint(a)), cadPoints.map(a => vjmap.geoPoint(a)), true ); if (typeof Cesium !== "object") { await vjmap.addScript([{ src: "js/Cesium/Cesium.js" }, { src: "js/Cesium/Widgets/widgets.css" }]) } let imageryProvider= new Cesium.WebMapTileServiceImageryProvider({ url: "https://t0.tianditu.gov.cn/img_w/wmts?tk=3346bb6ad29b5013c5952cf1117b80e9", layer: "img", style: "default", tileMatrixSetID: "w", format: "tiles", maximumLevel: 14, }); let viewer = new Cesium.Viewer('map', { imageryProvider: imageryProvider, contextOptions: { webgl: { alpha: true } }, selectionIndicator: false, animation: false, baseLayerPicker: false, geocoder: false, timeline: false, sceneModePicker: false, navigationHelpButton: false, infoBox: false, fullscreenButton: false, shouldAnimate: true }); var layers = viewer.scene.imageryLayers; layers.addImageryProvider( new Cesium.UrlTemplateImageryProvider({ url: "https://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8", }) ); let wmsUrl = svc.wmsTileUrl({ mapid: mapId, layers: layer, bbox: '', srs: "EPSG:4326", crs: "EPSG:3857", fourParameter: [fourparam.dx,fourparam.dy,fourparam.scale,fourparam.rotate] }) layers.addImageryProvider( new Cesium.WebMapServiceImageryProvider({ url: wmsUrl, }) ); const cadToWebCoordinate = point => { let ptMkt = vjmap.coordTransfromByInvFourParamter(vjmap.geoPoint(point), fourparam); return vjmap.Projection.mercator2LngLat(ptMkt); } const webTocadCoordinate = point => { let ptMkt = vjmap.Projection.lngLat2Mercator(vjmap.geoPoint(point)); return vjmap.coordTransfromByFourParamter(ptMkt, fourparam); } let cadCenter = mapBounds.center(); let webCenter = cadToWebCoordinate(cadCenter); viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(webCenter[0], webCenter[1], 30000) }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 出于对数据保密的需要,我们对CAD图进行了脱敏处理,叠加的效果如下 访问 https://vjmap.com/demo/#/demo/map/web/07cesiumCadWmsLayer(opens new window) ,查看效果和代码 来自: 唯杰地图-VJMAP-为CAD图WebGIS可视化显示开发提供的一站式解决方案
1
1
1
1
1
1
1
1
引用到评论