☰
ArcGIS自建1:5万接图表:从分幅规则到图幅号计算
2026/10/16 16:45:33 网站建设 项目流程

简介:全国一比五万接图表是地理信息系统领域常用的基础数据,能在该比例尺下呈现地形、水系、道路与行政区域等要素,广泛用于城市规划、环境评估与土地利用调查。这份打包资料将标准接图表整理为矢量文件格式,共包含七个文件,主要有空间几何文件、属性数据文件、投影定义文件以及索引文件,可在主流桌面版地理信息软件中直接加载,无需额外转换。压缩包仅一点一四兆字节,体量很小,适合快速下载并作为项目底图。目前已有七百九十八人浏览学习。相比逐幅申请原始数据,该分包提供了全国统一的分幅格网与投影参数,省去格式整理与坐标对齐环节,便于开展图幅查询、要素编辑、叠加分析和专题制图,也适合作为课程实验或科研示例数据。

1. 全国1:5万接图表:别再来回找图幅号,自己用ArcGIS生成一份

做数据汇交时,两个单位拿着同一片区域的1:5万数据,图幅范围怎么都对不上,最后翻规范、查编号、问前辈,折腾半天才搞明白是接图表用错了版本。所谓全国1:5万接图表,就是把1:5万标准地形图逐幅的经纬度范围和图幅编号列成一张索引表,在ArcGIS里它可以是点、是线、是面,但核心价值只有一个:让你点到一处、看图幅号、按号找数据。网上流传的接图表不少,但坐标系旧、编号新旧混用的也很多,与其碰运气,不如按国标分幅规则自己生成一份,干净、可控、随时能更新。这篇就讲清楚规则、ArcGIS操作和那些让我踩过不止一次的坑。

2. 先把分幅规则吃透:1:5万接图表的经纬度骨架与编号规则

2.1 一张1:5万图幅到底占多大地方:从1:100万往下切

国家标准分幅地形图,从1:100万开始往下逐级划分,每一级都有固定的经差和纬差,不按行政边界、不按图廓美观,只按经纬度切。1:5万的图幅经差15分、纬差10分,换算成度分别是0.25度和0.1666667度。这个数看起来简单,却是后面生成格网、计算图幅号的全部基础。

分幅的源头是1:100万:经差6度、纬差4度。以1:100万图幅为底图,1:50万分为2行乘2列,1:25万分为4行乘4列,1:10万分为12行乘12列,到了1:5万这一级,一个1:100万图幅内正好分成24行乘24列,共576幅。各级比例尺的对应关系如下:

比例尺经差纬差在1:100万图幅内的行列划分
1:100万6°4°1幅
1:50万3°2°2行×2列=4幅
1:25万1°30′1°4行×4列=16幅
1:10万30′20′12行×12列=144幅
1:5万15′10′24行×24列=576幅
1:2.5万7′30″5′48行×48列=2304幅
1:1万3′45″2′30″96行×96列=9216幅

全国范围的1:5万图幅总量大约在两万七千余幅,覆盖陆地岛屿和近海。数值看起来吓人,但你要理解的是规则而不是数量:只要知道某点的经纬度,就能算出它落在哪个1:5万图幅里;反过来,给出图幅号,就能算出该图幅的经纬度范围。接图表本质上就是这套一一对应关系的空间化表达。

边界归属有个约定要注意:相邻图幅的边界上,通常按“含左下角,不含右上角”处理,避免两个图幅都算自己。算图幅号和生成格网时如果不遵守这个约定,容易出现一个点同时被两幅图命中的情况。后面写脚本时我会在代码里加容差处理。

2.2 新旧两套编号规则:接图表里最常见的“对不上号”

图幅编号看着像个黑匣子,其实解码规则非常机械。国内从1991年前后推行新编号体系,之前的老图用旧编号,之后的新图用新编号,两套规则并存,这是接图表使用中最常见的翻车点。

旧编号的典型形式是J-50-55-A:J-50代表1:100万图幅,55代表1:10万图幅序号,最后的A代表1:5万图幅在1:10万图幅内的四分之一位置。新编号则把1:100万、比例尺代码、行号、列号拼在一起,比如J50E001002:J50是1:100万图幅,E是1:5万比例尺代码,001是纬度方向的行号,002是经度方向的列号。新编号里1:5万的比例尺代码是E,不要和1:10万的D搞混。

