☰
郑州市OSM道路数据处理与路网分析实战指南
2026/10/3 10:51:52 网站建设 项目流程

简介:郑州市道路网络矢量数据集基于OpenStreetMap(OSM)开源地图项目,已经过预处理,面向GIS开发者与城市规划研究人员,可用于道路网络分析、交通规划及可视化展示等场景。压缩包共9个文件,约4.49MB,包含核心几何数据.shp、属性表.dbf、坐标参考系统.prj等Shapefile标准组件,并附有一张OSM类别对照表.jpg,便于理解道路分类与OSM标签的对应关系。已有395人学习下载。数据集涵盖郑州市道路的线性几何、属性分类与道路名称,可直接在QGIS、ArcGIS等软件中加载,执行最短路径分析、交通热点识别,或与人口、公交线路等其他数据进行叠加分析,为城市规划、交通管理及应急响应等应用提供基础数据支持。

1. 这份“已处理”的OSM道路数据,到底能帮你少踩多少坑?

做城市规划、交通分析或地图可视化的朋友,多半都有过这样的经历:从 OpenStreetMap 下载到的郑州市道路数据,打开一看,坐标系是 WGS84 经纬度,道路类型全靠highway字段里的几十种英文值区分,而且路网断头、重叠、悬挂线到处都是,连做个最简单的路网密度分析都得先花两天洗数据。这份标题里的“郑州市OSM道路矢量数据(已处理)”,就是针对这个痛点来的——它不再是你自己从 OSM 原始导出的一堆“毛坯路网”,而是已经完成投影转换、拓扑清洗、属性重构的“精装修”数据。本文会把这份数据的来龙去脉、加工逻辑、使用方法和踩坑点一次讲透,让你拿到手就能直接用,而不是再交一遍数据清洗的学费。

2. 从OSM原始数据到“已处理”产物:背后动了哪三刀

要理解这份数据,先得知道 OSM 原始数据长什么样,以及“已处理”到底意味着什么。我见过太多工程师拿到 OSM 数据就直接做分析,结果写在论文里被审稿人问“你的路网拓扑处理过吗”就直接卡住。处理过的数据和原始数据之间的差距,绝不是换个坐标系那么简单。

2.1 数据加工的第一个层次:坐标系转换

OSM 的原始数据一律使用 WGS84 经纬度坐标,这个坐标系是个球面坐标系统,单位是度,不适合做长度和面积量算。做郑州市层面的路网分析,常见做法是转换成 CGCS2000 / 3-degree Gauss-Kruger zone 38(即 EPSG:4547)或者 Web Mercator(EPSG:3857)。

我一般会强烈建议用 CGCS2000 的高斯投影,因为这个坐标系在郑州地区的长度变形小于 1/10000,做道路长度统计、缓冲区分析时数据才是可信的。Web Mercator 虽然浏览器兼容性好,但它的面积变形在郑州这个纬度(约北纬 34°)会膨胀 2 倍左右,做密度类分析会出大问题。

# QGIS 中查看当前图层坐标系 # 在图层属性 -> 信息 -> 坐标系 中确认 # EPSG:4547 是 CGCS2000 / 3-degree Gauss-Kruger zone 38,覆盖河南地区 # 如果原始数据是 WGS84(EPSG:4326),用"重投影图层"工具转换

很多新手在这步最容易翻车:拿着经纬度坐标的数据直接叠加 CGCS2000 的底图,结果道路全部偏出地图边界。处理好的数据会直接给你投影坐标系,省掉这个最容易出错的操作。

2.2 拓扑清洗:把毛坯路网变成可计算的路网

原始 OSM 数据的第二个痛点是拓扑混乱。道路在路口处经常没有精确相接,公共边重复绘制,还有大量只绘制了一半的断头路。这些在可视化里看不出问题,但一旦做网络分析(最短路径、等时圈),结果会让人崩溃——因为路网根本连不上。

处理过的数据会对道路进行拓扑重建,具体包括三个动作:

  1. 断链处理:把在路口相交但不共节点的线在交点处断开,生成真正的节点。这步在 ArcGIS 里叫“打断相交线”,但要注意打断后需要重建拓扑关系。
  2. 重复边合并:对于双向道路被画成两条几乎重合的线的情况,将其合并成一条中轴线,字段里用oneway或双向标记走向。
  3. 悬挂线检查:长度小于阈值(通常取 3 米)的悬挂线会被删除或标记为待核查。

