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

目录

前言

一、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中查看其空间位置和属性信息。

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

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

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

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。上述代码运行完成后即可完成数据的转换。转换后的数据列表如下:

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

 二、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"
          },
        })
      });
    })

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

三、界面优化

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

1、区域颜色设置

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

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

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

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'
          },
        })

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中实现对行政区划的3D展示,同时实现动态标注,边界展示,动态高度设置等需求。 

总结

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

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

2、mapboxgl绘制3D线教程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/399357.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IP地理位置查询定位:技术原理与实际应用

在互联网时代&#xff0c;IP地址是连接世界的桥梁&#xff0c;而了解IP地址的地理位置对于网络管理、个性化服务以及安全监控都至关重要。IP数据云将深入探讨IP地理位置查询定位的技术原理、实际应用场景以及相关的隐私保护问题&#xff0c;旨在为读者提供全面了解和应用该技术…

海外媒体发稿:提高用户留存率的7个链游媒体宣发推广策略-华媒舍

在当今数字化时代&#xff0c;移动链游已经成为人们生活中不可或缺的一部分。随着链游市场日益竞争激烈&#xff0c;如何提高用户留存率成为了游戏开发者和媒体宣发人员需要面对的重要问题。本文将为您介绍7个有效的链游媒体宣发推广策略&#xff0c;帮助您提高用户留存率。 1.…

Unity编辑器扩展之Text组件中字体替换工具

想要批量化替换项目预制体资源中Text组件引用的Font字体文件&#xff0c;可以采用以下步骤。 1、在项目的Editor文件中&#xff0c;新建一个名为FontToolEditor的C#脚本文件&#xff0c;然后把以下代码复制粘贴到新建的FontToolEditor的C#脚本文件中。 using System.Collect…

哪款护眼台灯适合孩子用?五大爆款选购指南分享

护眼台灯凭借各种好处让很多家长都为孩子选择。但是许多想要选择护眼台灯的家长们&#xff0c;各种台灯不能盲目入手&#xff0c;因为市面上存在各种生产实力不足&#xff0c;做工差&#xff0c;以及选材廉价等问题的劣质产品。那么护眼台灯要怎么选&#xff1f;关于这个问题&a…

2024牛客寒假算法基础集训营4(视频讲解题目)

2024牛客寒假算法基础集训营4&#xff08;视频讲解题目&#xff09; 视频链接ABCDEFG、H&#xff08;下面是hard版本的代码两个都可以过&#xff09; 视频链接 2024牛客寒假算法基础集训营4&#xff08;视频讲解题目&#xff09; A #include<bits/stdc.h> #define en…

在Win系统部署WampServer并实现公网访问本地服务【内网穿透】

目录 推荐 前言 1.WampServer下载安装 2.WampServer启动 3.安装cpolar内网穿透 3.1 注册账号 3.2 下载cpolar客户端 3.3 登录cpolar web ui管理界面 3.4 创建公网地址 4.固定公网地址访问 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0…

Windows系统安全策略设置之本地NTLM重放提权

经安全部门研究分析&#xff0c;近期利用NTLM重放机制入侵Windows 系统事件增多&#xff0c;入侵者主要通过Potato程序攻击拥有SYSTEM权限的端口伪造网络身份认证过程&#xff0c;利用NTLM重放机制骗取SYSTEM身份令牌&#xff0c;最终取得系统权限&#xff0c;该安全风险微软并…

vue3 用xlsx 解决 excel 低版本office无法打开问题

需求背景解决思路解决效果将json导出为excel将table导为excel导出样式 需求背景 原使用 vue3-json-excel &#xff0c;导致在笔记本office环境下&#xff0c;出现兼容性问题 <vue3-json-excel class"export-btn" :fetch"excelGetList" :fields"js…

国际贸易报关需要向海关提交哪些资料 | 全球数字贸易发展联盟 | 箱讯科技

1、进出口货物报关单。一般进口货物应填写一式二份;需要由海关核销的货物&#xff0c;如加工贸易货物和保税货物等&#xff0c;应填写专用报关单一式三份;货物出口后需国内退税的&#xff0c;应另填一份退税专用报关单。 2、货物发票。要求份数比报关单少一份&#xff0c;对货…

