简介:面向GIS分析与交通规划人员,提供重庆全市各级公路网络与区县行政区划矢量数据。资源按一级公路、二级公路、三级公路及高速公路分类整理,同时包含重庆各区县边界shp,可用于路网可视化、区域连通性分析、交通可达性计算及城市空间研究等场景。
包体共35个文件,压缩包约1.15MB。除几何数据shp外,还配齐dbf属性表、prj投影信息、shx索引及sbn/sbx空间索引,并附带xml元数据,适合在ArcGIS、QGIS等平台直接加载使用。结构简洁,命名规范,便于按公路等级或区县范围快速筛选调用。
已有680人学习下载,尤其适合需要基础路网底图开展教学实验、课题调研或业务制图的用户。结合人口、土地利用等数据后可进一步支撑交通规划、应急响应与城乡发展分析。
1. 重庆各级公路shp文件到底是什么
打开压缩包那一刻,你会看到一整套完整的公路分级矢量数据:重庆高速公路、一级公路、二级公路、三级公路,再加上各区县行政区划面。这不是单张shp,而是每个图层都标配了.shp、.dbf、.shx、.prj、.sbn、.sbx,甚至还有.xml元数据文件。也就是说,拿到手不需要修补坐标系,直接拖进QGIS或ArcGIS就能用,省去了最常见的“投影对不上”的麻烦。对于做区域交通分析、路网密度计算或者城市规划的人来说,这套数据最值钱的不是“有没有路”,而是“路分了几级”——高速公路、一二三级公路分别对应不同的通行能力、设计时速和规划口径,这决定了你能不能准确算路网等级结构、做缓冲区分析、甚至为应急路径规划提供基础底图。适合的人群很明确:GIS开发工程师、交通规划师、想做地图可视化的数据分析师,以及需要行政边界和路网叠加做空间统计的研究人员。需要注意的是,压缩包内容以重庆为范围,名称里的“四川”只是历史行政区划沿革的残留,实际使用以.shp边界范围为准。
2. Shapefile组成与公路等级编码规则
2.1 每个shp图层附带的那堆文件都是干什么的
一套完整的shapefile不是单个文件,而是一组配套文件的集合。你看到每个图层都有.shp、.dbf、.shx、.prj,这是最核心的四件套,缺一不可。.shp存几何坐标,.dbf存属性表,.shx是几何索引,.prj存坐标系信息。除此之外还有.sbn和.sbx,这是ArcGIS生成的空间索引文件,只影响查询性能,损坏了可以重建。.xml是元数据,记录图层来源、字段说明和坐标系信息,对数据校验很有用。
以重庆二级公路.shp这一套为例,常见的文件组合如下:
| 文件后缀 | 作用 | 缺失后果 |
|---|---|---|
| .shp | 几何数据(点线面坐标) | 无法显示地图 |
| .dbf | 属性数据(道路等级、名称等) | 无法查属性 |
| .shx | 几何位置索引 | 部分软件打不开 |
| .prj | 坐标系定义 | 坐标位置偏移 |
| .sbn / .sbx | 空间索引 | 加载变慢,可重建 |
| .xml | 元数据 | 不影响使用,但信息丢失 |
这套数据里每个图层的文件是完整的,.prj都在,这是好事。很多网上下载的道路shp只有.shp和.dbf,没有.prj,结果在QGIS里默认跑到WGS84上,跟其他数据一叠就跑到海里去了。拿到手第一步应该先看.prj内容,确认坐标系统。
2.2 公路等级在属性表里怎么编码
打开重庆高速公路.dbf,你会看到属性字段通常包括路名、编号、长度、等级等。不同数据源编码规则不一致,有的用中文“高速公路”“一级公路”,有的用代码“1”“2”“3”“4”。这份数据里从文件名能看出已经把等级拆成了单独图层,但属性表里仍然可能有“class”或“grade”字段,需要实际打开确认。
我一般拿到shp会先用QGIS的属性表看一眼字段类型和值域,再决定后续操作。常见做法是新建一个字段level_code,把高速公路赋值为1,一级公路为2,二级公路为3,三级公路为4。这样后面做样式分级、按等级做不同宽度渲染、或者导出成GeoJSON给前端地图用,都比直接用中文字段名更省事。
如果属性表里没有等级字段,也完全不用慌。因为文件名已经分层,直接在QGIS里按图层合并时手动指定等级即可。用Python的geopandas读取时也是同样道理:
import geopandas as gpd express = gpd.read_file("重庆高速公路.shp") express["level_code"] = 1 primary = gpd.read_file("重庆一级公路.shp") primary["level_code"] = 2 secondary = gpd.read_file("重庆二级公路.shp") secondary["level_code"] = 3 tertiary = gpd.read_file("重庆三级公路.shp") tertiary["level_code"] = 4 all_roads = gpd.concat([express, primary, secondary, tertiary], ignore_index=True) print(all_roads.crs)这段代码把四个等级图层分别读取,打上等级编码后纵向合并成一个完整路网。ignore_index=True是为了避免多个图层索引重复导致后续处理出错。合并前先打印crs确认坐标系一致,四个图层的.prj如果都是从同一来源导出的,坐标系应该相同,但保险起见还是检查一下,否则后续空间分析会出现“几何无效”或距离单位错误。
2.3 坐标系判断:prj里写的到底是什么
打开重庆各区县.prj,常见的坐标系有两种:一种是GCS_WGS_1984,经纬度单位;另一种是CGCS2000_3_Degree_GK_Zone_35或类似投影坐标,单位是米。如果是经纬度,算距离时先转投影;如果是投影坐标,直接就能算长度。
用文本编辑器打开.prj可以看到完整定义。QGIS里双击图层也能看到CRS信息。如果发现四个公路图层的坐标系跟区县图层不一致,建议统一用重庆本地的投影坐标系,比如EPSG:4547(CGCS2000 / 3-degree Gauss-Kruger CM 108E),因为重庆大致位于东经108度附近。这样后续做缓冲区、算路网密度,单位都是米,不用再换算。
3. 加载、预览与基本检查
3.1 用QGIS加载并查看路网拓扑
把压缩包解压后,QGIS里直接拖拽.shp到图层窗口即可。如果安装了QGIS,推荐先打开重庆各区县.shp,用半透明填充作为底图,再叠加四个公路图层。这样能快速看出道路分布是否合理,比如高速公路是不是跨区县连续,有没有断头路。
加载后按F6打开属性表,重点检查几个字段:道路名称是否完整、是否出现大量空值、几何类型是不是LineString。有一种常见坑:某些shp文件内容本来是线,但属性表里混入了点或多点,导致后续网络分析报错。可以用QGIS的“检查几何有效性”工具跑一遍,工具在“矢量”菜单下的“几何工具”里。如果出现“自相交”或“重复节点”问题,先记下来,后面用特定方法修复。
3.2 命令行快速检查shp文件是否完整
没有图形界面时,用ogrinfo命令能快速看图层几何类型、字段列表和要素数量。这是GDAL自带的工具,跨平台可用。打开终端执行:
ogrinfo -so 重庆高速公路.shp 重庆高速公路-so是只读汇总,不遍历全部要素。输出里会显示Layer name、Geometry类型、Feature Count以及所有字段名和类型。这条命令最大的价值是快速确认shp有没有损坏、字段有没有丢失。如果ogrinfo报错“Failed to open shapefile”,先检查.shx是否跟.shp在同目录且文件名一致,这是最常见的打开失败原因。
参数说明:第一个参数是shp文件路径,第二个参数是图层名。因为在shapefile格式里,图层名默认就是文件名去掉后缀,所以这两个参数通常一样。如果记不住,也可以只写文件路径,不写第二个参数,ogrinfo会列出该文件所有图层。
3.3 用Python做一次路网完整性校验
如果想做更细的校验,比如检查每条路是否有节点、有没有孤立路段,写段Python脚本最方便。用geopandas读取后,查看几何类型和边界:
import geopandas as gpd roads = gpd.read_file("重庆一级公路.shp") print(roads.geom_type.unique()) # 应输出 LineString print(roads.is_valid.sum(), "条有效几何") print(roads.geometry.length.min()) # 最小长度,单位为度或米geom_type.unique()能看出来有没有混入Point或Polygon。is_valid是shapely的几何有效性检查,如果出现False,后面做缓冲区、叠加分析时很可能会有异常结果。长度单位取决于坐标系,如果是WGS84经纬度,长度单位是度,读数没有实际意义,需要转换为投影坐标系再算。常见做法是用roads.to_crs(epsg=4547)转换后再算长度。
4. 按等级提取、缓冲区分析与shp转txt实战
4.1 提取某一条高速公路的沿线缓冲区
重庆高速公路.shp里包含多条高速线路。假设需要分析G5001重庆绕城高速两侧3公里范围内的用地类型,第一步是按名称筛选出这条高速,然后建缓冲区。
在QGIS里用“按表达式选择要素”,表达式写:
"name" LIKE '%绕城%'选中后右键图层导出,保存为新文件。或者用Python:
import geopandas as gpd highway = gpd.read_file("重庆高速公路.shp") ring = highway[highway["name"].str.contains("绕城", na=False)] ring = ring.to_crs(epsg=4547) # 投影到米制坐标 buffer_3km = ring.geometry.buffer(3000) gpd.GeoDataFrame(geometry=buffer_3km, crs=ring.crs).to_file("绕城高速_3km缓冲区.shp")这里的关键是先把数据投影到EPSG:4547,这样buffer(3000)的单位是米。如果跳过投影直接在经纬度上做缓冲区,3000会被当成3000度,结果完全错误。这是shp处理里最常见的灾难性失误,我在很多项目里看到过坐标没转就直接做缓冲区的例子,出来的范围能覆盖半个中国。
4.2 把shp转成txt导出路网坐标
热词里经常有人搜“shp转txt”,实际场景是把路网坐标导出成文本,给交通仿真的路网生成工具或者自研地图引擎用。每一条路的每个折点坐标写一行,格式自定。用Python实现:
import geopandas as gpd import numpy as np roads = gpd.read_file("重庆三级公路.shp") roads = roads.to_crs(epsg=4547) with open("roads.txt", "w") as f: for geom in roads.geometry: if geom.geom_type == "LineString": for x, y in geom.coords: f.write(f"{x:.3f},{y:.3f}\n") elif geom.geom_type == "MultiLineString": for line in geom.geoms: for x, y in line.coords: f.write(f"{x:.3f},{y:.3f}\n")输出每行是一个点坐标,x和y分别是投影后的横纵坐标,:.3f保留到毫米级。如果后续要重建线段关系,最好每条线之间留一行空行或者标记线ID。这个例子里只输出坐标,适合做点集可视化,不适合做路网重建。如果你是想输出带线段起止关系的拓扑txt,建议同时把每条路在属性表里的唯一ID也写进去。
4.3 渔网分割shp:把大路网切成瓦片
做web地图加载大路网时,直接把整个shp转GeoJSON会很卡,常见做法是把路网切分成网格,然后分块处理。“渔网分割”就是生成一个规则网格,用空间裁剪把原图层切割成多个小块。QGIS里有“创建渔网”工具,参数包括网格范围、宽度、高度。也可以直接用Python批量炸开:
import geopandas as gpd from shapely.geometry import box roads = gpd.read_file("重庆各级公路.shp") xmin, ymin, xmax, ymax = roads.total_bounds grid_width = 10000 # 10km见方 cols = int((xmax - xmin) / grid_width) + 1 rows = int((ymax - ymin) / grid_width) + 1 for i in range(rows): for j in range(cols): minx = xmin + j * grid_width maxx = minx + grid_width miny = ymin + i * grid_width maxy = miny + grid_width grid_cell = box(minx, miny, maxx, maxy) clipped = gpd.clip(roads, grid_cell) if not clipped.empty: clipped.to_file(f"tile_{j}_{i}.shp")total_bounds返回整个路网的最小外接矩形,然后按10公里边长切网格。gpd.clip做的是几何裁剪,只保留落在网格内的线段,并用not clipped.empty跳过空网格。这个方案适合把重庆全境路网切块并行处理,切出来的每个tile都可以单独转成GeoJSON或者3D Tiles。注意这里的坐标系必须是投影坐标系,否则10000会被当成经度差,网格形状会变形。
5. 修复shp问题、转GDB与只保留外边界线
5.1 用shapechecker修复损坏的shp文件
从网上下来的shp十有八九会有拓扑问题,尤其是反复编辑过或者从CAD转换过来的。特征表现是QGIS打开后部分线段消失、属性表行数对不上、或者求长度时出现负数。这种情况下首选工具是ShapeChecker,一个免费的小工具,专门用来检查和修复shapefile的几何错误。打开软件后导入.shp,它会列出所有如空几何、重复顶点、线段自相交等问题,并一键修复。
修复前后最好做一次备份。因为ShapeChecker有时会改动顶点顺序,导致原本正确的方向字段反向。操作路径:启动软件,选择“File”里的“Open Shapefile”,等扫描结束,在问题列表里右键点击每一项,选择“Repair”,然后另存为新文件。修复后的shp再丢回QGIS里验证一遍,看要素数量是否和原始dbf记录数一致。
5.2 shp转gdb,是不是同一个东西
“shp转gdb”完全不是一个概念。shp是单文件集,gdb(File Geodatabase)是ArcGIS的文件夹式数据库,可以装多个要素类,支持拓扑规则、网络数据集和字段别名。如果项目要求把重庆各级公路全部塞进一个gdb里,用gdal命令最快:
ogr2ogr -f "FileGDB" 重庆公路.gdb 重庆高速公路.shp ogr2ogr -f "FileGDB" 重庆公路.gdb 重庆一级公路.shp -nln 一级公路第一条命令把高速公路写入gdb,第二条用-nln指定要素类名称,不然还是沿用原名“重庆一级公路”。写入后gdb里就会多一个名叫“一级公路”的要素类。gdb的好处是属性字段长度、索引、空间参考都统一管理,不需要维护一堆.sbn文件。但要注意,gdb不能跨平台在QGIS里直接读,除非把环境变量OGR_DRIVER_PATH配好,或者用GeoPackage代替,后者是跨平台的标准格式。
5.3 只保留外边界线:删除内部道路网
有时候做地图背景,只需要行政区边界,不需要内部路网。shp有没有办法只保留外边界线?如果是区县边界shp,内部有很多子边界,只保留外轮廓的方法是把面转线,再删掉非外环线。QGIS里用“Polygons to lines”把面转成线后,线属性表里有left和right字段,表示这条线左右两侧的面。正常情况下外部边界线一侧是地块,另一侧是空值。筛选条件:
"left" IS NULL OR "right" IS NULL这样就能滤出外边界线,导出后就是只保留外轮廓的shp。如果数据没有左右字段,用Python的shapely处理也可以:
import geopandas as gpd from shapely.geometry import LineString admin = gpd.read_file("重庆各区县.shp") admin = admin.to_crs(epsg=4547) outer_lines = [] for geom in admin.geometry: if geom.geom_type == "Polygon": outer_lines.append(LineString(geom.exterior)) elif geom.geom_type == "MultiPolygon": for part in geom.geoms: outer_lines.append(LineString(part.exterior)) outer_gdf = gpd.GeoDataFrame(geometry=outer_lines, crs=admin.crs) outer_gdf.to_file("重庆各区县_外边界线.shp")geom.exterior取Polygon的外环,MultiPolygon则逐个取。生成的结果一定是线要素,包含重庆市级外部边界,内部区县之间的分界线全部排除。这个技巧在做城市群专题图、去掉内部行政区隔线时非常有用。配合公路shp叠加,可以快速做出一张“只有边界+路网”的交通底图。
本文还有配套的精品资源,点击获取