news 2026/11/6 12:33:26

台湾道路矢量数据分级处理:QGIS拆分shp并导出WKT全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
台湾道路矢量数据分级处理:QGIS拆分shp并导出WKT全攻略

简介:台湾省道路数据最新分级精确到乡道矢量数据包,面向地理信息系统开发、交通规划与地图制图等专业人员,适合需要道路路网底图进行空间分析、可视化或研究台湾地区道路分级体系的场景。数据分为三个维度:城市一级至四级道路线要素,覆盖城区内部不同等级路网;高速、国道、省道、县道、乡道等行政等级道路,体现区域骨架与连接关系;另有来源于OpenStreetMap的铁路与道路图层,包含轻轨、窄轨、地铁、有轨电车及主干道、次干道、支道、人行道、住宅街道、自行车道等多种类型。16种道路数据既有重复也有互补,可相互校验与修正,便于按不同精度与用途选用,也可用于不同来源路网对比和台湾地区道路现状研究。压缩包整体约43.63MB,已被463人浏览学习,适合作为GIS底图、制图输出与路网分析的补充资料。

1. 用之前先看懂分级:从高速到乡道的道路矢量能做什么

做 GIS 的人都知道,一份「分级精确到乡道」的道路矢量数据有多难得。日常接触的免费路网要么只有主干道,要么是某个平台导出的切片,想按国道、省道、县道、乡道分级出图,要么靠人工描,要么靠关系找测绘院的朋友。这份压缩包解压之后就是一套完整的台湾地区道路 shp 数据,从高速公路一路分到乡道,导入 QGIS 或 ArcGIS 就能直接筛、直接切、直接出图,不依赖在线服务,离线环境里也能跑。对搞规划、做制图、写 WebGIS 地图服务的人,以及需要把本地路网接进自己系统的开发者,这份数据都能省掉一大半预处理时间。

这套数据真正值钱的地方是「分级」两个字。很多公开路网数据只有几何,没有道路等级字段,你想把高速和乡道分开渲染都做不到。这里的 shp 属性表里带着等级标识,按字段筛一下,就能把不同层级的路拆到独立图层。第 2 章先把 shp 的内部结构和投影坐标系讲清楚,因为后面所有筛选、导出、验证的坑,几乎都出在坐标系和编码上。

2. 数据组织与坐标系:打开 shp 前先搞清三件事

拿到 rar 压缩包,先别急着拖进 GIS 软件。shp 不是单文件,它是一组同名文件的集合,缺了任何一个都可能出问题。这一步花五分钟检查清楚,后面能省两小时排错。

2.1 shp 文件族:.shp、.dbf、.prj 各管什么

一个完整的 shapefile 至少要有 .shp(几何)、.shx(索引)、.dbf(属性)三个文件,带投影信息的还会有 .prj,带编码说明的经常有 .cpg。解压后我先按文件后缀过一遍,下面这张表是判断依据。

后缀作用缺失后果
.shp存储点线面几何坐标无法显示图形
.shx几何位置索引部分软件打不开
.dbf属性数据,道路分级字段就在这里只有图形没有属性
.prj坐标系与投影定义软件按默认坐标系猜测,容易套错
.cpg属性编码声明中文属性乱码

我一般习惯先把这些文件复制到一个纯英文路径的目录里,比如D:\gis\tw_road\,顺手把 dbf 用文本编辑器打开看一眼开头几行。要是 dbf 里出现「鍦嬮亾」这种乱码,说明编码没识别对,别急着改,后面第 5 章有具体解法。这里要说的重点是:字段里通常有一个列叫ROAD_CLASS、Class或RANK,存的就是高速、省道、县道、乡道这类分级代码,数字还是拼音缩写,每套数据不一样,先看字典再动手。

2.2 坐标系判断:WGS84 和 TWD97 的区别决定了你叠不叠得准

台湾地区的道路数据,常见坐标系有两种。第一种是 WGS84,经纬度坐标,单位和全球 GPS 一致,QGIS 里默认就是它,打开直接能叠在线底图上。第二种是 TWD97,这是台湾本地的地心坐标基准,常配合 TM 二度分带投影,坐标单位是米,数值看起来是几十万到三十万左右的样子。还有更老的 TWD67,和 TWD97 之间差几百米,叠图时一眼就能看出来偏了。