编号体系典型格式组成部分
旧编号J-50-55-A1:100万图号-1:10万序号-四分之一方位码
新编号J50E0010021:100万图号+比例尺代码+3位行号+3位列号

新旧编号的对应关系是可以直接换算的,但实际数据里经常两边混着用:老数据成果写旧号,新汇交成果写新号,Excel表格里又是一套,接图表和属性表一连接就大量空值。我的建议是接图表里同时保留SHEET_NO(新编号)和SHEET_NO_OLD(旧编号)两个字段,平时用新号做主键,遇到老数据再走旧号挂接,别做二选一。

2.3 在ArcGIS里用Create Fishnet生成全国1:5万格网

明白了分幅规则,生成接图表就顺理成章:把全国范围的经纬度范围按经差15分、纬差10分切成面网格,每个面就是一张1:5万图幅。ArcGIS里最直接的工具有两个名字:工具箱里的创建渔网,以及对应的arcpy.management.CreateFishnet。注意,生成格网这一步坐标系选地理坐标系,直接输出经纬度,不要在投影坐标系下生成,否则所有维度单位都会变成米。

常见做法是先建一个文件地理数据库,把格网放到里面。要素类用GDB格式比shapefile省心,字段长度、中文支持、编辑效率都好不少。以下是最小可运行脚本,在ArcGIS Pro的Python窗口或任何装了ArcPy的环境里都能跑:

import arcpy out_gdb = r"D:\workspace\GB50000.gdb" out_fc = out_gdb + r"\grid_50000" # 全国1:5万分幅的大致覆盖范围,单位:度 origin = "73 3" # 渔网起点:左下角经纬度 y_axis = "73 4" # Y轴方向点,保证格网正南正北 cell_w = "0.25" # 经差15分 = 0.25度 cell_h = "0.16666666666666666" # 纬差10分 opposite = "136 54" # 对边角:右上角经纬度,决定格网范围 arcpy.management.CreateFishnet( out_fc, origin, y_axis, cell_w, cell_h, 0, 0, # 行列数填0,由对边角自动推导 opposite, "NO_LABELS", "#", "POLYGON" ) arcpy.management.AddField(out_fc, "SHEET_NO", "TEXT", field_length=20) print("格网已生成:", arcpy.management.GetCount(out_fc)[0])

逻辑说明:CreateFishnet以Origin为起点,按给定的单元格宽度和高度向对边角方向铺满,生成规则整齐的矩形面。这里用经纬度地理坐标系,单元宽高直接填度,0.25度就是15经分,0.16666666666666666度等于10纬分。行列数参数填0,工具会根据起点到对边角的距离自动计算需要多少行多少列,省去手动数的麻烦。输出POLYGON面要素,每个面后续会对应一个图幅号。

参数说明:Origin务必是左下角;Y轴坐标点只决定格网的方向,填正北方向(经度相同、纬度略高)即可;Opposite的经纬度范围要略大于全国覆盖范围,否则边缘图幅会被截掉;如果不需要创建标注点,Labels填NO_LABELS。生成后建议用GetCount看一眼要素数量,全国范围算上海域格网会有数万个,如果只想留陆地图幅,后续可以叠加陆地或已有图幅目录做筛选,这也是后面章节要处理的事。

3. 给格网写入图幅号:字段设计与ArcPy批量计算

3.1 接图表字段怎么设计才不乱

格网建好后只是一堆矩形面,真正值钱的是每个面对应的图幅号、图名和位置信息。字段设计在第一步就做对,后面能少踩很多坑。我把常用字段列成下表,其中SHEET_NO作为唯一标识,建议设置成文本类型并限制长度,避免数字型字段丢失前导零。

字段名类型长度说明
SHEET_NOTEXT20新编号图幅号,主键,如J50E001002
SHEET_NO_OLDTEXT30旧编号图幅号,兼容老数据
MAP_NAMETEXT30图名,需从正式图幅目录中填入
LON_MINDOUBLE-图幅左下角经度
LAT_MINDOUBLE-图幅左下角纬度
LON_MAXDOUBLE-图幅右上角经度
LAT_MAXDOUBLE-图幅右上角纬度
BELT_6SHORT-所在6度分带带号,用于投影转换