处理前后最大的观感差异是:原始数据里有大量“毛刺”——几条十几厘米长的短线互相重叠交叉,处理后的数据画面干净得多。

2.3 属性字段重构:从 highway 到面向分析的字段体系

OSM 原始数据的highway字段是分类的核心,但它的取值极其庞杂,光道路类就有 motorway、trunk、primary、secondary、tertiary、unclassified、residential、service、living_street 等近 20 种,而且还混着 footway、cycleway、path 等非机动车道类型。分析时要自己过滤,非常麻烦。

处理后的数据一般会重构字段结构,常见做法是新增中文分类字段(如道路等级),把 OSM 的英文分类映射到国家标准体系。比如 motorway 映射为“高速公路”,trunk 映射为“快速路”,primary 映射为“主干道”,secondary 映射为“次干道”,tertiary 映射为“支路”。同时保留原始highway字段供你自行二次细分。

字段重构的价值在于:你可以直接在属性表里按“主干道”筛选,而不是写一长串WHERE highway IN ('primary', 'trunk', 'motorway')——这是一个非常真实的生产力提升。

3. 读懂坐标系与投影:郑州的道路数据到底落在哪套坐标里

处理好的数据通常已经给出了明确的坐标系定义,但你需要真正理解它是什么,否则后续叠加其他数据源时还会犯糊涂。数据拿到手后不要急着做分析,先花五分钟确认坐标系——这是所有地理数据工作的第一性原理。

3.1 WGS84经纬度到地方投影的转换路径

郑州位于东经约 113.6 度,北纬约 34.7 度,处于高斯-克吕格投影 38 度带的覆盖范围内。OSM 数据是 WGS84 经纬度,直接换算到 EPSG:4547 后,你会看到坐标数值从(113.6, 34.7)这样的度变成几百米的千米级数值——这是高斯投影带内的以米为单位的平面坐标。

如果你拿到的处理数据是 EPSG:3857(Web Mercator),它也能用,但这个坐标系只适合做底图显示和前端可视化,不适合做长度和面积量算。做统计分析的底线是:量算类操作必须在投影坐标系下做,而不是在经纬度下做。

-- SQL 示例:PostGIS 中把 WGS84 数据重投影到 EPSG:4547 ALTER TABLE zz_roads_processed ALTER COLUMN geom TYPE geometry(LineString, 4547) USING ST_Transform(geom, 4547); -- 走查:转换后检查长度变化 -- 原本经纬度下无法直接算长度,转换后可以用 ST_Length 统计 SELECT SUM(ST_Length(geom)) AS total_km FROM zz_roads_processed; -- 结果单位是米,除以 1000 得到公里数

投影转换后一定要做一次全量长度统计作为“合理性检查”。郑州市建成区道路总里程大约在 3000~5000 公里量级,如果你算出来只有 200 公里或者有 5 万公里,那一定是有地方错了——要么是坐标系没转对,要么是数据裁剪范围不对。合理范围的检查是数据工程师的底线意识。

3.2 在QGIS里快速验证数据坐标系的正确性

拿到数据后先做三件检查,哪怕你不是 GIS 专业出身也要会:

  1. 打开图层属性,看坐标系是否是 EPSG:4547、EPSG:4490 或者 EPSG:3857 之一;
  2. 加载一个在线底图(如天地图或 ESRI 影像),把道路数据叠加上去,看道路是否和影像上的道路对齐;
  3. 看看道路图层能否正常显示中文属性,属性表里打开道路名称这一列,确认不是乱码。

如果第一步发现坐标系是空的或者未知,那就是数据出问题了,千万别用。如果第二步对不齐,不要轻易手动平移——很可能是坐标系搞错了,应该回去确认坐标系定义。

3.3 统一坐标系:跨数据源叠加分析前的必做动作

实际工作中,你手里绝不是只有这一份数据。你还会有行政区划边界、土地利用现状、POI 点数据、影像底图,这些数据来自不同口径,坐标系可能五花八门。最稳妥的工作流是:把所有数据统一到一个坐标系下再做任何叠加操作。

我自己的经验是,在郑州项目里我会把行政区划边界、POI、路网统一到 EPSG:4547。这个坐标系是 CGCS2000 下的高斯投影,和目标区域完全匹配。注意这里有一个隐藏坑:如果底图是遥感影像的 Web 服务(通常是 EPSG:3857 切片),叠加分析时请先确认你用的是不是“动态投影”模式——QGIS 会自动做即时转换,但 ArcGIS 里有时候需要手动开“后台处理”。