OpenProject 安装迁移

文章目录 1、概要2、备份3、新服务器安装OpenProject4、新服务器安装Postgresql5、旧服务器数据转移到新服务器5.1、转移attachments附件5.2、转移conf配置文件5.3、转移存储库5.4、导入Postgres数据库 6、openproject配置 1、概要 注意&#xff1a;本文仅适用于 DEB/RPM 包安…

高品质定制线缆厂家推荐:精工电联-打造智能智造的线缆解决方案(线缆定制流程)

高品质定制线缆厂家&#xff1a;精工电联-打造智能智造的线缆解决方案&#xff08;定制线缆定制流程&#xff09; 精工电联 在百年未有之大变局的当下&#xff0c;科技发展日新月异的今天&#xff0c;智能制造正在改变着各行各业的生产及人们的生活方式。作为线缆制造领域的领先…

0220作业

C语言实现LED1闪烁 led.h #ifndef __LED_H__ #define __LED_H__//RCC寄存器封装 #define RCC_MP_AHB4_ENSETR (*(volatile unsigned int*)0x50000A28) //寄存器封装//GPIO寄存器封装 typedef struct{volatile unsigned int MODER; //00volatile unsigned int OTYPER; //04vol…

c++:蓝桥杯中的基础算法1(枚举,双指针)

枚举 基础概念&#xff1a; 枚举&#xff08;Enum&#xff09;是一种用户定义的数据类型&#xff0c;用于定义一个有限集合的命名常量。在C中&#xff0c;枚举类型可以通过关键字enum来定义。 下面是一个简单的枚举类型的定义示例&#xff1a; #include <iostream>enum…

Spring Bean 的生命周期了解么?

Spring Bean 的生命周期基本流程 一个Spring的Bean从出生到销毁的全过程就是他的整个生命周期, 整个生命周期可以大致分为3个大的阶段 : 创建 使用 销毁 还可以分为5个小步骤 : 实例化(Bean的创建) , 初始化赋值, 注册Destruction回调 , Bean的正常使用 以及 Bean的销毁 …

leetcode 105. 从前序与中序遍历序列构造二叉树【构造二叉树】

原题链接&#xff1a;105. 从前序与中序遍历序列构造二叉树 题目描述&#xff1a; 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 输入输出描述&…

ETL快速拉取物流信息

我国作为世界第一的物流大国&#xff0c;但是在目前的物流信息系统还存在着几大的痛点。主要包括以下几个方面&#xff1a; 数据孤岛&#xff1a;有些物流企业各个部门之间的数据标准不一致&#xff0c;难以实现数据共享和协同&#xff0c;容易导致信息孤岛。 操作繁琐&#x…

小程序--loading和toast

一、loading wx.showLoading({})显示loading提示框。wx.hideLoading({})隐藏loading提示框。 title&#xff1a;文字提示内容 mask&#xff1a;是否显示透明蒙层&#xff0c;防止触摸穿透。 更多属性参考showLoading官方文档。 wx.showLoading({title: 加载中...,mask: true }…

HTML学习笔记——08:表单<form>

HTML <form> 元素表示文档中的一个区域&#xff0c;此区域包含交互控件&#xff0c;用于向 Web 服务器提交信息。 例如&#xff1a;登录页面。 作用&#xff1a;搜集不同类型的用户输入&#xff0c;并向服务器传送数据。 注意&#xff1a;表单本身并不可见&#xff01;…

Git基本操作(2)

Git基本操作&#xff08;2&#xff09; 上交文件之后&#xff0c;git文件的变化git cat-file HEAD指针里面有啥文件被修改git statusgit diff 文件名 版本回退&#xff08;git reset&#xff09;撤销回退git reflog 撤销的三种情况还没有addgit checkout -- [file] 已经add还没…

全志 T527 适配 I2S

一、背景概念 在 T5 系列芯片中&#xff0c;内置了一个 AudioHub 模块&#xff0c;使用的 是I2S 接口&#xff0c;都跟 AudioHub 关联在一起&#xff0c;此时外挂的声卡若想正常工作&#xff0c;还需要配置 AudioHub 的路由信息。&#xff08;AudioHub 是全志 T527 特有的模块&…