注意图名不是程序能直接算出来的,它取自图幅内重要的居民地或自然地名,必须从国家正式出版的图幅目录或已有的标准分幅数据元数据里拷贝,别指望脚本凭空生成。SHEET_NO_OLD同理,需按新旧编号规则从新号换算,或从元数据中提取。我的习惯是先用脚本计算新号,再批量生成旧号字段,两次结果对比校验。

字段名一律用英文大写,中文含义写在别名里。shapefile的字段名长度限制和编码兼容性都差,GDB要素类要宽松得多,这也是我坚持把接图表放GDB的原因。先留好字段免得后悔,后面再补字段、改字段类型才是真的折磨。

3.2 ArcPy批量计算1:5万图幅号:核心脚本

图幅号的计算逻辑分三步:先算1:100万图幅的行列号,再算该点在1:100万图幅内的1:5万行列号,最后拼装成完整编号。1:100万行号从赤道向北每4度一行,用字母A到V表示;列号从西经180度起每6度一列,用两位数字表示。1:5万行号列号各三位,范围001到024。

下面这段脚本遍历上一步生成的格网,取每个格网范围左下角的经纬度计算图幅号,直接回写到SHEET_NO字段。我在边界处理上加了小容差,避免浮点误差导致经纬度刚好落在分幅线上时算错行。

import arcpy fc = r"D:\workspace\GB50000.gdb\grid_50000" field = "SHEET_NO" def get_sheet_no(lon, lat): # 1:100万行号:纬度0-4度为A,每4度递增一字母 row100 = int(lat // 4.0) + 1 # 1:100万列号:从西经180度起每6度一列 col100 = int((lon + 180.0) // 6.0) + 1 # 该1:100万图幅左下角的经纬度 lon_min = (col100 - 1) * 6.0 - 180.0 lat_min = (row100 - 1) * 4.0 # 容差:浮点误差会导致整分边界判断错位 eps = 1e-6 # 1:5万纬差10分,行号范围001-024 row5 = int((lat - lat_min) / (10.0 / 60.0) + eps) + 1 # 1:5万经差15分,列号范围001-024 col5 = int((lon - lon_min) / (15.0 / 60.0) + eps) + 1 # 行号字母:A对应1,B对应2,依此类推 row_char = chr(ord('A') + row100 - 1) return "{}{:02d}E{:03d}{:03d}".format(row_char, col100, row5, col5) with arcpy.da.UpdateCursor(fc, ["SHAPE@", field]) as cursor: for i, (shape, _) in enumerate(cursor, 1): ext = shape.extent cursor.updateRow([shape, get_sheet_no(ext.XMin, ext.YMin)]) if i % 5000 == 0: arcpy.AddMessage("已处理 {0} 个图幅".format(i))

逻辑说明:UpdateCursor遍历要素时,SHAPE@返回几何对象,extent取到的是当前面的最小外包矩形,XMin和YMin恰好是该图幅左下角的经纬度。每个图幅格网本身就是按经纬度切出来的规则矩形,左下角作为定位点不会受质心偏移影响,这也是不采样面中心的原因。字符串拼装时,行号字母用ASCII码转换,列号用两位补零,比例尺代码E写死,后面三位行号三位列号分别补零,最终得到规范的12位新编号。

参数说明:row100和col100的“+1”是因为编号从1开始而非从0开始;eps容差的量级定在1e-6度,约等于0.0036秒,只消化浮点误差,不会吞掉真实边界;如果遇到复杂面要素比如跨越两个图幅的合并面,必须先在前面保证格网要素不与分幅线交叉,这正是Create Fishnet按经纬度切格网的天然优势。脚本跑完后,用属性表检查几个已知坐标点的图幅号是否和规范一致,再往下走。

3.3 计算完怎么验证:标注样式与SQL查重

图幅号写进属性表并不代表万事大吉,我吃过一次亏:全批量算完后发现某一行公式里把比例尺代码写成了D,整个图层看起来没问题,实际没有一幅是1:5万的。所以验证步骤不能省。

第一步做标注。在图层面板打开标注,字段选SHEET_NO,用“图幅号”做显示表达式,缩放到局部窗口,肉眼判断图幅号是否随经纬度递增有序。第二步用SQL查重复,理论上每个格网的图幅号必须唯一:

SELECT SHEET_NO, COUNT(*) AS CNT FROM grid_50000 GROUP BY SHEET_NO HAVING COUNT(*) > 1