统一坐标系之后,做缓冲区、做叠加统计、做路网密度计算,出来的结果才是有意义的数字,而不是一个仅供可视化的“图”。这个原则比任何具体工具都重要。

4. 把数据用起来:道路筛选、拓扑建网与网格化统计

数据拿到手,第一步是筛选你需要的那部分。全量道路数据包含所有等级的机动车道和非机动车道,通常处理后的数据还会保留人行道、自行车道等 OSM 要素,这些在你只需要机动车路网时是要剔除的。

4.1 用字段筛选快速提取指定等级道路

处理后的数据一般有类级或level字段,按照从高速到支路的顺序排列。做路网分析时通常只需要保留机动车道,过滤条件是等级在“支路”及以上,同时剔除人行道、阶梯、行人区。

-- 使用 SQL 筛选机动车道路网 CREATE TABLE zz_roads_motor AS SELECT * FROM zz_roads_processed WHERE 类级 IN ('高速公路', '快速路', '主干道', '次干道', '支路') AND 类级 IS NOT NULL; -- 逻辑说明: -- 直接排除 footway、cycleway、path、steps 等非机动车道类型 -- 这些类型在 OSM 原始数据里很常见,不排除会把路网密度统计抬高 -- 类级字段是处理时映射的,若你的数据里没有这个字段, -- 退回使用原始 OSM 的 highway 字段筛选: -- WHERE highway IN ('motorway','trunk','primary','secondary','tertiary','unclassified','residential')

筛选这一步看着简单,但有一个细节:OSM 原始数据里residential(居住区道路)和unclassified(一般等级未分类道路)数量非常大,它们在城市道路统计里通常算作支路级别。如果你在计算路网总里程时把它们排除,结果会比真实值少很多。要不要包含这两类,取决于你的分析目标——如果做“机动车可通行总里程”,建议包含;如果只统计“县级以上道路里程”,则排除。

4.2 拓扑建网:把可视化的线变成可计算的路网

处理过的数据虽然已经断链,但在导入 PostGIS 之后还需要一步动作——构建拓扑网络。PostGIS 的pgr_createTopology函数用来生成路网的节点和连接关系,给最短路径分析做准备。

-- PostGIS 路由分析前必须执行的拓扑构建 SELECT pgr_createTopology('zz_roads_motor', 0.0001, 'geom', 'id'); -- 参数说明: -- 第一个参数是表名,第二个参数 0.0001 是容差(单位与坐标系一致,这里是米) -- 0.0001 米容差意味着距离 0.1 毫米内的节点会被合并,这个值对处理过的数据足够 -- 第三个参数是几何列名,第四个参数是主键列名 -- 拓扑构建完成后,表里会多出 source 和 target 两列,记录每条线的起终点节点 ID

执行完拓扑构建,你可以立刻做一个连通性检查:

-- 找出孤立的道路子网(不能从主路网到达的部分) SELECT count(*) FROM ( SELECT DISTINCT source FROM zz_roads_motor WHERE source NOT IN ( SELECT target FROM zz_roads_motor ) ) AS isolated_nodes; -- 如果结果接近 0,说明路网连通性良好;如果几百上千,说明数据存在问题 -- 不过注意:城市路网中确实存在“飞地”路段,比如被铁路隔断的局部支路

拓扑构建失败或者连通性差,多半是因为容差设置不当。容差太大,会把近在咫尺但不相连的道路错误合并;容差太小,断链处没接上,后续路径规划就会绕远路。处理过的数据已经断链,容差可以设得比较小,0.0001 到 0.01 之间是常用区间。

4.3 网格化统计:1公里网格内的路网密度计算

做城市规划分析,路网密度是绕不开的指标。处理后的路网数据可以直接拿来计算:把研究区分成 1km x 1km 的网格,统计每个网格内的道路总长度。

-- 生成网格并计算路网密度(米/平方公里) CREATE TABLE zz_grid AS SELECT (ST_PixelAsPolygons(ST_SetValues( ST_AddBand(ST_MakeEmptyRaster(50, 50, ST_XMin(ST_Extent(geom)), ST_YMin(ST_Extent(geom)), 1000, 1000, 0, 0, 4547), 1, 0))) ).geom AS grid_geom FROM zz_roads_motor; -- 上面这段生成 1km 网格比较复杂,我实际更常用 QGIS 的"创建网格"工具: -- 矢量 -> 研究工具 -> 创建网格,网格类型选择"多边形",宽度/高度设为 1000 米 -- 高级:直接用 ST_Subdivide 或 Bbox 方式按已知研究区边界生成网格

