根据省边界 GeoJSON + 真实 DEM 高程,生成可直接 3D 打印的中国地形浮雕 STL 模型。含省界台阶墙、河流/湖泊雕刻、山峰凸起、地级市插旗孔,大省自动分块,支持多省无缝拼接成一张全国大地图。
- 真实地形:基于 Copernicus DEM GLO-90(90m 分辨率)高程,按统一映射
z = K·√(h+200)生成浮雕高度(珠峰 ≈ 26mm) - 无缝拼接:所有省锚定同一全国 Albers 网格(
dx = scale/ppm全局常量),多省生成后坐标天然对齐,可直接拼接成完整中国地图 - 省界台阶墙:等高线式垂直台阶(无 45° 斜切),支持斜边 / 贝塞尔圆弧平滑
- 自然要素:河流(按 HydroRIVERS 等级定宽)与湖泊雕刻、主要山峰三角凸起
- 城市插旗孔:地级市中心贯穿孔,方便插旗杆
- 自动分块:单块超过 250mm 自动切分,附
summary.json布局元数据用于拼接对齐
china3dmap/
├── scripts/
│ ├── build_province_stl3.py # 主脚本: 按省生成 STL(全国共用网格版)
│ ├── config_data.py # 各省城市名单 + 主要山峰坐标
│ └── download_dem.py # 下载 Copernicus DEM 中国区瓦片
├── data/
│ ├── bounds/ # 省边界 GeoJSON(DataV, 随仓库分发)
│ ├── dem/ # DEM 瓦片(用 download_dem.py 获取, 不入库)
│ └── hydro/ # 河流/湖泊 shapefile(自备, 不入库)
├── output/ # 生成的 STL / 预览图 / summary.json
├── requirements.txt
└── README.md
- Python ≥ 3.10(开发环境 3.10.9)
- Windows / macOS / Linux 均可
# 1. 创建虚拟环境(可选但推荐)
python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS / Linux:
source .venv/bin/activate
# 2. 安装依赖
pip install -r requirements.txt脚本运行需要三类数据,除边界外均不随仓库分发(体积大或需遵守原始许可):
data/bounds/ 下的 china.json(全国省界)与各省 {adcode}_full.json(省内地级市)来自 阿里 DataV.GeoAtlas,已包含在仓库中,无需额外下载。
python scripts/download_dem.py从 AWS 公开桶 copernicus-dem-90m 下载中国全境(73.5E135.1E, 18.2N53.6N)的 GLO-90 瓦片到 data/dem/(约 1000+ 个 90m 瓦片,共数 GB,16 线程约 30-60 分钟)。支持断点续传(已存在的瓦片自动跳过)。
数据来源:Copernicus DEM GLO-90,© ESA/Copernicus,使用条款见 https://copernicus-dem-30m.s3.amazonaws.com/readme.html
- 河流:HydroRIVERS v1.0 Asia(需
ORD_STRA字段)- 来源:https://www.hydrosheds.org/products/hydrorivers
- 放置:
data/hydro/HydroRIVERS_asia/HydroRIVERS_v10_as_shp/HydroRIVERS_v10_as.shp
- 湖泊:Natural Earth 10m lakes
- 来源:https://www.naturalearthdata.com/downloads/10m-physical-vectors/
- 放置:
data/hydro/ne_lakes/ne_10m_lakes.shp
缺失时脚本会明确报错并提示放置路径(README『数据准备』)。
# 生成单个省(默认 1:300 万, 无底座)
python scripts/build_province_stl3.py --province 110000
# 生成北京 + 2mm 城市插旗孔 + 省界墙斜边平滑(推荐组合)
python scripts/build_province_stl3.py --province 110000 --city-holes 2 --smooth-boundary 0.3
# 生成全部 32 省(约 7-8 分钟)
python scripts/build_province_stl3.py --province all --city-holes 2 --smooth-boundary 0.3输出到 output/:<adcode>_<省名>.stl、同名 _preview.png,分块文件带 _pN 后缀,拼接布局在 summary.json。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
--province |
str | 必填 | 省 adcode(如 110000)或 all |
--scale |
float | 3000.0 |
比例尺:1mm = N 米(3000 = 1:300 万) |
--block |
float | 250.0 |
单块最大边长 mm,超过自动分块 |
--ppm |
int | 4 |
分辨率 px/mm(越大细节越多、文件越大) |
--pins |
flag | 关 | 底座四角定位销(分块拼接对齐用) |
--mountain-labels |
flag | 关 | 山峰标注名称文字 |
--base |
float | 0.0 |
底座高度 mm,0 = 无底座 |
--seam-smooth |
float | 0.0 |
省界锯齿简化容差 mm(0 = 不简化) |
--seam-curve |
int | 0 |
省界轮廓 Chaikin 样条平滑迭代次数(推荐 2) |
--suffix |
str | "" |
输出文件名后缀(多版本对比用) |
--city-holes |
float | 0.0 |
地级市中心插旗孔直径 mm(推荐 2) |
--smooth-boundary |
float | 0.0 |
省界墙斜边平滑阈值 mm(推荐 0.3) |
--curve-boundary |
float | 0.0 |
省界墙圆弧平滑阈值 mm(与 --smooth-boundary 互斥) |
--no-exclaves |
flag | 关 | 剔除飞地(默认保留) |
所有省锚定同一全国网格,逐省生成后坐标天然对齐:
# 逐省生成(可分次执行, 推荐用于分块打印)
python scripts/build_province_stl3.py --province 110000 --city-holes 2 --smooth-boundary 0.3
python scripts/build_province_stl3.py --province 120000 --city-holes 2 --smooth-boundary 0.3
# ...其余省份...
# 或一次全量
python scripts/build_province_stl3.py --province all --city-holes 2 --smooth-boundary 0.3关键:所有省必须使用同一套 --scale / --ppm / --base / --block。1:300 万全国约 166×133cm,超出打印幅面时用 --block 自动分块,按 summary.json 布局拼接;可用更大 --scale(如 6000)缩小整图。
所有 STL 应为水密模型(0 开边):
python -c "
from stl import mesh
from collections import defaultdict
import glob
for f in glob.glob('output/*.stl'):
v = mesh.Mesh.from_file(f).vectors
ec = defaultdict(int)
for tri in v:
for a, b in [(0,1),(1,2),(2,0)]:
ec[tuple(sorted((tuple(tri[a]), tuple(tri[b]))))] += 1
print(f, 'open_edges:', sum(1 for k, c in ec.items() if c == 1))
"- 报错「缺少水文数据」:按『数据准备』第 3 节放置 HydroRIVERS 与 ne_lakes
- 报错「bbox 内无 DEM 瓦片」:先运行
download_dem.py下载 DEM - 生成很慢:大省(内蒙古/新疆)约 1 分钟属正常;
--scale越小、--ppm越大越慢 - 拼缝有缝隙:优先检查是否用了同一套
--scale/--ppm;可见缝隙主要来自数据几何本身(凹形边界、沿海段),非网格对齐问题
Apache License 2.0。详见 LICENSE。
- 省边界:阿里 DataV.GeoAtlas
- DEM:Copernicus DEM GLO-90(ESA/Copernicus)
- 河流:HydroRIVERS v1.0(HydroSHEDS)
- 湖泊:Natural Earth 10m