判断方法是打开 .prj 文件看文字描述:带GCS_WGS_1984的是经纬度,带TWD_1997_TM_2_NGA_121或类似字样的就是投影坐标。如果连 .prj 都没有,打开图层后看坐标范围——经度在 120 左右、纬度在 22 到 25 之间的,是 WGS84 没跑了;数值落在十几万到三十几万、最大不超过五十万的,是按米计的投影坐标。

QGIS 里右键图层选「图层属性 → 源」,下面有个「强制图层 CRS」按钮,可以手动指定坐标系,不用重新投影文件。注意:用「强制」只是把错的标注改掉,不改几何;真要换坐标系,得用工具箱里的「重投影图层」。这一步是后期导出 WKT 时最容易翻车的地方,第 4 章会专门讲。

3. 在 QGIS 里按分级拆层:筛选、分离和出底图

数据能正常显示了,下一步就是把不同等级的路拆出来。拆层的目的不只是好看,更是给后续每条路单独做样式、做分析打基础。你可以用「按属性选择」临时看效果,也可以用「按表达式提取要素」,一劳永逸拆出独立图层。

3.1 先用表达式摸清字段内容

打开属性表,点左上角「选择使用表达式」,先跑一句看看分级字段里到底存了什么值。假设分级字段叫Class,先统计一下有哪些取值:

-- 统计 Class 字段的去重值,确认道路分级代码 "Class" IS NOT NULL

这一步在「按属性选择」里执行,选中后看底部状态栏的选中数量,再配合字段筛选逐个查看。用 QGIS 的「按字段值分组统计」更方便:菜单「处理 → 工具箱」搜「统计」,选Class作为分组字段,直接出汇总表。

实际数据里Class可能是数字(1 代表高速、2 代表省道),也可能是拼音(G、S、X、Y,分别对应国道、省道、县道、乡道),还可能直接是中文。先跑出这一张去重表,后面所有提取表达式都以它为准,这是最稳的做法。

3.2 用提取表达式拆出乡道图层

摸清取值后,用「按表达式提取要素」拆层,输出 shp 到本地目录。假设验证下来Class字段里Y代表乡道,提取表达式如下:

"Class" = 'Y'

参数说明:这是精确匹配。如果字段是数字类型就别加引号,写成"Class" = 4。如果发现同一个等级在数据里有两种写法,比如Y和Y1同时存在,用 LIKE 匹配更保险:

"Class" LIKE 'Y%'

逻辑说明:LIKE是按前缀模糊匹配,这样Y1、Y2都会被抓出来,适合分道编号和等级混在一个字段里的情况。提取工具会生成一个新的矢量图层,右键导出就能存成独立 shp。拆层时顺手做三件事:给每个等级分别存一个文件、文件命名带等级名、全部放在同一坐标系目录里,不然第 4 章会自食其果。

3.3 分级配色的出图小技巧

拆完层,出图就很轻松了。我一般用「图层样式 → 分类」按字段自动配五档:高速用红色宽线、国道用橙色、省道用黄色、县道用浅蓝、乡道用灰色细线。乡道数量大,显示级别调到最小,避免盖住高层级。出图前确认一下项目的 CRS 是 WGS84(EPSG:4326),因为后续如果接在线底图,CRS 不一致,图面直接错位。

4. shp 导出 WKT:把矢量数据喂给离线地图和 WebGIS

很多做前端地图和离线瓦片的人会卡在这一步:手里有 shp,但项目要的是 WKT 或 GeoJSON,没法直接读 shp。WKT 是文本格式的几何描述,PostGIS、OpenLayers、Leaflet 里都能直接吃,导出后相当于把数据做了一次格式解耦,不再依赖 GIS 软件。

4.1 先用 ogr2ogr 做批量转换

GDAL 里的ogr2ogr是最快的转换工具,一条命令就能把整个 shp 转成 WKT 文本:

ogr2ogr -f "CSV" tw_road_wkt.csv tw_road.shp -lco GEOMETRY=AS_WKT

参数说明:-f "CSV"指定输出格式为 CSV,-lco GEOMETRY=AS_WKT是让几何列以 WKT 形式写入。生成的文件里每个要素一行,WKT列里就是LINESTRING (… )或MULTILINESTRING (…)这样的文本。

注意一点:CSV 输出默认不保留 CRS 信息,所以转之前要在 QGIS 里先把图层重投影到 WGS84。命令改成:

ogr2ogr -f "CSV" tw_road_wkt.csv tw_road.shp -lco GEOMETRY=AS_WKT -t_srs EPSG:4326