网格生成后,用空间连接统计每个网格内的道路总里程:

-- 空间连接统计道路长度 CREATE TABLE zz_grid_density AS SELECT g.id, g.grid_geom, COALESCE(SUM(ST_Length(ST_Intersection(r.geom, g.grid_geom))), 0) AS road_m FROM zz_grid g LEFT JOIN zz_roads_motor r ON ST_Intersects(r.geom, g.grid_geom) GROUP BY g.id, g.grid_geom; -- 说明: -- ST_Intersection 会精确切割道路落在网格内的部分,再统计长度 -- 这样避免了整条道路跨越多个网格时在多处重复计算的问题 -- COALESCE 把没有道路的网格记作 0,而不是 NULL -- 最后 road_m / 1000 / (1km*1km) 得到公里/平方公里的密度值

这个统计在 ArcGIS 里可以用“空间连接-求和”直接达成,但 PostGIS 的 SQL 方式好处是结果可复现——你在脚本里留下公式,以后换城市、换数据源,只要改表名就能重跑。我做这类分析时永远不会用 GUI 操作完就交付,因为半年后回溯时需要能回答“这个数字是怎么来的”。

5. 避坑指南:OSM数据处理的5个高频坑

数据处理和分析做了这么多年,见过的问题五花八门。这里挑 5 个最常见的坑,按“现象 → 原因 → 解决”的方式记录,希望你能少走点弯路。

5.1 坐标系搞错,叠加天地图底图全偏

现象:把路网数据拖进 QGIS,叠加在线天地图后发现道路与卫星影像中的道路错位了几百米,而且偏差方向不固定。

原因:OSM 原始数据是 WGS84 经纬度,在叠加 Web 墨卡托底图时被直接当作 Web Mercator 投影的平面坐标使用,坐标数值没变但单位被错解成米,导致数据被“压扁”在错误位置。

解决:拿到任何 OSM 数据的第一步永远是确认坐标系定义,不要相信文件名的“已处理”字样。检查方式:图层属性里看坐标系是否明确,用信息工具点击道路查看坐标值——如果坐标值在 113 左右的(经纬度),说明还是 WGS84;如果坐标值在几千上万(米制),确认是投影坐标系。确认是 WGS84 后,用“重投影图层”转到目标投影坐标系再做分析。

5.2 中文路名字段显示乱码

现象:属性表里打开道路名称字段,中文全部显示为“锟斤拷”或者方框乱码,英文和拼音正常。

原因:处理数据时把 GBK 编码的 CSV 或 Shapefile 的 dbf 文件当成 UTF-8 读取,或反过来。OSM 原始数据的 name 字段在社区编辑中大量使用中文,势必涉及编码处理。常见的坑是对 Shapefile 的 dbf 头文件里的语言驱动标识处理不当。

解决:如果数据是 GeoJSON 或 GPKG,直接用 QGIS 打开一般没问题;如果是 Shapefile,在 QGIS 中选择图层时要注意编码选项,手动指定 UTF-8 或 GBK 重载。更省心的方法:在 PostGIS 里读一次数据,统一让数据库管理编码,应用程序从数据库读取就不会有编码问题。

5.3 立交桥断链导致路口拓扑异常

现象:路网在其他地方都正常,唯独在互通立交、高架桥区域出现大量断头,做路径规划时车辆会“飞”上去或者无法上下匝道。

原因:OSM 对立体交叉的处理思路是画多条平面线段,用layer或bridge标记上下层关系,但处理时如果没有把layer字段纳入断链逻辑,匝道和主路的上下层线段就会被错误地做立体连接,或者反过来该连接的地方没连上。

解决:处理数据时给匝道、桥面加空间属性特征区分,断链时先按layer标签区分层级,再在同一层内打断。拿到处理后的数据时,检查立交桥位置是否保留匝道口,如果确实有断链,手动在 QGIS 打开节点编辑模式修复,或者用“拓扑检查器”插件扫描,批量修复所有 source/target 不匹配的悬挂节点。

5.4 道路分级字段缺失,一条路“身份不明”

现象:用“道路等级”筛选时发现很多道路没有等级字段,统计里程时分不到任何等级类别里,结果偏低。

原因:OSM 原始数据中大量highway标签缺失或用了非标准值(比如highway=road表示“不知道是什么路”),处理时映射表没有兜底规则,这些路就被丢弃了。

