QGIS基于规则的道路分级制图及Leaflet集成展示实例
目录
前言
一、QGIS分等级制图
1、道路等级标注
2、QGIS道路按规则标注
3、QGIS制图成果展示
二、QGIS路网导出及Leaflet集成
1、使用QGIS进行路网导出
2、Leaflet集成路网展示
3、WebGIS成果展示
三、总结
前言
在当今数字化时代,地理信息系统的应用日益广泛,而地图作为地理信息的重要可视化载体,其重要性不言而喻。道路作为城市和区域交通网络的核心组成部分,其可视化表达对于交通规划、城市管理和公众出行等众多领域都有着极为关键的作用。然而,面对复杂的道路数据,如何高效、准确且美观地进行分级制图,并将其以一种便捷、交互性强的方式呈现给用户,是地理信息工作者面临的重要挑战之一。
将 QGIS 制作的道路分级地图与 Leaflet 进行集成展示,不仅可以充分发挥 QGIS 在地图制作方面的专业优势,还能借助 Leaflet 的强大交互能力,使地图成果能够更广泛地应用于互联网环境。这种结合方式为地理信息的可视化展示提供了一种全新的思路和解决方案,具有广阔的应用前景。
本文将以 QGIS 基于规则的道路分级制图及 Leaflet 集成展示为例,详细阐述从数据准备、分级规则设置、地图符号化设计,到最终将地图成果通过 Leaflet 进行网络展示的全过程。通过这一实例,读者可以深入了解如何利用开源工具实现高效的地图制图与展示,掌握相关技术方法,为自己的地理信息项目提供参考和借鉴。在接下来的章节中,我们将逐步展开介绍,带领读者走进这一精彩的地图制作与展示之旅。
一、QGIS分等级制图
QGIS 是一款开源的地理信息系统软件,它凭借其强大的功能、灵活的定制能力和丰富的插件生态,已成为众多地理信息专业人士和爱好者的首选工具之一。QGIS 提供了强大的地图制图功能,能够对地理数据进行精细的符号化、标注和布局设计,尤其在基于规则的制图方面,能够根据数据的属性特征灵活设置分级规则,从而实现对复杂道路数据的清晰分级表达。
1、道路等级标注
道路分级制图的核心在于根据道路的功能、等级、流量等属性,将道路划分为不同的级别,并为每个级别设计合适的符号和样式。例如,高速公路通常采用较粗的线条和醒目的颜色,以突出其在交通网络中的重要地位;而小巷则可以用较细的线条表示,以体现其辅助性作用。通过合理的分级规则,可以使地图在不同比例尺下都能清晰地表达道路的层次关系,避免地图过于杂乱或信息缺失。在之前的系列博客中,我们曾详细的介绍了OSM路网数据中的不同等级类型的相关信息。如下图所示:
以上的道路分类是我们后期进行制图的基础。因为不同的道路等级其样式展示是不一样的,因此请大家完整的记录以上道路分级信息。
2、QGIS道路按规则标注
与之前的各种QGIS的制图方式不一样,在之前的制图方式中,我们使用较多的都是简单标注。分类标注也会使用到,但是不多。而按规则标注的方式在之前的工作过程中几乎就是没有进行任何讲解的,因此本文将重点围绕如何进行规则标注来阐述。在讲述规则标注时,需要大家对前面的道路等级分类有简单的了解,因为后续的道路分等级的规则标注就是在这个前提下进行的。这里以高速公路为例,加入我们要想在QGIS中实现按照高速公路这个规则进行地图标注。首先就需要先确定分类的规则,然后将设置不同的规则。
高速公路样式设置:
与之前的简单标注和分类标注不同,这里我们首先需要建立一些规则。比如按照前一节讲过的把高速公路、高速公路连接线、干道以及干道连接线作为一种规则,首先右键shp的属性,如下图:
然后使用鼠标在符号化类型中选择基于规则,然后点击新增打开如下的编辑页面:
在新打开的符号化页面中,选择符号过滤,同时点击后面的表达式字符串构造器,通过这个构造器来进行条件的设置,可以理解成类似于在数据库中的设置查询条件,这里的规则编辑其实就是where条件的设置,这里我们选择使用in查询子句。在高速公路及主干道的过滤条件中设置如下:
"fclass" in ('motorway','motorway_link','trunk','trunk_link')
输入完成后可以点击测试按钮,可以测试使用这条规则会返回的结果行数,如下图所示:
如上图中就表示使用如上的表达式,在矢量数据中可以筛选出4550个要素,也就是符合规则的数据条数。 除了需要设置不同的道路等级的数据规则之外,我们还需要设置道路的宽度等样式信息,也是在同一个界面中进行设置,在界面稍往下的位置中可以看到符号化的设置,比如我们可以点击“简单”线条,在QGIS中展示以下的样式操作界面:
这里的不同等级的道路可以根据实际的需要来进行设置,可以设置的属性包括形状、颜色、描边宽度、偏移量、描边样式、连接样式、端点样式等进行统一设置。这里以高速路为例,我们需要设置一个道路的颜色和宽度,选择颜色的下拉选项,在颜色设置的过程中我们可以有以下的操作设置方法,比如采用复制颜色(从别的地方进行复制)、选择颜色(支持从网页的其它地方或者其它颜色板进行设置),选择颜色(从自带的颜色面板中进行颜色选择),基本上着三种已经可以覆盖当前的一些场景。
大家可以参考互联网地图,如高德的设置方法来进行道路的样式的设置。设置好了颜色之后,下面我们来设置一下路宽,不同的道路,其路宽肯定是不一样的,比如高速公路通常来说会比较宽,而其它的内部道路,宽度就会根据实际的需要来制定了。这里我们采用像素值来设置宽度,如10px,
其它的属性可以根据需要来进行统一的设置, 设置好之后点击ok即可完成一类规则的设置,然后点击应用来看一下实际的效果:
由于篇幅有限,这里直接提供一些常见分类的道路的规则设置及分类属性,这里的道路分类规则是参考上一节的说明,而样式参考了部分的互联网道路样式设置。分享本示例中的其它道路分级展示样式:
序号 | 规则 | 条件 | 颜色 | 道路宽度 |
1 | 高速公路、国道 | "fclass" in ('motorway','motorway_link','trunk','trunk_link') | #fbc114 | 10px |
2 | 城市主干道 | "fclass" in ('primary','primary_link','secondary','secondary_link') | #f4e8b9 | 8px |
3 | 次干道 | "fclass" in ('tertiary' , 'tertiary_link','unclassified','residential') | #a9a9a9 | 6px |
4 | 城市乡村道路 | "fclass" in( 'track','track_grade1','track_grade3','track_grade5') | #ffffff | 4px |
5 | 内部道路 | "fclass" in ('bridleway','living_street','path','service') | #481bd0 | 2px |
6 | 行人步道、自行车道 | "fclass" in ('cycleway','footway','steps','pedestrian') | #3aca52 | 2px |
3、QGIS制图成果展示
在针对不同的道路等级进行设置之后,下面就结合前面的标注类型以及具体的样式设置之后,来看一下在QGIS中的道路绘制效果。
高速公路展示
城市主干道展示
次干道展示
内部道路展示
以上就是在QGIS中对不同的道路图层进行标绘后的结果展示,可以看到还是有了基本的效果。这里是使用QGIS中进行展示的。为了方便大家还原样式,这里也提供QGIS的SLD源码:
<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:se="http://www.opengis.net/se" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1.0"><NamedLayer><se:Name>长沙路网OSM2024</se:Name><UserStyle><se:Name>长沙路网OSM2024</se:Name><se:FeatureTypeStyle><se:Rule><se:Name>内部道路</se:Name><se:Description><se:Title>内部道路</se:Title></se:Description><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:Or><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>bridleway</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>living_street</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>path</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>service</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Or></ogc:Filter><se:LineSymbolizer><se:Stroke><se:SvgParameter name="stroke">#481bd0</se:SvgParameter><se:SvgParameter name="stroke-width">2</se:SvgParameter><se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter><se:SvgParameter name="stroke-linecap">square</se:SvgParameter></se:Stroke></se:LineSymbolizer></se:Rule><se:Rule><se:Name>行人步道、自行车道</se:Name><se:Description><se:Title>行人步道、自行车道</se:Title></se:Description><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:Or><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>cycleway</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>footway</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>steps</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>pedestrian</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Or></ogc:Filter><se:LineSymbolizer><se:Stroke><se:SvgParameter name="stroke">#3aca52</se:SvgParameter><se:SvgParameter name="stroke-width">2</se:SvgParameter><se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter><se:SvgParameter name="stroke-linecap">square</se:SvgParameter></se:Stroke></se:LineSymbolizer></se:Rule><se:Rule><se:Name>高速公路、国道</se:Name><se:Description><se:Title>高速公路、国道</se:Title></se:Description><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:Or><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>motorway</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>motorway_link</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>trunk</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>trunk_link</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Or></ogc:Filter><se:LineSymbolizer><se:Stroke><se:SvgParameter name="stroke">#fbc114</se:SvgParameter><se:SvgParameter name="stroke-width">10</se:SvgParameter><se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter><se:SvgParameter name="stroke-linecap">square</se:SvgParameter></se:Stroke></se:LineSymbolizer></se:Rule><se:Rule><se:Name>城市主干道</se:Name><se:Description><se:Title>城市主干道</se:Title></se:Description><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:Or><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>primary</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>primary_link</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>secondary</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>secondary_link</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Or></ogc:Filter><se:LineSymbolizer><se:Stroke><se:SvgParameter name="stroke">#f4e8b9</se:SvgParameter><se:SvgParameter name="stroke-width">8</se:SvgParameter><se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter><se:SvgParameter name="stroke-linecap">square</se:SvgParameter></se:Stroke></se:LineSymbolizer></se:Rule><se:Rule><se:Name>次干道</se:Name><se:Description><se:Title>次干道</se:Title></se:Description><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:Or><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>tertiary</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>tertiary_link</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>unclassified</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>residential</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Or></ogc:Filter><se:LineSymbolizer><se:Stroke><se:SvgParameter name="stroke">#a9a9a9</se:SvgParameter><se:SvgParameter name="stroke-width">6</se:SvgParameter><se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter><se:SvgParameter name="stroke-linecap">square</se:SvgParameter></se:Stroke></se:LineSymbolizer></se:Rule><se:Rule><se:Name>城市乡村道路</se:Name><se:Description><se:Title>城市乡村道路</se:Title></se:Description><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:Or><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>track</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>track_grade1</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>track_grade3</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>track_grade5</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Or></ogc:Filter><se:LineSymbolizer><se:Stroke><se:SvgParameter name="stroke">#ffffff</se:SvgParameter><se:SvgParameter name="stroke-width">4</se:SvgParameter><se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter><se:SvgParameter name="stroke-linecap">square</se:SvgParameter></se:Stroke></se:LineSymbolizer></se:Rule><se:Rule><se:Name>unknown</se:Name><se:Description><se:Title>unknown</se:Title></se:Description><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:PropertyIsEqualTo><ogc:PropertyName>fclass</ogc:PropertyName><ogc:Literal>unknown</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Filter><se:LineSymbolizer><se:Stroke><se:SvgParameter name="stroke">#d5d756</se:SvgParameter><se:SvgParameter name="stroke-width">1</se:SvgParameter><se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter><se:SvgParameter name="stroke-linecap">square</se:SvgParameter></se:Stroke></se:LineSymbolizer></se:Rule><se:Rule><se:Name></se:Name><!--Parser Error:
syntax error, unexpected ELSE - Expression was: ELSE--><se:LineSymbolizer><se:Stroke><se:SvgParameter name="stroke">#8599e9</se:SvgParameter><se:SvgParameter name="stroke-width">1</se:SvgParameter><se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter><se:SvgParameter name="stroke-linecap">square</se:SvgParameter></se:Stroke></se:LineSymbolizer></se:Rule><se:Rule><se:TextSymbolizer><se:Label><ogc:PropertyName>name</ogc:PropertyName></se:Label><se:Font><se:SvgParameter name="font-family">SimSun</se:SvgParameter><se:SvgParameter name="font-size">13</se:SvgParameter></se:Font><se:LabelPlacement><se:LinePlacement><se:GeneralizeLine>true</se:GeneralizeLine></se:LinePlacement></se:LabelPlacement><se:Fill><se:SvgParameter name="fill">#000000</se:SvgParameter></se:Fill></se:TextSymbolizer></se:Rule></se:FeatureTypeStyle></UserStyle></NamedLayer>
</StyledLayerDescriptor>
至此,基于QGIS实现道路的分等级制图功能及基于规则的标绘基本已实现。 为了实现能将地图进行共享,我们可以制作一个WebGIS应用,将QGIS的制图成果进行切片发布后就可以进行共享了,关键内容在下一节中进行详述。
二、QGIS路网导出及Leaflet集成
在完成道路分级制图后,如何将成果高效地展示给用户同样至关重要。传统的纸质地图或静态电子地图在展示动态数据和交互性方面存在局限性。而 Leaflet 作为一种轻量级的开源 JavaScript 地图库,能够轻松地将地理信息数据集成到网页中,实现地图的交互式展示。用户可以通过缩放、平移等操作查看地图的细节,还可以通过添加控件实现对图层的切换、查询等功能,极大地提升了用户体验。本节将详细介绍如何使用Qgis来进行路网的导出以及集成Leaflet组件。
1、使用QGIS进行路网导出
要想实现将地图进行切图,首先我们需要将地图切成瓦片的形式,然后再和Leaflet这样的前端组件进行深度结合来实现WebGIS的可视化。因此瓦片的生成是至关重要的一步,在QGIS中我们使用栅格工具中的生成XYZ图块,在QGIS中打开工具栏,
点击后出现以下界面,
在界面中我们设置相关的切图参数,如层级关系、DPI配置、以及切图的保存地址、这里分享我的本机设置参数:
参数设置好后,点击运行,qgis就会自动在后台进行切图,可以看到以下的输出信息:
QGIS版本:3.16.0-Hannover
QGIS代码版本:43b64b13f3
Qt版本:5.11.2
GDAL版本:3.1.4
GEOS版本:3.8.1-CAPI-1.13.3
PROJ版本:Rel. 6.3.2, May 1st, 2020
处理算法...
正在启动“生成 XYZ 图块(目录)”算法…
参数输入:
{ 'BACKGROUND_COLOR' : QColor(0, 0, 0, 0), 'DPI' : 96, 'EXTENT' : '111.893574191,114.208299888,27.860826328,28.664090613 [EPSG:4326]', 'METATILESIZE' : 4, 'OUTPUT_DIRECTORY' : 'D:\\shp2xyz\\csroad', 'OUTPUT_HTML' : 'D:/shp2xyz/csroad/index.html', 'QUALITY' : 75, 'TILE_FORMAT' : 0, 'TILE_HEIGHT' : 256, 'TILE_WIDTH' : 256, 'TMS_CONVENTION' : False, 'ZOOM_MAX' : 12, 'ZOOM_MIN' : 7 }Using 4 CPU Threads:
Generating tiles for zoom level: 7
Generating tiles for zoom level: 8
Generating tiles for zoom level: 9
Generating tiles for zoom level: 10
Generating tiles for zoom level: 11
Generating tiles for zoom level: 12
执行完成,花了28.46 秒
结果:
{'OUTPUT_DIRECTORY': 'D:\\shp2xyz\\csroad',
'OUTPUT_HTML': 'D:/shp2xyz/csroad/index.html'}载入结果图层
算法“生成 XYZ 图块(目录)”执行已完成
已生成该算法 HTML 格式输出结果。
请打开结果对话框进行检查。
下面来看一下实际的结果。
2、Leaflet集成路网展示
首先在我们设置的目标文件夹下,来看一下是否有瓦片生成,打开磁盘后发现:
在打开不同的层级目录,来看下是否有目标瓦片的生成,
可以看到瓦片已经成功生成,为了方便在Leaflet中进行瓦片展示,我们还生成了一个Leaflet集成的在线例子。代码如下:
<!DOCTYPE html>
<html>
<head><title>Leaflet Preview</title><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css"integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="crossorigin=""/><script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="crossorigin=""></script><style type="text/css">body {margin: 0;padding: 0;}html, body, #map{width: 100%;height: 100%;}</style>
</head>
<body><div id="map"></div><script>var map = L.map('map').setView([28.2624584705, 113.0509370395], 9.5);L.tileLayer('file:///D%3A/shp2xyz/csroad/{z}/{x}/{y}.png', {minZoom: 7,maxZoom: 12,tms: false,attribution: 'Generated by TilesXYZ'}).addTo(map);</script>
</body>
</html>
需要注意的是,这里采用的是file静态协议,如果大家希望将瓦片发布成动态的,可以将瓦片保存成动态的或者放到nginx等动态服务器中即可,为了节约内容,不再进行赘述。
3、WebGIS成果展示
下面来看一下实际的结果,使用浏览器直接打开磁盘中的index文件,可以直接进行数据浏览,效果如下图所示:
城市内部道路展示
其它的不同层级道路效果基本一致,因此在此不再进行赘述。
三、总结
以上就是本文的主要内容,本文将以 QGIS 基于规则的道路分级制图及 Leaflet 集成展示为例,详细阐述从数据准备、分级规则设置、地图符号化设计,到最终将地图成果通过 Leaflet 进行网络展示的全过程。通过这一实例,读者可以深入了解如何利用开源工具实现高效的地图制图与展示,掌握相关技术方法,为自己的地理信息项目提供参考和借鉴。博文详细的介绍如何在Qgis中如何对道路实现按等级制图,同时非常详细的介绍按规则进行标注的细节,最后通过如何将QGIS的制图效果如何在WebGIS上进行发布,并且使用Leafet来进行展示,让大家对QGIS的切片能力有了进一步的认识。行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。