GeoJSONcn
GeoJSONcn / 技术专栏 / 全国省市区县区划边界数据下载后的…

全国省市区县区划边界数据下载后的部件粒度:一个省 6 个要素怎么摊出 657 块

发布于 2026-09-26 · GeoJSONcn 技术团队 · 阅读约 10 分钟

一份省级边界文件打开来看,features 数组的长度往往只有十几个,凭直觉会以为这是份轻量数据。实际把它摊平到多边形一级,情况完全不同:本站 mapjson/省/ 下 34 个文件合计 498 个要素,展开后是 1590 个独立部件;海南省 6 个地级单元里,有两个分别由 328 块和 324 块组成,平均每块只有 11 个顶点。这个反差不是数据质量问题,而是岛屿与飞地的必然结果,它直接决定了后续建什么索引、按什么粒度发渲染任务。

先看清 features 数量代表什么

这批文件的属性只有四个字段:省、省代码、类型,几何是 MultiPolygon。没有地级名称列,所以 features 的长度实际上等于该省下辖的地级单元数——重庆市 38 个、四川省 22 个、宁夏 6 个,与行政区划口径对得上。真正的信息藏在每个要素的 coordinates 数组里,那里才是离散程度的分水岭。

把 498 个要素逐个统计部件数(Polygon 的个数),分布是这样的:

分位单要素部件数
中位数1
均值3.2
最大328
单部件要素占比79.9%

近八成要素只有一块,这说明内陆与平原省份的文件极其规整。新疆那个顶点最多的要素有 8556 个顶点、却只占 1 个部件,是典型的"一整片、边界密";西藏 8 个要素里 6 个是单部件,最大一块 6865 顶点。这类数据在建索引时几乎没有额外开销。

岛屿把部件数拉开三个数量级

沿海省份是另一回事。按"部件数 ÷ 要素数"这个比值排序,梯度陡得离谱:

省份要素数部件数部件/要素
海南省6657109.5
浙江省1216013.3
福建省10585.8
广东省22964.4
台湾省21502.4

海南的 657 块摊在 6 个要素上,两个大要素各分走 328 与 324 块,余下四块是零星小岛。浙江 160 块里,两个沿海地级单元贡献 123 块。取一个沿海要素单独看,它的几何形态与新疆那种"大而密"完全相反:328 块共 3932 个顶点,平均一块 12 个点——每块就是一座小岛的四至轮廓,甚至只是几笔蘸出的礁体形状。

这个结构对空间索引的选型是决定性的。R 树、四叉树这类索引的节点分裂依赖要素的包围盒分布,面对 328 个散在经纬度上的小矩形,用"要素级"索引会得到一个几乎无用的稀疏树;而把它们当独立几何体加进去,检索效率立刻回到正常水平。判断方法很直接:

import json

def part_stats(path):
    gj = json.load(open(path, encoding="utf-8"))
    parts, single = 0, 0
    for ft in gj["features"]:
        polys = ft["geometry"]["coordinates"]
        parts += len(polys)
        # 单部件且顶点少 ⇒ 大概率是碎岛,索引时按独立几何处理
        v = sum(len(r) for p in polys for r in p)
        if len(polys) == 1 and v < 100:
            single += 1
    return {"parts": parts, "single_part": single,
            "splittable": parts > len(gj["features"]) * 3}

for p in ["内蒙古自治区", "浙江省", "海南省"]:
    print(p, part_stats(f"site/mapjson/省/{p}.json"))

splittable 这个判据取 3 倍是经验值:低于它,文件规整、按要素处理最省事;高于它,就该把几何体拆开再入索引,否则一次"点选某座岛"的查询要在整个城市的多边形上做逐点判定。

渲染批处理该按谁分组

另一个直接受影响的环节是切分渲染任务。把每个地级单元当成一个任务包时,任务耗时与顶点数并不成比例——两个沿海要素的顶点数(3932、3593)与内陆地级单元相当,但前者要处理 328 个部件、走 328 次独立路径绘制,样式切换与线宽重算的次数是后者的几百倍。实测中这类任务的实际绘制开销比同顶点的单部件任务高出数倍。

稳妥的做法是按"部件数 × 顶点数"的估算值分档:内陆单部件要素合并成批,沿海高部件数要素单独成批,避免一个批次里既有 8556 顶点的巨块又有 328 块碎岛,导致长尾任务拖住整个队列。这套分档与县级、乡镇级数据同一逻辑,只是全国乡镇街道边界数据下载 得到的文件里"部件数"的离散程度远大于"要素数",差距更容易被忽略。

本轮统计跑在本站 mapjson/省/ 的当前快照上,换一版来源数字会浮动。真正能带走的是两个判据:部件计数与部件密度,它们只读几何结构、不看属性列,从 GeoJSON下载 回来的任意一批省级边界都能直接跑一遍做对照。

落到实际使用的取舍

如果目的只是把某个省或某个市的轮廓摆进汇报材料,这套索引与批处理逻辑完全用不上。要省事的话,可直接从这里取现成的排版件——地图 PPT 模板选购页 里每个单元都是一张排好版的可编辑底图,预览免费,单份 ¥4.99,碎岛在制作阶段就按视觉权重调过大小,不必再纠结该不该保留。全国村级 geojson 数据下载 得到的村级数据在这一点上更极端,一个沿海乡镇拆出上百个海岛村面是常事,届时部件粒度这个指标的价值会比省级文件大得多。

需要说明的是,本站只对预览免收费用,文件导出与模板下载均按次计费——全国省市区县区划边界数据下载 的单次导出为 ¥1.99,地图 PPT 模板为 ¥4.99 一份。

上面这套部件粒度判据,对全国省市区县 geojson 数据下载 之外的数据同样成立:省界、市界、区县界三级文件的部件结构差异只体现在岛屿密度上,索引与分批策略可以共用一套代码路径。