-t_srs EPSG:4326是目标坐标系参数,加了它,转换过程会自动把 TWD97 米制坐标转成经纬度,坐标准确性由这一步保证。转完用文本编辑器打开看一眼,确认LINESTRING里的坐标是 120.x、24.x 这种格式,说明坐标系对了。

4.2 用 Python ogr 跑字段级导出

如果只想导出某个等级,或者想把道路等级一起写进 WKT,ogr2ogr 不够灵活。我一般直接用 Python 的osgeo.ogr,把 WKT 和属性一起落表:

from osgeo import ogr # 打开 shp,第二个参数 0 表示只读 ds = ogr.Open(r"D:\gis\tw_road\tw_road.shp", 0) layer = ds.GetLayer() with open(r"D:\gis\tw_road\tw_road_wkt.csv", "w", encoding="utf-8") as f: f.write("class,wkt\n") # 表头:等级与几何 for feat in layer: cls = feat.GetField("Class") geom = feat.geometry() if geom is None: continue # 空几何直接跳过,避免写坏行 wkt = geom.ExportToWkt() f.write(f"{cls},{wkt}\n") ds = None # 手动释放数据源,Windows 上不释放会锁文件

逻辑说明:feat.GetField("Class")按字段名取值,geom.ExportToWkt()把几何对象序列化成 WKT 字符串。字段名对不上会直接抛异常,跑之前先打印layer.schema确认字段写法。

这段脚本默认用 shp 自带的坐标系输出 WKT。要强制转 WGS84,需要额外调用osr做坐标变换,处理思路是:源坐标系读取 shp 的 .prj,目标坐标系设 EPSG:4326,再用geom.Transform(transform)转换。导出后抽样对比几段路的经纬度数值,就能确认没偏。

4.3 导出后怎么验证数据没丢

导出完不是直接扔进项目里完事。我有个习惯:先数行数,再抽查拐点。ogr2ogr转换后,用如下命令统计 CSV 行数:

wc -l tw_road_wkt.csv

行数应该和原 shp 的属性表行数一致,偏差超过 1 说明有要素因为几何为空被跳过了。再选一条熟悉的道路,比如从台北到桃园的某段高速,在 QGIS 里对比原始几何和 WKT 画出的是否一致,比如拐点数量和形状有没有收敛,偏差不超过 2 个点,说明转换无损。

5. 避坑清单:坐标系、乱码、字段截断与无图层的真凶

这套数据我踩过的坑不少,挑五个典型记录下来,照着排查能省很多时间。

坑一:整层偏移 300 米,叠在线底图上是歪的。现象:图层单独看没问题,叠加到在线卫星图后,道路和建筑明显不重合,整体平移了几百米。 原因:数据实际是 TWD97 投影坐标系,但打开时 QGIS 自动按 WGS84 识别,坐标系一错,几何数值被当成经纬度显示。 解决:右键图层选「图层属性 → 源 → 强制图层 CRS」,手动指定为 TWD97 对应的 EPSG 代码,坐标值和图面立即归位。注意是「强制」,不是「重投影」。

坑二:属性表里中文全是乱码。现象:dbf 字段里的中文路名显示成「鍙板」「閬撹」这种。 原因:dbf 的编码声明文件缺失或写的是 BIG5,QGIS 默认按 UTF-8 读,必然乱码。台湾早期数据很多是 BIG5 编码。 解决:在「图层属性 → 源 → 数据源编码」里手动改成 System(BIG5),或者改成 UTF-8,切换后立即重载属性表,再重新导出成 UTF-8 的 shp 或 CSV。

坑三:属性字段名被截断成 10 个字符。现象:本应是ROAD_CLASS_CODE,打开后变成ROAD_CLASS_,字段名不全。 原因:shapefile 的 dbf 格式规定字段名最长 10 字符,超出部分被截断。这不是数据损坏,是格式硬限制。 解决:直接用截断后的字段名写表达式,或先在 QGIS 里用「重命名字段」把名改短。写脚本时用layer.schema打印实际字段名,别凭记忆写。

坑四:乡道图层提取后要素数量骤减。现象:用"Class" = 'Y'提取乡道,结果只剩几百条,而属性表里明明有好几千。 原因:Class字段里乡道可能混着Y、Y1、Y2多种代码,精确匹配只抓到了纯Y的。 解决:改用"Class" LIKE 'Y%'模糊匹配,或先去重统计出所有取值再写表达式。这也印证了第 3 章先统计数据再动手的做法是对的。

