基于Mapbox展示GDAL处理的3D行政区划展示实践

基于Mapbox展示GDAL处理的3D行政区划展示实践,第1张

目录

前言

一、Gdal数据处理

1、数据展示

2、Java数据转换

 二、Mapbox可视化

1、定义Mapbox地图

2、地图初始化

3、创建地图

三、界面优化

1、区域颜色设置

2、高度自适应和边界区分 

3、中文标注

总结


前言

        最近有遇到一个需求,用户想在地图上把行政区划数据做成那种3D凸出的效果,同时支持各个行政区划按照不同颜色进行展示,在行政区划上还能展示不同的标注,各个行政区的立体高度可以动态设置。刚开始收到这个需求的时候想用cesium来实现或者threejs来实现,要想实现3D的凸出特效,传统的Leaflet和OpenLayers似乎都有没有这种组件进行支持。各位朋友如果有相应的组件,欢迎留言指导指导。最后查找了一些Mapbox的资料,发现在Mapbox中有直接的样式配置就可以满足上述的需求实现。

        由于这里要展示3D行政数据,因此首先准备一份北京的行政区划实例。作为演示数据,这里并不保证数据的准确性。重点演示软件的功能。行政区划数据刚开始拿到的是Shp数据,为了在Mapbox中方便展示,可以将shp数据处理成矢量瓦片,这里为了演示方便,直接处理成geojson,关于geojson的基本知识,以后有时间可以进行深入讲解。

        本文首先讲解使用Java语言调用Gdal将shp数据转为geojson数据,然后使用Mapbox将处理好的Geojson行政区划数据进行3D展示,同时将不同行政区划进行动态颜色标绘,可以对行政区划的名称进行中文标注,最后动态设置不同行政区划的高度。如果您在项目中也有这种需求,可以参考本文进行开发。

一、Gdal数据处理

        由于默认的行政区划数据是采用Shp格式存储,为了在前端展示的方便,我们预先将shp数据转换成geojson。关于Gdal的相关知识,这里不赘述,在java开发语言中使用GDAL,在之前的博客中有进行详细的说明,各位朋友可以简单进行了解。使用Gdal进行处理,主要是方便进行服务调用,方便进行程序扩展。如果您实在不了解gdal,为了进行下一步,也可以采用诸如Qgis、Arcgis、SuperMap等这样的地图软件,直接将shp数据处理成geojson也是可以的。并不影响后面的效果展示。

1、数据展示

        这里采用的数据默认是shp格式,我们在qgis中查看其空间位置和属性信息。

基于Mapbox展示GDAL处理的3D行政区划展示实践,第2张

         上面本人已经默认进行中文标注以及颜色渲染,不过这是在qgis中进行标注实现的。下面来看一下数据的属性。

序号属性类型说明
1namestring行政区划名称

        在Qgis中,打开属性表可以看到以下的数据(ps:这里的数据不准确,仅供参考)。这里的数据比较老,与现行的行政区划是不一致的,同时北京市城区没有进行更详细的划分。

基于Mapbox展示GDAL处理的3D行政区划展示实践,第3张

2、Java数据转换

        数据格式转换从shp到geojson,这里采用Gdal组件作为转换插件。这里将转换程序的源码进行详细分析说明,让大家对转化过程有一个详细的了解。下面项目配置采用Maven进行编译,jdk使用1.8。首先来看一下Pom的定义。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.yelang</groupId> <artifactId>gdal_demo1</artifactId> <version>1.0.0</version> <name>gdal_demo1</name> <description>gdal试验</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.gdal</groupId> <artifactId>gdal</artifactId> <version>3.4.3</version> <scope>system</scope> <systemPath>${project.basedir}/lib/gdal.jar</systemPath> </dependency> <dependency> <groupId>net.sf.ucanaccess</groupId> <artifactId>ucanaccess</artifactId> <version>4.0.4</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> </project>

        为了演示方便,这里使用Junit的方式将处理过程以单元测试的构建方式给出,实际项目开发过程中,需要考虑更多的因素。详细的java转换代码如下:

@Test public void testShp2GeoJson() { // 注册所有的驱动 ogr.RegisterAll(); // 为了支持中文路径,请添加下面这句代码 gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","YES"); // 为了使属性表字段支持中文,请添加下面这句 gdal.SetConfigOption("SHAPE_ENCODING",""); //shp文件所在的位置 String strVectorFile = "E:/ruanzhu_4326_vector/2019/GS(2019)1822/beijing.shp"; //打开数据 DataSource ds = ogr.Open(strVectorFile,0); if (ds == null) { System.out.println("打开文件失败!" ); return; } System.out.println("打开文件成功!" ); Driver dv = ogr.GetDriverByName("GeoJSON"); if (dv == null) { System.out.println("打开驱动失败!" ); return; } System.out.println("打开驱动成功!" ); //输出geojson的位置及文件名 dv.CopyDataSource(ds, "E:/shp2geojson/beijing.geojson"); System.out.println("转换成功!" ); }

        上述的核心API就是使用geojson的驱动,实现将shp转换成geojson。上述代码运行完成后即可完成数据的转换。转换后的数据列表如下:

基于Mapbox展示GDAL处理的3D行政区划展示实践,第4张

        将beijing.json数据使用文本文件打开,可以看到以下结果,同时需要进行处理的还有行政区划的边界数据。

基于Mapbox展示GDAL处理的3D行政区划展示实践,第5张

 二、Mapbox可视化

        经过上述的数据处理步骤后,即可得到可以直接用于展示的原始数据,将数据进行静态化发布后,即可为前端提供数据源服务。下面将重点对采用Mapbox进行行政区划的3D展示进行详细说明。尤其是在Mapbox中如何进行高度控制,如何结合属性进行动态参数注入控制等 *** 作。要想实现这个需求,主要是需要使用fill-extrusion-xxx属性。通过这个属性来控制地图的可视化效果。

1、定义Mapbox地图

        首先新建Mapbox的html主体框架,关键代码如下所示:

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>基于Mapbox的3D行政区划立体展示</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link href="css/common.css" rel="stylesheet" /> <link href="lib/mapbox-gl.css" rel="stylesheet" /> <style> #map,body,html { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; font-size: 16px; } </style> </head> <body> <div id="map"></div> <script src="lib/mapbox-gl.js"></script> </body> </html>

2、地图初始化

        在定义了基本的网页结构后,我们使用javascript进行地图的初始化,首先来添加一个基础栅格影像底图,同时在资源引用列表中,将行政区划geojson和行政区划边界的geojson数据进行引入。关键代码如下:

var mapStyle = { "version": 8, "name": "Dark", "glyphs": "http://localhost:8086/2d/mapbox-gl-js-offline-example/font/{fontstack}/{range}.pbf", "sources": { "geojson": { type: 'geojson', data: './assets/beijing.geojson' }, "geojson-b": { type: 'geojson', data: './assets/beijing-b.geojson' }, "raster-tiles": { "type": "raster", "tiles": ['http://localhost:8086/data/xxgc/q0403/{z}/{x}/{y}.png'], "tileSize": 256, } }, "layers": [ { "id": "tdt-img-tiles", "type": "raster", "source": "raster-tiles", "minzoom": 0, "maxzoom": 8 } ] };

3、创建地图

map = new mapboxgl.Map({ container: 'map', maxZoom: 18, minZoom: 0, zoom: 7.6, center: [116.56330634582548, 40.20241714634946], pitch: 35, style: mapStyle, attributionControl: false });

        使用上述代码对地图进行初始化后,我们把数据添加到地图中进行展示。

map.on('load', () => { map.loadImage('./assets/ground.PNG', function(error, image) { if (error) throw error; map.addLayer({ id: 'geojson-fill', source: 'geojson', type: 'fill-extrusion', paint: { 'fill-extrusion-height': 15000, 'fill-extrusion-base': 0, 'fill-extrusion-opacity': 0.85, 'fill-extrusion-color': "#F84E2D" }, }) }); })

        到这里已经完成地图的基础展示,也实现了高度的自动配置。只不过每个行政区划的高度是一致的。实际效果如下:

基于Mapbox展示GDAL处理的3D行政区划展示实践,第6张

三、界面优化

        经过上面的可视化展示,基本已经实现了行政区划的3D立体展示。只是目前还存在一些明显的问题,比如行政区划边界不明显,各个行政区划无明显颜色区分,行政区划没有中文标注,各区域没有明显高度值差别。下面我们逐一来进行可视化调整优化。

1、区域颜色设置

        为了将各个行政区区分开来,我们采用不同的颜色进行标注。下面将fill-extrusio欧诺个n-color进行动态设置,根据属性列表中的name属性,不同的区域名称设置不同的颜色。下面的代表示,怀柔县采用#F84E2D展示,如果没有匹配的,最后一个是默认颜色#AAAAAA。关键设置如下:

fill-extrusion-color': [//根据数值中加载相对应颜色 'match', ['get', 'name'], '怀柔县', '#F84E2D', '密云县','#44DEA3', '平谷县','#ffd0a6', '延庆县','#FFC544', '顺义县','#ff704e', '大兴县','#6C44FF', '北京市', '#1372EC', '#AAAAAA' ]

        经过以上调整,来看具体的效果:

基于Mapbox展示GDAL处理的3D行政区划展示实践,第7张

2、高度自适应和边界区分 

        为了模拟各个行政区划的高度不一样,比如各区域的人口密度展示,我们会展示不同的高度,同时将行政区划的边界更加明显的展示出来。首先实现动态高度展示:

'fill-extrusion-height': [//根据数值中加载相对应颜色 'match', ['get', 'name'], '怀柔县', 15000, '密云县',17000, '延庆县',19000, '大兴县',21000, '北京市', 23000, 15000 ],

        然后添加行政区划边界信息图层,使区域信息更加明显。添加后再来看具体的效果。

map.addLayer({ id: 'geojson-fill-b', source: 'geojson-b', type: 'fill-extrusion', paint: { 'fill-extrusion-height': [//根据数值中加载相对应颜色 'match', ['get', 'name'], '怀柔县', 16100, '密云县',17100, '延庆县',19100, '大兴县',21100, '北京市', 23100, 16100 ], 'fill-extrusion-base': 14950, 'fill-extrusion-opacity': 1, 'fill-extrusion-color': '#fff' }, })

基于Mapbox展示GDAL处理的3D行政区划展示实践,第8张

3、中文标注

        行政区划标注是最简单的,再添加图层后,指定symbol类型进行展示即可。来看核心代码:

map.addLayer({ 'id': 'geojson-label', 'type': 'symbol', 'source': 'geojson', layout: { 'text-field': ['get', 'name'], 'text-size': 14, 'text-allow-overlap': true, 'text-justify': 'center' }, paint: { 'text-color': 'rgb(159, 96, 55)', 'text-halo-color': '#fff', 'text-halo-width': 1.8, }, });

        在地图上添加中文标注后,来看最后的实际效果。

基于Mapbox展示GDAL处理的3D行政区划展示实践,第9张

        到此即实现了在Mapbox中实现对行政区划的3D展示,同时实现动态标注,边界展示,动态高度设置等需求。 

总结

        以上就是本文的主要内容,本文首先讲解使用Java语言调用Gdal将shp数据转为geojson数据,然后使用Mapbox将处理好的Geojson行政区划数据进行3D展示,同时将不同行政区划进行动态颜色标绘,可以对行政区划的名称进行中文标注,最后动态设置不同行政区划的高度。如果您在项目中也有这种需求,可以参考本文进行开发。在使用Mapbox展示的时候,主要是采用fill-extrusion-xx关键字,同时在进行属性动态设置时的匹配规则的合理采用。本案例在实现时重点参考了以下博客,并优化了数据的展示和属性的配置。站在前人的肩膀上,可以看到更远的地方。在此感谢以下博文。

1、牛老师讲gis mapboxGL中3d行政区实现

2、mapboxgl绘制3D线教程

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/13518859.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024-03-05

发表评论

登录后才能评论

评论列表(0条)

保存