ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

2005年全国矢量数据图:坐标系校正、编码转换与GIS发布指南

2005年全国矢量数据图:坐标系校正、编码转换与GIS发布指南 简介一套覆盖全国范围的矢量地理数据合集整合道路、河流、铁路等基础要素特别收录2005年全国铁路网与各级路网数据可支撑城市规划、交通分析、环境研究等GIS应用也适合用于历史路网回溯与现状对比。压缩包共161个文件、约11.25MB主体为22套shp矢量图层及配套shx/dbf/prj文件分别保存几何形状、属性字段与投影定义另有sbn/sbx空间索引、mxd地图文档和adf栅格数据能够在ArcGIS中直接加载并组织工程。目前已有2567人学习。道路数据涵盖高速公路、国道、省道、县道等层级铁路数据包含高速与普速线路并附有等级、方向、长度等属性信息借助内置Lambert投影参数可避免大范围制图时的形变误差便于开展连通性、缓冲区等空间分析或叠加人口、地形数据辅助决策。对于需要2005年路网底图进行历史比较或区域研究的用户这是一份即取即用的基础数据。1. 2005年的全国矢量数据图到底能干什么用做GIS分析的人几乎都经历过一个场景项目要路网、河流、铁路做底图手头只有一套压缩包叫“全国矢量数据图大全道路河流铁路等详细”解压开是几十个文件夹里面是带字段属性的全国路网数据、铁路数据和主要河流图层。这套以2005年为基准年的矢量成果特点是覆盖全、要素分层细适合做宏观规划底图、历史对比分析和模型输入的基底数据。它不是你从某个官方入口点几下就有的现成东西而是要自己整理、校准坐标系、处理编码之后才能真正喂给ArcGIS或QGIS的原料。这篇笔记就把我几次用这套数据的完整路径写出来从格式、坐标系到发布成GeoServer服务和切给ArcSWAT做小流域分析前置输入每一步都会说参数和坑。2. 打开之前先过三关格式、坐标系与属性编码2.1 先分析压缩包内组织结构哪些图层是你真正要的拿到手先别急着拖进ArcGIS。这套数据的常见分层是按照要素类别走的road道路、railway铁路、river河流、hydro水系附属、boundary境界、residential居民地、terrain地形地貌等每一类下面按省级或流域存放。我的建议是第一遍用目录清单快速确认每个图层的空间范围和要素类型不需要一次性全部加载。这一步有个容易被忽略的细节压缩包里的shp文件物理上由至少三个文件组成——.shp存几何、.dbf存属性、.shx存索引有些还带.prj投影文件。如果你要拷贝给别人或移动位置三个文件必须一起动。单独拷一个.shp过去对方打开就只有图形没有属性表。2.2 先看坐标系参数WGS84、西安80还是CGCS20002005年基准的数据坐标系标注往往不是统一的。常见的有WGS84经纬度、西安80高斯投影、北京54高斯投影少数已经转了CGCS2000。如果数据带有.prj文件用QGIS或ArcGIS直接读属性就能看到坐标系定义但更常见的是一套数据里不同图层混用了不同的坐标系。我一般会先写一小段Python用geopandas快速扫一遍全部的prj信息避免后续叠加时整体跑偏。import geopandas as gpd from pathlib import Path # 遍历某个文件夹下所有shapefile打印文件名和坐标系 shp_files list(Path(./vector_data).rglob(*.shp)) for f in shp_files: try: gdf gpd.read_file(f, encodinggbk, rows1) # 只读1行快速检查 print(f.stem, -, gdf.crs) except Exception as e: print(f.stem, - 读取失败:, e)这段代码的逻辑是只读每个shapefile的第一行避免把成千上万条要素全部加载进内存。encodinggbk是兼容早期国内矢量数据属性编码的常见做法后面字段乱码问题会专门说。输出结果里你能一眼看到哪些图层是WGS84EPSG:4326哪些是西安80常见是EPSG:2333这一类投影坐标或自定义Gauss Kruger哪些没有坐标系定义。如果某个图层没有.prj文件gis软件会按“未知坐标系”处理叠到其他图上自然就是偏移的。遇到这种情况不要靠猜要靠图上已知参考点判断——比如找一条河流与道路的交叉点对比它和现状底图差多远。经验做法是优先把它按同目录里大多数图层的坐标系处理再用一个已校准的参考图层验证。2.3 DBF属性乱码GBK和UTF-8的识别顺序问题2005年前后建库的矢量数据属性表.dbf里的字段值基本是用GBK或GB2312编码写的。现代QGIS默认按UTF-8读结果就是“名称”字段显示成乱码。这个问题在ArcGIS里反而少见因为它会自动用系统区域语言解码但到了QGIS和GeoServer里必现。解决办法有两个层面。一是在QGIS加载时数据源管理器里手动把编码从UTF-8改成GBK或GB18030二是用GDAL做一次无损转码直接把dbf里的编码改成UTF-8一劳永逸。我习惯用第二条因为后续发布GeoServer服务时属性乱码一样会从WMS/WFS接口里冒出来。# 把原始GBK编码的shapefile转换为UTF-8编码并写成新文件 ogr2ogr -f ESRI Shapefile \ -lco ENCODINGUTF-8 \ -nln road_utf8 \ road_utf8.shp road.shp这条命令里核心参数是-lco ENCODINGUTF-8它控制输出shapefile的.dbf文件用什么编码写字段值。注意ogr2ogr不会自动识别输入文件是GBK还是别的它默认按系统locale去解。如果系统locale是UTF-8读GBK的dbf还是会乱所以建议在转换前先确保ogr2ogr能以GBK读取输入。做法是设置环境变量ogr2ogr的读取编码-nlt控制几何类型不要动-overwrite控制输出覆盖。更稳的方式是给GDAL加配置项export GDAL_FILENAME_IS_UTF8YES export SHAPE_ENCODINGGBK ogr2ogr -f ESRI Shapefile -lco ENCODINGUTF-8 road_utf8.shp road.shpSHAPE_ENCODINGGBK让GDAL先把输入dbf按GBK解码再把字段值编码成UTF-8写入新文件。转换完成后建议再用geopandas读一次确认字段可读。3. 把道路、铁路、河流三类图层整理成能出图的底图3.1 路网数据按等级字段筛出你要的层级全国路网矢量数据里道路字段通常带“等级”“类型”“名称”这些属性。“等级”常见值包含高速、国道、省道、县道等但不同批次数据里的取值并不统一有的用代码1/2/3有的用中文“G”“S”“X”。先把字段枚举值打出来确认数据自己的分类口径。import geopandas as gpd gdf gpd.read_file(road.shp, encodinggbk) # 查看字段类型和等级枚举 print(gdf.dtypes) if 等级 in gdf.columns: print(gdf[等级].value_counts(dropnaFalse)) elif type in gdf.columns: print(gdf[type].value_counts(dropnaFalse))这一步的价值在于你会发现同一套数据里“等级”可能有缺失值可能把高速公路写成“高速道路”四个字也可能和“编号”字段混在一起。先把取值搞清楚再决定是直接按字段过滤还是新建一个标准字段做重分类。我处理时一般新建一列class_new把高速、国道、省道、县道、乡道映射成1到5便于符号化时按宽度和颜色控制。如果要做100米网格或更细粒度的分析建议直接把乡道以下的路网剔掉因为1:25万综合精度的数据低等级道路的位置偏差可能达到几百米做精细分析会误导结论。3.2 铁路数据跨图层落在不同图幅里的“同一条线”铁路数据比道路更容易出问题原因是铁路线往往是长跨度的而矢量切图经常按标准图幅或行政区划拆开。同一条京沪铁路可能在某两个省的交界处断成两段接点位置有几十米的重叠或空隙。直接用修复几何的工具不一定能处理因为断裂处不是零长度线段而是两条线交叉区域。我的惯用做法是先把所有铁路要素合并成一个要素集再用路网拓扑工具找断点人工结合线路名称字段做连接。字段里的“线名称”值如“京沪线”“陇海线”是判断两条线段是不是同一条铁路的最可靠依据。import geopandas as gpd rail gpd.read_file(railway.shp, encodinggbk) # 按线路名称分组统计每条线路的要素数量和总长度 name_col 线名 if 线名 in rail.columns else name stats rail.groupby(name_col).agg( 要素数(geometry, count), 总长度(geometry, lambda g: g.length.sum()) ).sort_values(总长度, ascendingFalse) print(stats.head(20))如果一条线路被拆成几百个要素说明是按图幅切的你需要做的是按名称字段合并。合并前先对几何做一次Simplify消除因为人工数字化导致的重复节点合用前如果发现两条线的首尾点离得很近但不重合用snap工具把端点吸附到一起。3.3 河流数据双层河网与单线河的合理取舍河流矢量在这套数据里可能有多个图层一个是大江大河的主干图层一个是支流和小河流的次要图层还有可能是“双线河”表达——即河流用面状要素表示两岸各一条边界线。写ArcSWAT或做水文分析时必须先明确你要的是“单线河”还是“双线河”。做流域汇水分析时双线河会给河网提取带来干扰一般需要把面状河中心线提取出来或直接只用主干河网图层。中心线提取在QGIS里可以用Polygon to lines再把线简化但更省事的做法是看数据里有没有现成的“河网主线”字段。有的数据在面状河流的属性表里存了“流向”“河宽等级”等字段可以根据河宽等级决定取舍避免把所有细支流全兜进来。import geopandas as gpd river gpd.read_file(river.shp, encodinggbk) # 过滤出主要河流优先保留河宽等级为1-2或类型为干流的要素 if 河宽等级 in river.columns: main_rivers river[river[河宽等级].isin([1, 2])] else: main_rivers river[river[type].str.contains(干流|main, naFalse)] # 导出为单线河网用于后续分析 main_rivers.to_file(river_main.shp, encodingutf-8)这段代码的逻辑是根据字段值先做一次粗筛把面状河和支流去掉。注意字段名在不同数据里可能叫“等级”“类别”“river_level”不要写死先打印一下列名再改。导出的river_main.shp存成UTF-8后面给GeoServer用或直接给ArcSWAT当burn-in数据都方便。4. 使用这套数据最容易翻车的四件事坐标偏移、乱码与精度玄学4.1 叠加到最新遥感影像后整体偏移300米坐标系没有统一现象路网数据和2020年后获取的高分影像叠加道路全部偏到农田里偏移量在200米到500米之间。原因这套2005年数据的坐标基准是西安80而现代卫星影像是WGS84/CGCS2000两者在国境内部分区域存在系统性的椭球差异不做转换直接叠必定整体偏移。解决在geopandas里统一做一次重投影把西安80图层的坐标转换到CGCS2000或WGS84。注意如果你的源数据是高斯投影单位是米要先转成经纬度再从经纬度转目标坐标系而不是直接调用to_crs从投影转投影。import geopandas as gpd gdf gpd.read_file(road.shp, encodinggbk) # 先明确当前坐标系假设是西安80高斯投影 gdf gdf.set_crs(EPSG:2333, allow_overrideTrue) # 以实际prj为准 # 再重投影到WGS84 gdf_wgs gdf.to_crs(EPSG:4326) gdf_wgs.to_file(road_wgs84.shp, encodingutf-8)set_crs只是“声明”当前坐标系不改几何数值to_crs才真正做坐标转换。很多翻车就是因为跳过了set_crs这一步直接对一个没有坐标系定义的图层做to_crs结果软件按默认坐标系处理转换完偏移依旧。重投影后用一张已知坐标的道路互通立交叠底验证比看图例可靠得多。4.2 QGIS和GeoServer里属性全是“锟斤拷”编码识别顺序问题现象在ArcGIS里打开好好的中文属性换到GeoServer发布WFS之后前端查到的属性变成乱码或者QGIS里加载直接显示“锟斤拷”“烫烫烫”。原因GeoServer读取shapefile的dbf时默认用ISO-8859-1解码而源数据是GBK。ArcGIS能自动适应是因为Windows系统区域语言做了兜底Linux服务器没有这层。解决发布前先用ogr2ogr -lco ENCODINGUTF-8把编码转掉不要指望GeoServer自动识别。属性值多、字段多的情况下也可以转成GeoPackage后再发布GeoPackage的编码处理比shapefile省心很多这是我现在的首选。提示转编码前先确认数据普适。如果图层在ArcGIS里打开的字段值是好的就不要在GIS软件里“另存为UTF-8”务必用上面那套ogr2ogr做法因为它会保留几何精度不会顺手把字段精度也改了。4.3 铁路和路网交叉点对不上2005基准年与现状数据的拼接错位现象在同一张图里铁路线和公路线在平面交叉位置一个显示上跨、一个显示下穿点完全对不上甚至出现公路穿过铁轨面几十米。原因这套数据的多个要素层不是一次统一测绘的道路和铁路可能来自不同专业资料数字化各自存在独立的综合位移。更常见的是2005年之后新建的铁路复线和改造线路没有更新到路网层的底图里。解决不要试图用“吸附”把所有交叉点强行拉齐那是很危险的操作。正确做法是把2005年数据当作历史底图来用在图上明确标注“铁路线为现状参考路网为2005年道路网”做历史演变对比时不改几何只做可视化叠加。如果非要做现状分析用最新OSM路网或官方地理国情数据替换不要在这个问题上赌精度。4.4 精度与比例尺这套数据做不了宗地级和50米网格范围的分析现象把路网数据放大到1:5000比例尺道路线变成锯齿状河流边界和遥感影像严重不符。原因2005年这套全国矢量数据大多是1:25万或1:100万综合成果不是测量级数据。它的定位是宏观尺度的空间分析和制图不是给不动产测绘用的。解决使用前先明确“我能用它做到什么粒度”。我的底线是做县级以上的路网密度分析、跨省交通走廊识别、流域尺度的河网结构分析这套数据够用做具体地块的出门道路分析必须用现场踏勘和高精度影像修正。写技术方案时把数据的比例尺来源写清楚评审就不会拿它卡你的结论。5. 从文件到服务GeoServer发布矢量数据与ArcSWAT的数据准备5.1 GeoServer发布前要做的三件事预定义坐标系、分层、样式很多人把GeoServer发布当成“上传一个shp然后选发布”的操作结果前端地图上要素缩在某个角落里或属性乱码或图层样式丑到没法看。这三个问题基本都能在发布前用准备工作规避。第一件事坐标系统一成EPSG:4326或EPSG:3857。切片服务WMTS和前端WebGIS常用Web Mercator坐标范围是经纬度但以米为单位显示。发布时坐标系设置要明确建议先统一到4326再切成3857避免在服务端做不知道基准的转换。第二件事属性字段精简。用GeoServer发布的图层如果带一堆冗余字段每次GetFeature请求都会多传数据客户端加载也慢。发布前用ogr2ogr -select只保留自己需要的字段。第三件事样式使用SLD。根据“等级”字段做宽度分级比给整条路一个统一颜色实用得多。下面这个SLD是针对路网的分级样式核心逻辑高速给6像素宽度、国道4像素、省道3像素其他2像素。Rule Namehighway/Name Filter PropertyIsEqualTo PropertyNameclass_new/PropertyName Literal1/Literal /PropertyIsEqualTo /Filter LineSymbolizer Stroke CssParameter namestroke#d62728/CssParameter CssParameter namestroke-width6/CssParameter /Stroke /LineSymbolizer /RuleGeoServer加载该SLD后会自动按规则进行符号化GetMap请求时服务端渲染不用前端再做分类逻辑。发布服务的完整流程是先创建workspace再创建shapefile数据源然后发布图层最后绑定样式。用REST API可以一条命令完成# 创建workspace curl -v -u admin:geoserver -XPOST \ -H Content-type: text/xml -d \ workspacenamenational/name/workspace \ http://localhost:8080/geoserver/rest/workspaces然后创建数据存储并发布图层。注意这一步如果报“Could not list layers”八成是数据源路径里的中文目录或文件名未经URL编码curl命令里要先把路径转成URL编码再提交。5.2 ArcSWAT做小流域分析要用什么矢量数据ArcSWAT建小流域时很多人以为只有DEM就能跑结果提取出来的河网弯弯曲曲子流域边界和实际水系对不上。问题在于SWAT的河网提取需要一个“burn-in”过程也就是用已有的河流矢量数据强制修正流向。2005年这套数据里的河流图层正好派上用场。具体准备步骤是把河流主线转成和DEM相同投影再用ArcGIS的Feature to Raster把河网栅格化成和DEM像元对齐的网格把这个网格叠加到DEM上用“burn in”操作把DEM里对应河流位置的像元抬高河网提取就会被强制引导到实际河道位置。河流矢量的要求是单线、无重复线段、水系拓扑连续。另外ArcSWAT的子流域最小汇水阈值设置决定了划分出来的子流域数量。我做小流域分析时一般先用这套2005年河流数据做一次初步的阈值试算得到一个合理的阈值区间再正式跑模型。因为这套数据能反映真实河道密度拿来标定阈值参数比凭空猜靠谱得多。5.3 2005年数据与现状数据混用的取舍原则很多时候项目里不是只用2005年这一套数据而是要和最新路网、现状水系一起提资。我的一般原则是历史分析场景用2005版本做基准现状分析场景用最新数据做基准两套不混在同一图层里。具体说做交通可达性随时间变化分析2005年路网作为基期最新路网作为末期。做流域水环境模拟水系的2005年数据可以作为河网结构参考但河道断面及水位数据必须用现状实测。做土地利用变化分析2005年路网、铁路数据是解释土地扩张的驱动因子比现状路网更符合当时的发展阶段。这样混用不会让你在评审时被质疑反而能体现你对数据时间口径的把握。把每套数据入库时加一个year字段标记数据基准年份后面出图、做统计汇总、写说明都方便。6. 进阶一步用路网数据制作道路面的方法与验证习惯把线状路网变成道路面是很多专题图需要的进阶操作。常见做法有两种一是用GIS缓冲区按道路等级给出不同宽度高速30米、国道20米、省道15米、县道10米缓冲后做union合并二是用高精度路网数据做真实道路面如果手头有带车道宽度属性的路网数据可以按车道数×3.5米推算。这里讨论的是前者因为2005年这套数据没有车道宽度属性用分级宽度缓冲最可行。操作上推荐用PostGIS一条SQL就能完成宽度分级缓冲和融合SELECT ST_Union(ST_Buffer(geom, width)) AS geom FROM ( SELECT geom, CASE WHEN class_new 1 THEN 30 WHEN class_new 2 THEN 20 WHEN class_new 3 THEN 15 ELSE 10 END AS width FROM road_utf8 ) t;这里ST_Buffer按米计算缓冲宽度前提是geometry已经是投影坐标系。如果数据还是经纬度先用ST_Transform转成投影坐标再缓冲区。融合后的结果是一个连续的、分级宽度的道路面叠加到遥感影像上比线状路网真实得多做土地利用冲突分析、道路占地估算都能直接用。验证道路面质量的一个实用技巧把生成的面积数据叠到高分影像上沿路抽查10个点对比路面边缘和影像上的道路边缘间距。间距小于10米说明宽度赋值合理间距超过30米就要检查对应路段的等级字段是否准确。我自己的一个检查习惯是针对等级高的路段——高速、国道先叠影像验证这类路的宽度取值对总面积影响最大。毕竟宽度给错了整个面积统计就会“差之毫厘失之千里”。最后说一句这套2005年的矢量数据不是万能底图但它作为历史基准、宏观分析和模型输入的基底价值远超你临时从网上下载的零散数据。先把坐标系、编码、分级这三个基本功做扎实后面每一次叠加、发布、分析都会省很多事。希望帮到你。本文还有配套的精品资源点击获取
返回列表