解决:处理时对这类道路采用“未知等级 → 支路”的兜底映射,保证所有机动车道都归入可统计的等级框架。拿到数据处理后,先检查有没有“未知”或“未分级”的类别,数量别超过总长度的 5%。如果超过,在分析报告里把这个比例写清楚,这是诚实的数据态度。

5.5 面积/长度统计失真——投影坐标系的选择陷阱

现象:用 EPSG:3857(Web Mercator)做面积统计,结果比真实值大了 20% 以上;做缓冲区分析,缓冲区形状在视觉上是圆形的,但实际面积远不是理论值。

原因:Web Mercator 是等角投影,在高纬度地区面积变形极其严重。郑州虽然在中纬度,但面积变形仍然不可忽略——在 34.7°N 纬度上,Web Mercator 的面积膨胀约 1.7 倍到 2 倍。

解决:核心原则——量算和统计分析一律用高斯投影(EPSG:4547)或 UTM 投影(郑州对应 EPSG:32650)。Web Mercator 只用于屏幕显示。我自己的项目里,所有计算结果输出部署前都会用投影坐标系重算一遍,把“显示坐标系”和“分析坐标系”严格分离。

6. 进阶技巧:用空间索引把百万级道路数据的查询压到秒级

处理后的郑州路网数据量虽然不算巨大,但做城市级分析时总免不了叠加、缓冲区、空间连接这些高开销操作。空间索引用好了,性能提升按数量级计算。

6.1 构建空间索引

-- PostGIS 中给道路表创建空间索引 CREATE INDEX idx_zz_roads_geom ON zz_roads_processed USING GIST (geom); -- 说明: -- GIST 索引专门用于空间数据,配合 ST_Intersects、ST_DWithin 等操作符 -- 创建后可以立刻对比查询时间: -- SELECT COUNT(*) FROM zz_roads_processed WHERE ST_Intersects(geom, ST_GeomFromText('...')) -- 索引建好后第一次查询仍可能较慢,第二次开始显著提速

不要指望空间索引在建完后所有操作都变快——它的本质是缩小“参与运算的候选集”。道路数据越多,索引加速越明显。如果 PostGIS 做叠加分析仍然慢,可以尝试用 ST_Subdivide 把长线段切碎,让每个小块进入独立索引范围。

6.2 用SQL完成道路缓冲区的批量生成

-- 给所有快速路生成 50 米缓冲区,用于分析道路两侧用地 CREATE TABLE zz_roads_buffer AS SELECT id, ST_Buffer(geom, 50) AS buffer_geom FROM zz_roads_processed WHERE 类级 IN ('快速路', '主干道'); -- 参数说明: -- ST_Buffer 的第二个参数是缓冲半径,单位与坐标系一致,这里是米 -- 注意:在 EPSG:4547 下 50 米就是 50 米,但如果在 EPSG:3857 下做缓冲区 -- 实际空间范围会因投影变形产生误差,务必先确认坐标系 -- 批量缓冲后建议检查生成的缓冲区是否有自相交情况

缓冲区生成后有一步很多人会忽略:检查生成的缓冲区几何是否有效。ST_IsValid 可以排查,对无效要素做 ST_MakeValid 修复。这是防止后续叠加统计时报错的关键步骤。

6.3 交叠道路的拓扑校验与修复

处理后的数据偶尔也会有遗漏,尤其在 OSM 社区最近更新的区域。做网络分析前,跑一遍全库自相交检查是有必要的。

-- 找出自身相交的道路 SELECT a.id, ST_Intersection(a.geom, b.geom) AS intersect_geom FROM zz_roads_processed a, zz_roads_processed b WHERE a.id < b.id AND ST_Intersects(a.geom, b.geom) AND ST_GeometryType(ST_Intersection(a.geom, b.geom)) IN ('ST_Point', 'ST_MultiPoint'); -- 如果结果里只有“点”,说明是正常的十字交叉或立交 -- 如果出现 LineString 类型的相交,说明两条线有重叠段,需要合并或修正 -- 修复重叠段:用 ST_LineMerge 合并同一道路的重叠线 UPDATE zz_roads_processed SET geom = ST_LineMerge(geom) WHERE ST_IsValid(geom) = false;

我的习惯是:跑完修复再补一次ST_IsValidDetail看错误类型和位置,批量导出错误要素到单独图层,人工抽查一遍。数据质量不是一次检查能保证的,尤其是 OSM 这种众包数据,在月度更新后务必重新跑一遍拓扑校验。希望这个工作流能帮你在郑州路网数据上少踩几个坑。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询