ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

云南省河流水系shp数据加载与坐标系转换实战指南

云南省河流水系shp数据加载与坐标系转换实战指南 简介这是2024年云南省河流水系矢量图层数据属于地理信息数据集专为GIS开发者、测绘工程师、规划人员以及地理相关专业学生设计可满足地图制图、水文分析、生态评估、城乡规划等多种应用需求帮助使用者直接获得可编辑、可分析的水系基础图层避免从遥感影像或纸质地图中手工描绘河流的重复劳动。数据内部包含水系线和水系面两大要素类别总记录数达几千至一万余条划分详细既能展示大尺度流域格局也能保留小河流的细致走向坐标系统采用全球通用的WGS1984可在不同软件间无缝对接。整套资源压缩后约16.15MB共11个文件主要包括shp、shx、dbf、prj、cpg等类型分别存储几何、索引、属性、投影与编码信息并提供格式转换脚本方便用户将数据切换到其他常用GIS格式。当前已有233人学习下载。数据将云南复杂水网清晰分层主干与支流兼备用户可快速完成区域裁剪、专题着色或数据融合显著加快项目前期数据准备与底图搭建过程。1. 云南省河流水系shp数据拿到手先弄清分级与坐标系做水利或规划类项目的人都有这种经历上级给了一张云南省河流水系图你打开一看线条是有了但放大后跟卫星影像对不上或者想统计某条流域的河长发现属性表里全是乱码。这份2024版的云南省河流水系矢量图层shp数据正是为了省掉这些麻烦准备的。它把全省主要河流、支流、沟渠按等级做了分层属性表里有名称、级别和长度字段套上ArcGIS或QGIS就能直接用于制图、分析和出图。适合做水文分析、河长制公示牌部署、流域边界勾绘以及规划选址的从业者。先提醒一句拿到数据别急着拖进地图先看坐标系和字段结构后面所有操作都建立在这两步之上。2. 数据内容与坐标系字段表、投影参数与加载前检查2.1 河流水系矢量图层的字段组织方式打开shp文件的属性表这份数据的字段命名比较直观主要有三类标识字段、分级字段和几何计算字段。标识字段通常是GB码或内部编号用于区分每条河流的唯一身份分级字段用数字1到5表示河流等级1级是干流5级是末端沟渠几何字段里存的是长度和起点终点坐标长度单位取决于shp本身的投影坐标系。字段名在不同版本里可能有差异我见过有的叫“NAME”有的叫“河名”有的叫“grade”但核心信息是一致的。建议你拿到数据后先用ArcCatalog的预览功能看一眼字段列表不要双击直接打开因为ArcMap直接打开shp时如果缺少索引文件渲染会很慢。常见做法是先建一个文件地理数据库把shp导入进去顺便检查字段类型是否正确。# 用pyshp读取shp字段结构快速确认数据完整性 import shapefile sf shapefile.Reader(yunnan_rivers_2024.shp) fields sf.fields[1:] # 去掉deletion flag字段 for name, ftype, size, decimal in fields: print(f{name}: {ftype} 长度{size} 小数位{decimal}) # 统计要素数量核对数据是否完整 print(f要素总数: {len(sf)})上面这段代码用于加载前的快速体检。pyshp是纯Python库不需要ArcGIS环境就能跑适合在服务器或没有GIS桌面软件的机器上做数据预检。fields[1:]是为了跳过shp文件内置的删除标记字段真正的属性字段从这里开始。要素总数如果和发布说明里的数字对不上说明传输过程中可能有丢包或文件损坏。用GDAL读取更稳因为GDAL能同时读出投影信息。我一般会写一个两行脚本把投影字符串打出来确认是CGCS2000还是WGS84这一步决定了你后续所有坐标转换的方向。如果投影判断错了后面叠加任何其他数据都是白搭。from osgeo import ogr ds ogr.Open(yunnan_rivers_2024.shp) layer ds.GetLayer(0) spatial_ref layer.GetSpatialRef() print(spatial_ref.ExportToWkt()[:300]) # 只看前300字符足够判断坐标系2.2 CGCS2000坐标系与投影参数说明2024版的shp数据默认用的是CGCS2000国家大地坐标系投影方式是高斯-克吕格投影分带按3度带或6度带。云南省地处东经97度到106度之间跨越了3度带的33、34、35带也覆盖6度带的17、18带。很多新手在一张图里同时看到两条河想去量距离结果量出来数据完全不对多半是投影带选错了。实际操作中如果只是做全省范围的图可以直接用地理坐标系WGS84或CGCS2000的经纬度显示不需要重新投影。但如果做的是县域或者单个流域的精细化分析就必须按所在区域选择中央经线重投影。云南省常见的高斯投影参数中央经线选102度或99度。比如昆明周边项目中央经线102度比较合适怒江、德宏方向用99度。这里的规律是找离项目区最近的3度带中央经线。区域中央经线3度带带号适合场景昆明、玉溪、曲靖102°E34带县域制图、河长制管理楚雄、大理部分99°E或102°E33带或34带流域分水岭分析怒江、保山99°E33带小流域水文模拟昭通、文山105°E或102°E35带或34带跨省界河段投影参数用ArcGIS的Project工具设置时记得把地理坐标系转换也带上。CGCS2000和WGS84之间在云南地区的差值大约在0.1米到0.5米量级具体取决于控制点分布。你要是做的是大比例尺制图这种差距可能无所谓但做确权或者管线测量对照差距就必须修正。2.3 加载前的完整性检查清单先说一个坑shp文件不是一个单独的文件而是至少三个文件组成的集合——.shp存储几何.dbf存储属性.shx存储索引。这三个文件少了任何一个数据都打不开。经常有人只下载了.shp然后抓狂说数据损坏其实是没注意配套文件。完整性检查清单一般按这个顺序走第一步核对文件数量。除.shp、.dbf、.shx外最好还有.prj、.cpg、.sbn和.sbx。.prj缺失会导致ArcMap不认识坐标系默认按未知处理.cpg缺失会导致中文属性乱码这是最常见的翻车点。第二步用GIS软件打开后快速放大到昆明附近找滇池周边的河流看看有没有明显的断线或者交叉。水网数据里最常见的错误是河流在节点处没有打断两条河交差过去拓扑关系混乱。第三步检查是否有重复要素。选中所有要素打开属性表按GB码排序看有没有重复值。重复GB码说明有冗余数据统计河长时会重复计算。# 用GDAL的ogr2ogr做快速转换顺便验证文件能否正常读取 ogr2ogr -f GeoJSON yunnan_rivers_check.json yunnan_rivers_2024.shp -t_srs EPSG:4326 # 如果输出没有报错并且json文件大小不为0说明文件本身可读 ls -l yunnan_rivers_check.jsonogr2ogr是GDAL自带的命令行工具上面这条命令把shp转成GeoJSON。转换过程中如果shp损坏或缺少必要组件会有明确报错。转成的GeoJSON可以用QGIS直接打开用文本编辑器查看也行方便确认坐标系是否正确转换到了WGS84经纬度。注意-t_srs EPSG:4326参数这意味着输出结果从原始投影转换到了WGS84地理坐标系。如果你只是想做快速体检而不想改变原始数据把-t_srs去掉直接转GeoJSON即可。3. ArcMap与QGIS中加载水系数据符号化与标注的一次性设置3.1 ArcGIS中的加载与属性连接把云南省河流水系shp加载进ArcMap常规操作是点击添加数据按钮选中shp文件直接拖入。但这里有个容易忽略的细节ArcMap默认显示的是单一符号所有河流都是同一条细线根本分不清干流和支流。要想一眼看清河网结构需要按级别做符号化。右键图层打开属性切换到符号系统选项卡选择“类别-唯一值”值字段选分级字段。然后把1级河流设成2.6磅的深蓝色实线2级和3级设成1.6磅4级和5级设成0.8磅的浅蓝虚线。这套设置做完以后水系的主干和毛细分支立刻就能区分开。如果做河长制专题图需要把河流名称标注出来。标注时选名称字段设置最小显示比例尺为1:20万防止缩小后标注挤成一团。标注的优先级顺序推荐1级河优先显示2级河次之小沟渠最后。这样在1:50万以下比例尺出图时大江大河的名称保留小河名称自动隐藏图面干净不少。属性连接方面有时候需要把Excel里的监测断面数据连接到河流图层上。常见做法是通过GB码字段做一对多连接Excel表里每条河流有多个断面编码连接后河流属性表里会出现多条记录这时想按河流统计断面数量需要用“汇总数据”工具按GB码分组计数。3.2 按级别设置符号化与标注水系数据符号化没有统一标准但做水利的人大多采用蓝系配色。我常用的方案是1级河流用纯蓝色C0M10Y0K0线宽2.52级用C20M0Y0K0线宽差一个级别减0.53级以下用浅蓝配虚线。这套方案的逻辑是主航道视觉权重最高支流作为背景层出图时不会喧宾夺主。标注方面在ArcGIS的标注表达式里写一段简单脚本让不同级别的河用不同字号。比如1级河字号10加粗2级河字号83级以下字号6斜体。还可以加一条规则长度小于5公里的河流不标注避免图上全是字。// ArcGIS标注表达式按级别设置字号 function FindLabel ([级别], [河名], [长度]) { var size 8; if ([级别] 1) { size 10; } else if ([级别] 2) { size 9; } else if ([级别] 4) { size 6; } return FNT size size [河名] /FNT; }这段JavaScript用在ArcMap的标注表达式编辑器里。函数接收级别、河名、长度三个字段作为输入返回带字号的富文本标注。级别为1的河流字号10级别2的用9号字4级以上的小沟渠用6号字弱化。配合最小显示比例尺图面表达就能做到主次分明。注意表达式里字段名要用方括号包裹字段名中的中文或特殊字符在ArcGIS里必须这样引用。返回字符串里的FNT标签是ArcMap标注专用的富文本标签和HTML不完全一样不能直接套用。3.3 QGIS中另存为不同格式QGIS加载shp不需要太多设置拖入即用。有一点比ArcGIS方便QGIS能从.prj文件里自动识别CGCS2000无需手动指定。加载后在图层右键选择导出可保存为GeoPackage、GeoJSON、DWG等格式。如果想把这份水系数据发给同事用CAD打开QGIS里有一个比较稳的转换方法。# 用ogr2ogr把shp转成AutoCAD DWG格式 ogr2ogr -f DWG yunnan_rivers.dwg yunnan_rivers_2024.shp -lco HEADING云南省河流水系DWG转换需要额外配置库支持如果系统里没装对应组件这段命令会报错。替代方案是先把shp转成DXFDXF是文本格式几乎所有CAD版本都能打开。转的时候最好把要素按级别拆分1级河流转成一个图层2级河流转成另一个图层CAD里就能按图层开关控制显示。QGIS里还有一个独有优势可以直接把shp拖到3D视图里生成河网三维场景。配合DEM高程数据能让河流沿线的高程变化直观显示出来这对做淹没分析或者生态流量研判很有帮助。三维场景里河流线要素要设置Z值没有Z值就只能贴在地表上。4. 换格式与业务场景KML、JSON、Excel点转shp等常用转换4.1 把shp转成KML给移动端用野外巡河或者现场复核时拿着ArcGIS跑不方便常见的做法是把shp转成KML或KMZ导入奥维或手机地图App。转换前先想清楚一件事KML默认是WGS84经纬度坐标所以转换前要确认源数据是CGCS2000还是WGS84如果坐标系不一致就得先做转换。ArcGIS里的Layer to KML工具可以完成这个工作但图层必须已经设置了正确的坐标系。我通常先使用Project工具把shp从CGCS2000转为WGS84再转KML两步分开做容易排查问题。# 一步到位CGCS2000 shp转WGS84 KML ogr2ogr -f KML yunnan_rivers.kml yunnan_rivers_2024.shp -t_srs EPSG:4326转换成功后KML会保留属性字段里的名称和级别信息。手机App里打开KML时河流名称直接显示在地图上点击线条还能看到长度和等级。如果转出来的KML在手机上显示不了中文名称一般有两个原因一是dbf字段里的中文编码没有被正确识别二是手机App的KML渲染引擎不支持中文标注的富文本。4.2 用QGIS做Excel点转shp项目里经常遇到这样的场景现场记录的排污口坐标在Excel里经纬度列已经填好但需要转成点图层才能和河流叠加分析。QGIS里处理这个流程比ArcGIS直观原因是它自带“从分隔文本导入”的界面向导。Excel表格里至少要有一列经度、一列纬度格式必须是十进制度数。如果是度分秒格式先在Excel里转成十进制度再导入否则会出现点位满天飞的情况。# 排污口示例数据UTF-8编码的CSV 排污口编号,经度,纬度,所在河流 PS001,102.7156,25.0412,盘龙江 PS002,102.7123,25.0398,盘龙江 PS003,102.7067,25.0431,金汁河导入时QGIS会弹出坐标系选择窗口这里必须选EPSG:4326。然后右键图层选择导出要素另存为shp格式在保存对话框中把坐标系改成CGCS2000或对应的高斯投影。转换完成后点图层就和河流图层在同一个坐标系下了可以做缓冲区分析或距离计算。注意Excel导出CSV时一定选UTF-8编码否则导入后中文“排污口编号”会变成乱码。QGIS导入乱码处理起来麻烦最好在源头就搞定编码。4.3 json转shp与GeoJSON互操作很多在线数据平台现在提供GeoJSON下载有人在JSON里看到坐标数组就懵了。其实GeoJSON转shp用ogr2ogr一条命令就能搞定。# GeoJSON转shp ogr2ogr -f ESRI Shapefile yunnan_rivers.shp yunnan_rivers.geojson # 反过来shp转GeoJSON ogr2ogr -f GeoJSON yunnan_rivers.json yunnan_rivers_2024.shp -lco WRITE_BOMNO转换时最容易出错的是坐标嵌套层级。GeoJSON的coordinates数组可能是多层的比如MultiLineString里再套一层数组。如果ogr2ogr解析失败用QGIS打开GeoJSON看一眼数据的几何类型然后用“导出要素”另存为shpQGIS能自动处理复杂几何嵌套。shp转GeoJSON时默认输出没有UTF-8的BOM头有些国产平台解析会有兼容问题。加上WRITE_BOMYES可以解决一部分乱码问题。4.4 dwg转shp与反向转换规划口的人经常给水利院发来CAD地形图想把里面的水系线提出来和这份shp叠加。DWG转shp最常用的两种方式一是ArcMap的Import from CAD工具二是QGIS直接导入DWG。两种方式各有坑。# 在QGIS Python控制台里用原生CAD导入然后另存为shp layer iface.addVectorLayer(/path/to/river.dwg, river_cad, ogr) # 导入成功后右键另存为浙江省河流底图.shpCAD里一条多段线代表一条连续河段但CAD图里经常有重复线段导入后shp会出现很多重叠要素。处理办法是导入后用“删除重复几何”工具清理一遍然后用“按位置连接”把重复的河段属性合并。反过来shp转DWG给设计院用要注意线型定义。CAD里虚线、实线是靠图层线型控制的shp里的分级属性在转DWG后会变成属性块不会自动映射成线型。通常做法是导出前先在GIS里按级别拆分再把每个级别导出成单独的DXF文件CAD里手动挂线型。4.5 shp转txt的字段导出有时外部系统只接受文本格式的数据比如某个巡河App要求上传.txt文件里面是河流编码和坐标点序列。shp转txt用ArcGIS的Table to Table工具按属性导出就能做但要素坐标数据需要额外处理。# 用ogrinfo把shp属性导出成文本查看 ogrinfo yunnan_rivers_2024.shp -al -so # 用Python脚本把坐标落成txt python3 -c import shapefile sf shapefile.Reader(yunnan_rivers_2024.shp) with open(rivers.txt, w, encodingutf-8) as f: for sr in sf.shapeRecords(): name sr.record[1] for point in sr.shape.points: f.write(f{name},{point[0]},{point[1]}\n) 上面Python脚本做的事情是读取每个要素的属性取第二个字段作为河流名称然后遍历几何对象的坐标点把每个点输出成一行文本。输出格式是“河名,经度,纬度”适合直接导入Excel或外部系统。大型shp文件每次遍历完点序列后要清空列表否则内存占用会越来越大跑一半卡死是常有的翻车现场。这里出现坐标值对应的都是shp原始坐标系如果原始数据是CGCS2000平面坐标导出的txt里就是带带号的坐标值。想输出经纬度脚本里得先把几何做投影转换用pyproj库定义好CRS转换后逐个点处理。5. 避坑与常见问题省界、投影、字段编码与数据修复5.1 省界线文件s_1和s_2的分工做云南水利项目经常收到“省界线文件省1和省2”两个shp很多人搞不清有什么区别。省1通常是省级界线包含国界、省界、地州界精度和详细度较高省2是简化版通常用于小比例尺制图或者保密处理过的公开数据。选哪个用取决于你的出图比例尺。做1:100万的全省水资源分布图用省2就够了图面简洁不会有大量细碎的边界锯齿干扰。做1:5万或更大比例尺的县域确权图必须用省1简化版边界会导致绘图面积和实际面积出现偏差。需要注意省1和省2叠加到同一张图时两者边界可能不完全重合这属于正常现象。处理原则是以省1为准修正省2不要反过来。用ArcGIS的“对齐要素”工具把省2的边界吸附到省1上可以消除两个图层间的微小缝隙。5.2 经纬度与投影坐标混淆把shp数据放到地图上发现位置偏移了几百米甚至几公里最常见的原因是坐标系搞混了。有人把CGCS2000平面坐标当成经纬度直接加载结果图上的河流位置偏移到几十公里外也有人反过来把经纬度当平面坐标用导致整个图层在图上旋转。判断方法很简单打开图层的属性查看范围Extent。如果X范围在70到140之间Y范围在0到60之间说明是经纬度如果X范围在六位数左右比如300000到700000Y范围在2500000到3200000之间说明是高斯投影坐标。有经验的从业者会给自己定一条铁律任何shp数据进入项目之前先看一眼范围值再决定是否需要投影转换。特别是从网上下载的数据平台经常把原始坐标系信息丢掉你就得通过范围值反推坐标系。5.3 属性表中文乱码问题打开shp属性表看到“河流名称”字段全是“鍗楃洏姹熸祦鍩”这样的乱码十有八九是dbf文件编码问题。shp的dbf默认用GBK编码存储中文但有些发布工具用UTF-8导出cpg文件ArcGIS和QGIS读取时如果按错编码解析就会乱码。解决的办法通常是在QGIS里重新设置图层编码。图层属性里找到“数据源编码”改成UTF-8或GBK预览就会恢复。如果改完还是乱码用Notepad打开配套的.cpg文件看看里面写的什么编码名称改成和目标编码一致再保存。# 强制用GBK编码读取dbf内容输出正确中文 python3 -c import dbfread db dbfread.DBF(yunnan_rivers_2024.dbf, encodingGBK) for record in db[:3]: print(record) bdfread库能绕过GIS软件直接读取dbf文件指定GBK编码后打印前三条记录。如果输出中文正常说明是GIS软件编码识别环节的问题按上面说的改图层编码即可。如果输出还是乱码那就是dbf文件本身编码已经错了只能重新下载数据或者从源工程里重新导出。5.4 用shapechk修复损坏的shp文件shp文件在传输过程中因为断点续传失败、网盘抽风或者U盘拔得太快偶尔会出现文件尾不完整的情况。症状是GIS软件加载时提示“无法初始化Shapefile”或者“读取要素时出错”。ESRI官方提供了一个叫ShapeCheck的小工具专门用来扫描和修复shp文件结构问题。这工具不商业发布一般在ArcGIS安装目录的Utilities文件夹里能找到也可以从第三方GIS工具站下载。# 检查shp完整性的基础命令 shapechk yunnan_rivers_2024.shp # 修复后输出到新文件不覆盖原文件 shapechk yunnan_rivers_2024.shp -o yunnan_rivers_fixed.shpshapechk修复的原理是重写shp文件头并重建索引能解决大部分文件截断问题。但注意它只能修复几何结构修复后属性字段里的数据可能会丢一部分。所以修复完一定要做一次完整性抽查对比修复前后的要素数量。修复后要素数量变少的说明有部分几何确实无法恢复这时就得回到源数据重新获取。5.5 渔网分割shp不要硬切做河网密度分析时常需要用渔网工具把水系数据按格网分割统计。有人在ArcGIS里直接用Clip工具裁剪河流裁完发现很多河段断成碎线长度统计全乱了。这是因为Clip硬切出来的线要素在边界处被截断断点处的拓扑关系没有重建。正确的做法是创建渔网后先用“相交”工具让河段与网格产生叠加关系按格网编号分组汇总河段长度再做统计。用相交替代裁剪河段属性会带上对应的格网编号统计时容易得多。# QGIS处理脚本按渔网单元统计河长 # 输入河流shp 渔网shp # 输出每个网格内的河段总长度一个技巧如果只想显示格网内有没有河流不需要精确长度可以只用“空间连接”工具关联类型选择“相交”统计类型选择“计数”就能快速输出每个格网内的河段数量。这个方法计算量小很多跑得也快。6. 进阶验证拓扑检查与河网密度分析的一点技巧数据拿到手先不要急着画图花十分钟做一遍拓扑检查。用ArcGIS的Topology工具添加“不能重叠”和“不能悬空”两条规则。河流水系最怕的是断头路和重复段这两条规则能自动揪出来。悬空点多的图层要么是源头和河口处理不规范要么是数据生产时没做节点捕捉分析前必须修干净。修拓扑的方式有两种。一是人工沿悬空点逐个排查适合小范围重点河段二是用Planarize工具自动打断相交线再按属性重构连通关系适合大范围全覆盖。Planarize会把所有交叉点打断成独立节点但打断后河段属性会分裂成多段需要按原字段合并让属性恢复到打断前的状态。河网密度分析有一个惯用技巧把研究区切成1公里乘1公里的渔网然后用空间连接统计每个网格内的河段总长度再把总长度除以网格面积得到的就是该区域的河网密度数值。这个值做出来以后用分级色彩渲染山区和坝区的差异一目了然。以前在做云南某县的生态补偿评估时我用这个方法发现了三个被忽略的中小河流密集区后来实地核查发现其中一条确实有隐蔽排污口。做完密度分析后一定要做一次数据验证。方法很简单随机抽10条河流用高分辨率影像人工目视对比走向。影像上清晰可见的河段在shp里没有说明数据漏采shp里有但影像上看不到的线可能是季节河或者渠道被误判成天然河流。这种抽样合格率低于90%的数据不建议直接用于专业分析。从那以后我每次拿到新的水系shp都会强制走一遍这套流程字段预检、坐标系确认、拓扑检查、抽样验证。全部过了才敢在项目里用。云南的河流水系数据版本多、来源杂花十分钟做前期验证能省下后面几天的返工时间。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进