坑五:Python 跑导出时报「Permission Denied」。现象:代码运行到一半报错,提示文件被占用,第二次跑也一样。 原因:上一次运行没有释放数据源,Windows 把 shp 文件锁住了。QGIS 开着这个图层时,脚本也是打不开的。 解决:脚本末尾必须写ds = None,运行前关闭 QGIS 里打开的同名图层。我自己后来养成的习惯是导出脚本第一行先尝试删掉旧的输出文件,代码里加一句清理逻辑,一劳永逸。

6. 最后一公里:把 WKT 数据接进路径分析和离线底图

数据转成 WKT 之后,用途一下就打开了。我最近一次是把这套路网接进一个离线物流路径分析的实验里,用 PostGIS 的pgRouting插件直接加载 WKT 文本建拓扑,跑最短路径。关键步骤是用ST_GeometryFromText把 WKT 列转成空间字段,再走pgr_createTopology建拓扑。这一步对数据质量要求很高,尤其是乡道和县道的接点必须严格共点,否则建出来的拓扑是断的,路径经常绕远路。这套数据在接点上的处理算规整,比我之前处理过某些开源路网好很多。

想快速验证数据能不能用,有个零成本的土办法:直接把 WKT 粘到在线坐标预览工具里,比如 geojson.io 的代码面板,选择 WKT 模式贴上,能正确渲染成线段就说明几何没坏。我每次处理新数据都会拿一段最复杂的乡道交叉口做测试,交叉口都没问题,整条路大概率没问题。这样验证一次,比后面跑路径规划才发现错误,效率高得多。

往后我每拿到一套矢量数据,都强制走一遍这个流程:先查字段字典,再确认坐标系,再转 WKT 抽样验几何,然后才敢接进项目。这套流程看起来很基础,但每次能挡掉不少事后返工的活。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 8:26:18

Python打卡第32天

浙大疏锦行 类的装饰器: 01 02 03 04 05 06 07 08 09 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 def class_logger(cls): """ A class decorator that adds a lo…

作者头像 李华
网站建设 2026/10/28 3:29:24

RFID抗金属标签在智能制造中的选型与部署实战指南

1. 从一张“贴不上”的标签说起:RFID抗金属标签到底解决了什么问题做过智能制造产线改造的人大概率都遇到过这种尴尬:花大价钱上了RFID读写器和系统,结果在金属工装板、金属托盘、金属货架上贴标签时,读取率直接崩盘。普通不干胶R…

作者头像 李华
网站建设 2026/10/28 6:12:37

番茄识别数据集构建与训练避坑实战指南

简介:面向目标检测任务的番茄识别数据集,共含4786张番茄图片的标注信息,类别覆盖未成熟番茄、成熟番茄和患病番茄,适用于YOLO系列、Faster Rcnn、SSD等主流目标检测模型的训练与评估。压缩包共2000个文件,以txt标签文件…

作者头像 李华
网站建设 2026/11/5 8:52:28

Python开心消消乐源码实战:游戏循环、匹配判定与改造技巧

简介:Python项目实例源码,实现经典三消游戏开心消消乐,面向Python初学者与游戏开发爱好者,完整呈现休闲消除类游戏从界面搭建到核心逻辑的实现过程。资源共138个文件,涵盖92张png游戏素材、20组mp3/ogg背景音乐与音效、…

作者头像 李华
网站建设 2026/10/29 14:37:21

2026 企业 AI 办公工具选型指南:从评估框架到产品适配

一、企业选 AI 办公工具,为什么不能只看功能列表 不少企业在调研AI办公工具的初期,很容易陷入几个典型的选型误区:有的团队把不同产品的功能列表拉出来逐行比对,谁的功能条目多就优先纳入采购清单,最后上线之后才发现大…

作者头像 李华
网站建设 2026/10/29 22:33:31

【华科大船海学院主办、AFME2026分会、EI检索、JPCS出版】2026年智能船舶与海洋工程国际学术会议(ISOE 2026)

在全球航运智能化与海洋开发向深远海迈进的交汇期,智能船舶与海洋工程正成为推动海洋战略与绿色转型的核心力量。随着智能传感、数字孪生及AI技术的集群突破,船舶设计运营模式被重新定义;同时,海洋工程向深远海与极地的拓展&#…

作者头像 李华