如果查出的CNT大于0,说明有边界归属或格网重叠问题,重点检查Create Fishnet的对边角范围和容差设置。第三步抽样比对:随机挑几个图幅号,按经纬度范围手算一遍,或者和国家正式发布的1:5万图幅表核对。最后检查字段的左右值范围,LON_MIN应该全部落在东经73度到135度之间,LAT_MIN落在北纬3度到54度之间,出现越界值说明原始格网范围设大了或坐标系回写错了。

4. 接图表应用的排查与避坑:坐标系、字段和编码

4.1 接图表与标准分幅数据叠不上:坐标系的锅

现象:接图表在ArcMap里加载后,和已有的1:5万标准分幅影像叠加,整体偏移几十米到几百米,放大看错位明显,缩小看又像对上了,让人以为是数据本身的问题,其实是坐标系没统一。

原因:接图表生成时用的是WGS84地理坐标系,而多数国内1:5万生产数据用的是CGCS2000或1980西安坐标系的高斯投影。ArcMap的动态投影只是即时显示变换,缺基准面转换参数时,地理坐标系之间会默认按无偏移处理,投影坐标系和地理坐标系叠在一起自然错位。这种问题最迷惑人,经常被当成玄学处理。

解决:把接图表投影转换到和目标数据一致的坐标系,而不是依赖动态投影。用投影工具,输入接图表要素类,选择目标坐标系如CGCS2000 3 Degree GK Zone或6度带高斯投影,输出新要素类后重新加载。如果目标区域跨了好几个6度带,就按3.1里的BELT_6字段分带处理,每带单独投影,或者干脆用Albers等积投影做全国统一索引,标注时再去查带号。

4.2 新旧图幅号混用导致连接失败

现象:把Excel里的图幅清单和接图表做属性连接,结果大量记录显示为空,或者匹配上的只有一半;仔细看发现Excel里写的是J-50-55-A这种旧编号,而接图表里全是J50E001002这样的新编号,格式不同,连接自然失败。

原因:新旧编号规则差异不是简单的加字符,两个体系的排列方式、比例尺代码、行列号位数都不同,直接文本匹配必然失效。更隐蔽的是同一片区域有些数据源用旧号归档,有些用新号归档,汇总时没人统一。

解决:给接图表增加SHEET_NO_OLD字段,写一段换算逻辑生成旧编号,或者写个辅助函数在新旧编号之间互相转换,再把Excel数据统一转成新编号后再做连接。我的习惯是保留原始编号字段不动,新生成一个标准化字段用于挂接,这样既能看到原始值,又能稳定连接,算是一份后悔药。老旧数据务必在字段备注里标明编号体系来源,避免下次汇交又踩一遍。

4.3 中文图名乱码与字段长度问题

现象:接图表属性表里MAP_NAME字段打开一看,中文图名全变成“??”或一段乱码,有的字段只显示前面两个字,后半截被截断。这个现象在shapefile格式里尤其常见,GDB里偶尔也会出现。

原因:shapefile的dbf属性表对字符编码的支持比较弱,老版本ArcMap默认按系统代码页读取,中文很容易变成乱码;字段长度不够则是图名超过设定长度被截断,比如字段设了10个字符,遇到“某某县某某乡”这种长图名就装不下。

解决:接图表优先用GDB要素类而不是shapefile,GDB内部存储对UTF-8支持好很多;字段长度给足,MAP_NAME建议至少30个字符;如果确实要输出shapefile,在导出时把代码页设置成UTF-8,并在加载时确认编码识别正确。还有一个排查小技巧:乱码往往只在显示层,用字段计算器转成Unicode或重新读取一遍,有时能修复,但最稳妥还是源头就存对。

4.4 生成格网“图幅数不对”:单位与范围设置翻车

现象:按前面脚本创建渔网,结果出来图幅总数差得离谱,要么只有几百个,要么密密麻麻几百万个,缩放到图面上一看,格网要么大得离谱要么小得看不见,明显不是1:5万应有的尺度。

原因:大多数情况是坐标系没选对。Create Fishnet工具界面上如果当前地图或环境坐标系是投影坐标系,Cell Width和Cell Height的单位就变成米,此时填0.25产生的不是0.25度,而是0.25米,格网自然完全错乱。另一种情况是对边角范围填错,比如原点填了(73, 3),对边角填了(73.5, 4),生成的就只有一个格网。

