
简介全国地质图矢量图层数据集以Shapefile格式封装专为GIS数据处理、地质科研与Python空间分析场景设计可直接在ArcGIS、QGIS或GeoPandas中加载使用。数据采用WGS84地理坐标系核心字段包含地层多边形的面积、周长、岩性类型等几何与属性信息同时保留原始图面标注的地质年代GLG及编者推算的标准化“代”级年代GEN_GLG方便按不同时间尺度筛选和分析。压缩包内共有5个文件分别为矢量主文件shp、投影文件prj、属性表dbf、元数据xml及空间索引shx结构紧凑、体量轻量整体压缩包仅9.04MB。目前已有2620人学习或下载。用户拿到后无需复杂预处理即可直接导入主流GIS平台快速开展地层分布统计、岩性专题制图、地质单元面积计算或结合Python批量编写空间分析脚本有效减少数据清洗与投影转换工作量既适合需要标准化地质底图的入门与进阶用户也可作为高校地学课程的练习数据。1. 全国地质图矢量图层数据集把纸面地质图变成能查询、能裁剪的shp底图全国地质图矢量图层数据集是把全国分幅地质图的地质要素拆成多个shp矢量图层地质体是面断层和界线是线产状、样品记录是点。它的核心价值在于把“图”变成可查询的数据——找矿靶区、工程选址、地质灾害普查都要先拿它做底图但在实际项目里大多数人拿到的是从旧图幅矢量化来的shp属性表字段千奇百怪坐标系新旧混杂。这种数据集本来就不该被当成一张图片来用而是应该清洗、拼接、裁剪、符号化之后再交给后续分析。这篇记录就是沿着这条路径讲拿到shp以后先查什么dwg转shp怎么做哪些坑让新手翻车最后如何把样式沉淀成模板。适合正在做地质底图管理的GIS工程师也适合手里只有CAD图、急着转成shp的工程师。2. 拿到shp后的第一小时文件结构、属性字典和坐标系体检2.1 一个完整地质shp包至少是几件套缺.cpg会出乱码很多人把shp当成单文件拖进GIS结果不是缺属性表就是报坐标系错误。严格说一个能正常工作的地质shp包至少包含 .shp、.shx、.dbf 三件套如果还要让别人读得懂必须带上 .prj 和 .cpg。下面这张表是我的一个固定检查口径每拿到一批数据先对着它过一遍。扩展名作用缺失时最典型的后果.shp存储要素几何形状图层直接打不开.shxshp的几何索引打开慢部分软件报“shapefile 损坏”.dbf属性表图形还在但没有任何字段.prj坐标系描述图层以默认WGS84打开缩放后位置错乱.cpg属性编码声明中文字段变成乱码GBK内容被按Latin-1解码这里最容易被忽略的是 .cpg。ArcGIS导出shp时如果原始dbf字段里有中文默认会写一个.cpg文件记录编码但很多从CAD转过来的旧地质图幅只有.shp和.dbf连.prj都没有。没有.cpg时QGIS会先按系统默认编码去猜Windows上是ANSILinux上是UTF-8猜错了就是满屏“锘垮”。后面第5章会专门讲编码修复但建议从接收数据那一刻起就养成交付.cpg的习惯能少一半乱码问题。2.2 属性表里的地层代码和岩性代码是批处理的字典很多从业者拿到shp只看图形属性表几乎不看直到需要按时代分层出图才发现字段完全对不上。全国地质图矢量图层数据集的属性表通常来自不同时期数字化常见字段有 GeoID、地层层位、岩石类型、时代符号、地质单位名称等。真正用于驱动图例和查询的是“地层代码”和“岩性代码”这两类键字段。在一张1:20万地质图里地质体多边形属性往往长这样地层代码“O2-3”表示奥陶系中上统岩性代码“Ls”表示灰岩。字段值本身不复杂复杂的是不同图幅的命名规则不一致有的用“0_2_3”有的用“O23”。我一般会把所有图幅的属性先导成CSV做一个“代码字典表”把同一套地质时代的写法统一成一个标准值再回填到shp里。这个字典不丢进GIS而是作为独立csv保留后续做qml符号模板、做web地图服务都要引用它。还要提醒一点DBF是dBase III格式字段名最长10个字符中文会按字节被截断。所以属性表里的列名尽量避免用“地质单位名称”这种超长标题改成DGMC之类的缩写完整解释写到元数据文档里。很多shp转geojson、shp转wkt的工具对字段名截断问题不做任何提示等到了数据交换环节才暴雷。2.3 坐标系体检先看prj再和底图叠加坐标系错误是地质shp数据最常见的“隐形杀手”。打开一个shp图形能显示地图也没有跳海但一旦叠加上道路、水系、行政边界位置偏出去几百米甚至几公里——这种情况多半是.prj里的投影坐标系和实际数据不匹配。我拿到图层后的第一动作是右键查看图层属性里的“源数据”读一遍坐标系描述。全国地质图shp常见的坐标系有三类Beijing 1954、Xian 1980、CGCS2000前两者常以高斯-克吕格投影分带存储。一个典型的旧式.prj文本长这样GEOGCS[GCS_Beijing_1954, DATUM[D_Beijing_1954, SPHEROID[Krassowsky_1940,6378245.0,298.3]], PRIMEM[Greenwich,0.0], UNIT[Degree,0.0174532925199433]]这说明它用的是北京54地理坐标系单位是度。如果同一个图层数据本身是高斯投影的米制坐标却写了这样一行地理坐标系描述那叠加到其他图层时所有位置都会错到不可思议。更隐蔽的情况是prj缺失。有些老图幅只给了.data文件软件会默认按WGS84读但你仍需注意。我的做法是先用一个已知路网或水文shp做锚点加载后看两个图层是否重合再看状态栏坐标读数是经维度还是米制如果和坐标系描述不符就主动给图层指定正确坐标系再做真正的“投影转换”而不是直接“定义投影”。体检这一步花二十分钟后面裁图、接边、统计面积时能省下整周时间。3. 清洗全国地质图shp的实操QGIS批量修乱码和按边界裁剪3.1 为什么把清洗放在QGIS而不是ArcGIS批量处理逻辑更顺手ArcGIS里处理一个shp的乱码或坐标系很多人会打开属性表手动改或者用字段计算器一条条转换遇到几百个图幅就非常痛苦。QGIS本身免费、跨平台而且自带Processing框架能把同一套操作套到一批图层上这是我最常用它的原因。另外全国地质图矢量图层数据集往往存在多种交付形态有的是分幅shp有的是GeoPackage里的多个图层还有的是CAD残片转出来的散装dbf。QGIS可以直接拖入不同格式再借助原生算法统一输出为标准shp。需要说明的是这里说的清洗不是修改几何拓扑而是先把编码、坐标系、字段名这些“元数据层”统一起来。几何问题放到第4章处理。3.2 用ogr2ogr把DBF编码从GBK归一到UTF-8多数国产地质图shp的dbf是从ArcGIS旧版本导出的属性编码是GBK或CP936。QGIS虽然能通过重新选择编码方式读取但在做数据交付时把编码一次性落成UTF-8更省事。我最常用的不是QGIS菜单而是GDAL的ogr2ogr命令行。# 1. 先看图层的读取编码 ogrinfo -ro -so strata.shp strata # 2. 复制一份并把编码统一成UTF-8保留原文件做后悔药 ogr2ogr -f ESRI Shapefile strata_utf8.shp strata.shp -lco ENCODINGUTF-8 # 3. 检查复制出来的.cpg是不是UTF-8 cat strata_utf8.cpg这段命令的逻辑是ogrinfo -ro -so读的是只读的图层基本信息能显示图层名称和字段结构不会对原文件做任何改动ogr2ogr把源shp复制一份到新shp同时通过-lco ENCODINGUTF-8写入新的.cpg元数据。参数说明如下-f ESRI Shapefile目标格式保持shp格式不变-lco ENCODINGUTF-8layer creation option控制新文件的DBF编码标记strata_utf8.shp这个新文件名最好保留原图幅号不要光加一个编码标注就丢了图名。如果原始dbf不是GBK而是其他编码先手动在QGIS里用“设置图层编码”试几种常见编码确认能正确显示后再改用-lco ENCODING对应的编码。另一个值得留意的是这步不会重算几何坐标也不会改字段结构它只是把“读法”重新声明了一遍所以风险很低。如果图层已经在QGIS里打开了也可以直接在Python控制台里给数据源设置读取编码。不过我个人认为ogr2ogr这种方式更适合批量处理一百个图幅的场景写一个循环把所有待转shp按同一个参数跑完中间不会因为手动点错而漏图层。3.3 按行政边界裁剪地质图shp用clip还是extract by location拿到全国尺度的shp后最常见的需求是切到工作区范围。在QGIS的Processing里有两个容易混淆的工具Clip和Extract by Location。Clip是几何裁剪保留位于边界内部的那部分要素几何边界会被精确切到边界线上Extract by Location是空间选取只要多边形与边界相交、落在边界内、或与边界相交就整块保留。做项目底图时我通常先用Extract by Location筛出涉及图幅再对结果做一次Clip这样既减少处理数据量又能保证出图边界干净。# QGIS Processing 内直接跑裁剪 from qgis import processing params { INPUT: D:/national/strata_utf8.shp, OVERLAY: D:/admin/study_area.shp, OUTPUT: D:/work/strata_clip.shp } result processing.run(qgis:clip, params)这段代码的作用是把全国地质图shp按study_area.shp这个研究区边界做几何裁剪结果写到strata_clip.shp。参数说明INPUT是被裁剪的矢量图层OVERLAY是裁剪范围图层必须和输入图层在同一坐标系下OUTPUT指定输出路径如果没有给路径会自动生成临时图层qgis:clip是QGIS原生算法比GDAL的ogr2ogr -clipsrc更直观而且能保留所有字段。裁剪后建议立刻检查两个地方一是属性表行数是否明显小于输入二是图层范围是否和边界一致。如果裁剪后出现大片空白或者要素断裂先看两个输入图层坐标系是否一致再看边界线是面还是线如果用线图层做OVERLAY裁剪结果会空。这里还要说一个很常见的误用有人为了省事直接用老的ArcGIS Toolbox里的Clip电脑上没授权或版本过旧时经常报“999999”错误。换成QGIS的Processing之后batch模式可以直接拖入几十个图幅参数列表完全一致效率和稳定性都会好很多。4. 从dwg到shp的矢量化转换路径、投影校准和线闭合4.1 dwg转shp后为什么会出现线缺和面碎地质制图的历史数据有大量CDA工程图面里地质体是用闭合多段线画的断层是独立线产状是带旋转角度的块。这类dwg要转成shp最直接的坑是“面碎”CAD里看起来封得严严实实的地质体边界转成shp后变成一堆断裂的短线面要素根本无法构成。原因有几个。一是CAD没有拓扑概念两条相邻多段线的端点即使视觉上重合也没有真正“捕捉”二是CAD里的地质体填充图案例如斜线和岩性花纹会被当作图形实体一并转出来干扰后续识别三是部分dwg被保存成了高版本格式QGIS和GDAL直接读不了需要先在CAD里另存为低版本DXF。所以真正的矢量化流程从来不是“一个按钮dwg转shp”而是“分层清理、坐标校准、线闭合、转面、属性回填”五步。每一步都单独验证不要试图一把梭。4.2 先用DXF中转分层导出并定好坐标系最常见的做法是先把dwg在AutoCAD里另存为DXF格式。DXF是公开的文本交换格式GDAL和QGIS对它的支持比dwg本身稳定得多另存时推荐用R12或R2000版本兼容性最好。另存之后不要直接把整个DXF拖进qgis转shp而是先按“图层”字段过滤。# 把DXF里的“地质体”图层单独转成GeoJSON ogr2ogr -f GeoJSON stratum_geo.geojson stratum.dxf -where Layer地质体 # 再把GeoJSON转成shp并统一坐标系为CGCS2000 3度带投影 ogr2ogr -f ESRI Shapefile stratum_geo.shp stratum_geo.geojson \ -a_srs EPSG:4547 -lco ENCODINGUTF-8这两条命令的逻辑是第一步先用-where Layer地质体过滤出CAD里真正代表地质边界的图层避免把填充图案和注记一起转出来第二步把GeoJSON落到shp同时用-a_srs EPSG:4547声明坐标系。参数说明Layer‘地质体’要和CAD里的图层名严格一致中文图层名在命令行里注意编码建议先在QGIS里确认DXF读出来的图层名-a_srs是“assume SRS”只声明坐标系不改变几何坐标值适合那些dwg已是米制坐标但没有prj的场合EPSG:4547是CGCS2000 / 3-degree Gauss-Kruger zone 37如果你所在区域不在相应分带换成项目对应的带号。如果dwg本身就没有校准坐标只有相对坐标那么转shp之后再定义坐标系是没用的必须先通过控制点和位移、缩放把CAD图形套合到真实坐标上。这一步我一般拉到QGIS里用“Georeferencer”对几个已知坐标的钻孔点或地形特征点做仿射变换再导出shp。4.3 拓扑闭合后再转面polygonize与属性回填从DXF转出的线即使视觉上闭合实际端点也可能有微小间隙。如果直接跑“线转面”会出现大量碎面而且碎面之间互相重叠。我的处理顺序是先用Processing里的Fix geometries处理线自相交再用v.clean做端点捕捉最后才做 polygonize。# 把清理后的线图层转成面 from qgis import processing params { INPUT: D:/clean/stratum_lines.shp, BAND: 1, OUTPUT: D:/clean/stratum_polygons.shp } result processing.run(gdal:polygonize, params)这段代码用GDAL的Polygonize算法把闭合线包围的区域生成面要素。逻辑上它是根据线的网络闭合区域生成新多边形而不是像“line to polygon”那样依赖图层内置的几何关系更适合处理从CAD出来的散线。参数说明INPUT必须是一个线图层且线要尽量在端点处相交BAND1是栅格波段参数Polygonize的常见默认值矢量输入时保留即可OUTPUT新生成的面shp。这里最容易踩的坑是polygonize出来的面属性表是空的因为它只认几何不认原线属性。所以转完之后还需要用“Join attributes by location”把源线图层的图层名或地质代码关联回面图层。关联办法是以新面为target以原线为join layer选择“intersect”或“contained within”然后把地层代码、图层名等字段取过来。我习惯在输出字段里只保留一个EUR字段其他代码在后续清洗阶段再补。如果你运气好原始dwg里的面是真正的闭合多段线那么在CAD里可以直接用“转换为面”命令。但经验是兜一圈polygonize反而更可靠因为很多老dwg里的系统变量设置有偏差直接转换会漏面。5. 全国地质图shp避坑坐标系、编码、拓扑三类高发问题5.1 图层加载后“跳海”prj缺失或坐标系标签互相贴错现象shp加载后视图自动飞到赤道附近的海面或者要素跑到完全不可能的位置。原因最常见的两种情况一是shp没有prj文件QGIS按WGS84经纬度读取而图层数据实际是投影米制坐标坐标值被当成经纬度后自然跑到数百万度二是prj写的是Beijing 1954地理坐标但数据实际是Xian 1980投影坐标叠加到其他图层后偏移明显。解决先判断数据是经纬度还是米制。打开图层属性看坐标范围的数字如果是形如118.2、34.6这种就是经纬度如果是形如500000、3400000这种就是投影坐标。假如是投影坐标且缺失prj用一条命令给它指定正确坐标系ogr2ogr -f ESRI Shapefile strata_fixed.shp strata.shp -a_srs EPSG:4547记得不要用gdal_translate去指定矢量的坐标系那是对栅格的。指定完再用元数据清洗工具确认坐标范围显示正常。5.2 属性表满屏乱码GBK与UTF-8之间缺一道 .cpg现象打开属性表后中文显示成“锘垮鍦板眰”一类不可读字符。原因dbf内部有编码标记ArcGIS老版本常见为CP936当无cpg或cpg内容为1252时读出来全是乱码。再叠加一个条件Linux系统下默认UTF-8Windows下默认ANSI所以同一张shp在不同电脑上打开乱码状态还不一样。解决先在QGIS里不断切换“设置图层编码”直到属性正确显示。确认是GBK后用第3章的ogr2ogr -lco ENCODINGUTF-8统一产出新文件。如果文件中已经有中文只是软件没检测到不要直接在属性表里手动改要改就去改编码标记改一个字段只能骗过自己改编码能把整张表都救回来。5.3 裁剪后边界出现锯齿花不同图幅的容差和结点精度不一致现象用同一研究区边界裁剪多个图幅拼到一起后边界线像锯齿一样互相咬合缝隙宽窄不一。原因每个shp的节点密度、坐标精度、甚至数字化的“逼近容差”不同裁剪到同一范围后边界线无法完全重合。全国地质图这种多图幅拼接数据在接边处尤其常见。解决把拼接工作分成两级。第一级是把所有图幅转到一个共同坐标系并对边界顶点做一次“捕捉到格网”例如在QGIS里用Snap points to layer把顶点吸附到统一格网上第二级是用Processing的Fix geometries检查是否有重复节点或自相交。真正做合并后再用Dissolve按GeoID融合让接边的同一地质体合并成一块连续面而不是保留两条近似平行的边界线。5.4 裁剪结果属性丢失把clip当成了切割对象现象做qgis:clip后输出的面几何正确但属性表里大量字段是空的或者原来唯一标识变成了Null。原因很多裁剪工具默认只保留输入图层的几何和部分字段如果输入图层是polygonize刚生成、还未做属性回填的中间产品裁剪后就只能得到一堆“有面无名”的碎块。另一种情况是在ArcGIS里勾选了“仅保留相交要素”却把输出路径放到了临时位置结果关了工程就找不回来。解决裁剪操作本身不会丢字段是先确认输入shp字段在裁剪前就完整。建议在裁剪前跑一次“汇总统计”统计GeoID的计数确认没有空值再裁。裁剪后立刻对输出做同样的统计对比。如果真丢了用Join attributes by location以输出面为target、原图为join layer把属性补回来。5.5 拼接后同一条地质界线错位跨图幅并库要先统一控制点现象两幅相邻1:20万地质图分别转成shp后各自图层内正常但把它们放到同一工程里两幅图的同一套地层界线错位了几十米甚至同一片地质体被切成两部分。原因纸质地质图扫描矢量化时每幅图是单独进行地理配准的控制点选取不同、图幅变形校正方式不同导致与地图接边不严丝合缝。这已经不是shp格式的问题而是数据源头质量的问题。解决这类数据不能只靠GIS算法修复。我一般会把接边区域放大到1:5000用“移位编辑”手工把明显错位的地质界线拉住对于大量图幅则先用一个统一矢量图层作为骨架再用“对齐栅格”或“边匹配”工具把相邻图幅边界上的节点按容差移动。这一步也叫“并库底图准备”最好在项目启动时就做别等裁完图再补救。6. 把图例做进QML模板让全国地质图图层的样式一次到位地质图出图最花时间的不是数据而是图例。全国地质图的图式对地层时代、侵入岩、断层线型的颜色有固定要求每次拿到新shp都重新配符号太浪费人力。正确的做法是把一套符合规范的样式存成QML模板然后反复套用。在QGIS里做好一个图层的分类符号后右键图层导出样式得到QML文件。它本质上是一个XML记录渲染类型、分类字段、每个类别的颜色和线型。下次拿到另一个图幅时只需把属性字段名对齐然后加载样式。# 把当前图层样式保存为模板 from qgis.core import QgsProject layer QgsProject.instance().mapLayersByName(strata_clip)[0] layer.saveNamedStyle(D:/styles/strata_qgisfirst.qml)这段代码的作用很简单把当前strata_clip图层的符号系统保存到指定路径。之后换图幅时在新图层上右键“加载样式”选择这个QML即可。但注意QML里的分类字段名是写死的如果新图幅的字段名不一样需要先在属性表里把字段名改一致。使用过程中我会再配一个“字段映射表”把不同图幅的GeoID、STRAT_CODE、LITHO这类别名统一映射到模板用的标准字段。靠这个习惯我维护过多幅1:20万地质图从接手到完成标准化底图时间从一周压缩到一天。如果你后续还要做三维展示先把这套QML固定下来再做shp转3dtiles就能把颜色符号一起带过去不用在三维场景里重新做材质。最后说一句我的习惯每交付一批全国地质图shp我一定把.cpg、.prj、.qml三件套连同属性字典一起交出去而不是只丢一个裸shp。缺了这些再好的几何数据也是黑匣子。前面几次我为省事跳过QML模板后来换同事接手时对方重新配了一晚上图例从那以后就再也不敢偷懒。希望这篇笔记能帮你少走几次这种弯路让这份shp数据真正落成可用的工程底图。本文还有配套的精品资源点击获取