解决:生成渔网前把环境坐标系设置成GCS_WGS_1984,或者干脆在图层属性里把地图坐标系切到WGS84再运行工具;对边角范围要比全国实际覆盖范围略大,建议填(136, 54);生成后第一时间检查要素总数和范围,全国含海域的1:5万格网数量应该在数万个量级,如果差太多直接取消重新生成。这个坑几乎每个做过接图表的人都会踩一次,花两分钟检查环境设置,能省两小时排错。

5. 接图表真正的用武之地:批量裁剪与图幅检索

5.1 按图幅号批量裁剪数据

接图表最大的价值不是画出来好看,而是作为工作清单驱动批量处理。最常见的需求是:手头有一整块DOM或DEM,要按1:5万图幅裁成标准分幅成果,输出文件名直接带图幅号,后续入库、分发、质检全部按图幅走。用接图表遍历每个图幅的坐标范围执行裁剪,比手工一个个画范围框快一个数量级。

import arcpy grid_fc = r"D:\workspace\GB50000.gdb\grid_50000" in_raster = r"D:\raw\DOM.img" out_gdb = r"D:\clip\ClipResult.gdb" arcpy.env.workspace = out_gdb with arcpy.da.SearchCursor(grid_fc, ["SHEET_NO", "SHAPE@"]) as cursor: for sheet_no, shape in cursor: ext = shape.extent extent_str = "{} {} {} {}".format(ext.XMin, ext.YMin, ext.XMax, ext.YMax) out_name = "clip_{}".format(sheet_no) try: # 栅格裁剪:范围字符串依次为左、下、右、上 arcpy.Clip_management(in_raster, extent_str, out_name, "#", "#", "NONE") arcpy.AddMessage("完成: {}".format(out_name)) except Exception as e: arcpy.AddWarning("图幅 {} 裁剪失败: {}".format(sheet_no, e))

逻辑说明:SearchCursor逐行读取接图表,取出SHEET_NO和几何范围,extent拼成“最小经度 最小纬度 最大经度 最大纬度”的字符串传给Clip_management。输出文件名直接使用图幅号,保证和接图表一一对应。try块把失败图幅单独记录为警告,而不是中断整个循环,方便跑完后统计失败清单,一次处理完所有图幅。裁剪参数最后的NONE表示不执行NoData值掩膜,具体要不要掩膜按源数据情况调整。

参数说明:Clip_management第一个参数是输入栅格,第二个是四角范围字符串,顺序一定不能换;输出名只写要素类名,会自动创建在out_gdb里;如果裁剪矢量,用arcpy.Clip_analysis并传入面要素作为裁剪范围。每幅数据裁完后,建议顺手生成一张覆盖统计表,记录图幅号、像元数、空值率,作为成果质量检查的辅助材料。这样接图表就从“一张索引图”变成了“一个可执行的工作流”,整个分幅入库流程能节省大量手工操作时间。

5.2 图幅检索小工具与制图索引

日常用图幅号定位也离不开接图表。以前找幅图要在纸质接图表上数格子,现在直接在ArcGIS里写一句属性查询,选中即缩放定位,非常快。给接图表图层配好这个交互逻辑,基本就是半个图幅检索小工具了,不用额外开发。我平时最常用的操作:

import arcpy arcpy.SelectLayerByAttribute_management("grid_50000", "NEW_SELECTION", "SHEET_NO = 'J50E001002'") arcpy.ZoomToSelected("grid_50000")

SELECT语句里的图幅号可以从Excel、定位点或其他系统传入,配合一个简单的输入框就能做成随手可用的检索功能。如果想把接图表放进挂图或图集,可以直接把SHEET_NO和MAP_NAME字段做标注,按图幅号排序后就是标准索引页。发布成服务后,前端点击图幅面即可高亮显示图幅信息,这套思路不需要额外插件,只要把接图表作为基础图层发布即可。

做了这么多年分幅数据,我最大的教训是:接图表这种基础资料,越早自己建一份越省心。网上拿来的数据版本不明,用起来心里没底;按规则自己生成,图幅号逻辑完全在掌控之中,坐标系、字段、编号体系都清楚,出问题也能快速定位。希望这份踩坑记录帮你在做接图表时少绕几个弯,一次做成顺手能用的好工具。

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

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

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

立即咨询