CityPoster — 城市地图海报生成器
基于 maptoposter 改造,专注中国城市离线地图海报。
安装
git clone https://codeberg.org/songwupei/cityposter.git
cd cityposter
uv sync
依赖
核心依赖:geopandas matplotlib osmnx pyarrow(Parquet 缓存),详见 pyproject.toml。
Shell 补全
# bash
source completions/cityposter.bash
# zsh
fpath=(completions $fpath); autoload -Uz compinit; compinit
SinoGDB 数据 (中国城市离线生成)
新:支持 Parquet 和 GPKG 双后端,自动检测。 首次运行后自动缓存,后续秒出图。
数据源优先级(自动检测,无需手动配置):
SINOGDB_DIR 自动选择:
├─ ~/Public/GeoData/SinoGDB/ ← Parquet(推荐,3.1GB / zstd)
├─ ~/Downloads/SinoGDB-PackSet_gpkg_*/ ← GPKG(原始,7GB)
└─ ~/NutstoreFiles/8-MyData/GeoData/SinoGDB/ ← 坚果云同步
方式一:Parquet(推荐) — 用 gpkg2parquet.py 将 GPKG 转为 Parquet:
python gpkg2parquet.py ~/Downloads/SinoGDB-PackSet_gpkg_*/ -o ~/Public/GeoData/SinoGDB/
# 7 GB GPKG → 3.1 GB Parquet (zstd),直接可用
方式二:GPKG 原始格式 — 下载 SinoGDB-PackSet,设置路径:
export SINOGDB_DIR="$HOME/Downloads/SinoGDB-PackSet_gpkg_20260208"
首次运行后,数据自动缓存至 cache/:
| 缓存 | 路径 | 用途 |
|---|---|---|
| 城市数据 | cache/sinogdb_city/{lat}_{lon}_{radius}/*.parquet |
道路+水系+POI,按 bbox 分片 |
| 全国铁路 | cache/railway_cache.parquet |
一次性全量构建,所有 country 主题共用 |
缓存一旦建立,即使源数据被删除或移动也能正常渲染。 适合:
- 在多台机器间共享缓存目录
- 构建一次后归档源数据释放磁盘空间
- CI/CD 环境只需缓存文件即可出图
使用
# 中国城市 — 走 SinoGDB(有缓存直接用缓存,无缓存从 GPKG 读取并缓存)
cityposter --lat 39.9042 --lon 116.4074 -dc "北京" -dC "中国" -t noir --poi
cityposter --lat 30.5728 --lon 104.0668 -dc "成都" -dC "中国" -t gongqiang --poi
# 中国城市 — GPKG 和缓存都没有时自动降级到 OSMnx(在线)
cityposter --lat 34.26 --lon 108.94 -dc "西安" -t terracotta
# 国际城市 — 直接走 OSMnx
cityposter -c "Paris" -C "France" -t pastel_dream -d 10000
数据源逻辑
cityposter 会自动选择最佳数据源,优先离线:
中国坐标?
├─ 是 → sinogdb 路径
│ ├─ 有 parquet 缓存?→ ✓ 直接用缓存(离线,秒级)
│ ├─ Parquet 数据在? → 读取 Parquet + 自动写缓存(推荐)
│ ├─ GPKG 数据在? → 读取 GPKG + 自动写缓存
│ └─ 都没有
│ ├─ Country 主题 → ❌ 报错(需源数据或预置缓存)
│ └─ City 主题 → ⚠ 降级 OSMnx(在线)
└─ 否 → OSMnx 路径(在线,有 pickle 缓存)
--data-source sinogdb|osmnx 可强制指定数据源,跳过自动检测。
参数
| 参数 | 说明 | 默认 |
|---|---|---|
--lat, --lon |
中心坐标 (WGS-84) | |
--gcj02 |
坐标视为 GCJ-02 | |
-dc, -dC |
显示名称 | |
-t |
主题 | terracotta |
-d |
半径 (米) | 8000(中国) |
--poi |
POI 标注 | 关闭 |
--poi 全部 / --poi subway,sightseeing 指定类别 |
--poi 详情
不加值显示全部,指定类别则只显示选中项:
cityposter ... --poi # 全部
cityposter ... --poi subway # 只看地铁
cityposter ... --poi subway,sightseeing,park # 地铁+景点+公园
cityposter ... --poi subway,custom # 地铁 + 自定义 POI
简写对照:
| 简写 | 全称 | 中文 |
|---|---|---|
subway |
subway_station |
地铁站 |
train |
train_station |
火车站 |
bus |
bus_station |
公交站 |
airport |
airport |
机场 |
sightseeing |
sightseeing_spot |
景点 |
landmark |
landmark |
地标 |
museum |
museum |
博物馆 |
temple |
temple |
寺庙 |
park |
park |
公园 |
mall |
mall |
商场 |
food |
restaurant |
餐饮 |
hotel |
accommodation |
住宿 |
school |
school |
学校 |
hospital |
hospital |
医院 |
custom |
— | 自定义 POI(同 --custom-poi) |
不加 --poi 则不显示任何标注,纯地图。
自定义 POI (--custom-poi)
两处数据源,个人目录优先:
| 目录 | 用途 |
|---|---|
~/.config/cityposter/custom-poi/ |
个人专属,升级不丢 |
config/custom-poi/ |
项目通用,随代码分发 |
GeoJSON 格式(支持 .json / .geojson):
{
"type": "FeatureCollection",
"coord_type": "gcj02",
"features": [
{
"type": "Feature",
"properties": {"name": "故宫", "category": "景点"},
"geometry": {"type": "Point", "coordinates": [116.3972, 39.9163]}
}
]
}
coord_type:"gcj02"高德坐标自动转 WGS-84,默认"wgs84"category: 支持中文("景点")、英文("Sightseeing")、key("sightseeing_spot")- 文件名含城市名 = 城市专属优先加载;不含 = 通用兜底
_或.前缀文件忽略(禁用/备份)
| -f | png/svg/pdf | png |
| --font-family | Google Fonts | Noto Sans SC(中国) |
主题层级
主题按 themes/{city,province,country}/ 分三级,自动检测中国坐标走 SinoGDB:
| 级别 | 目录 | 数据 | 适用 |
|---|---|---|---|
city |
themes/city/ |
道路+水系+公园+POI | 城市级(<50km) |
province |
themes/province/ |
铁路+省界 | 省级(100–1000km) |
country |
themes/country/ |
铁路+省界 | 全国/大区域(>1000km) |
province 级别默认启用铁路虚线(railway_dashed),在省级尺度清晰可见。
全国地图 (country/province 主题)
themes/country/ 目录包含全国/大区域主题,只加载铁路+省界数据,支持大半径:
# 全国高铁+省界图(8500km,西安中心,16:9 桌面壁纸)
cityposter --lat 34.26 --lon 108.94 -dc 中国 \
-t atlas_outline -W 16 -H 9 -d 8500000
# SVG 矢量输出(无限缩放)
cityposter ... -f svg
| 级别 | 主题 | 说明 |
|---|---|---|
| country | atlas_outline |
高铁+省界,纯轮廓图 |
| country | atlas_highway |
高速路网(motorway+primary) |
| country | atlas_railway |
全部铁路+高速骨架 |
| country | atlas_highspeed |
仅高铁+高速骨架 |
| country | atlas_transport |
综合交通(高速+主干+铁路) |
| country | atlas_outline_relief |
地形底图+高铁+省界,山河叙事地图 |
| country | atlas_outline_relief_water |
地形+水系+高铁+国省界,全要素山河地图 |
| country | atlas_outline_relief_water_noroad |
地形+水系+国省界,无道路版 |
| country | atlas_outline_relief_water_noroad_midnight |
暗色 — 午夜海图配色 |
| country | atlas_outline_relief_water_noroad_noir |
暗色 — 暖黑金配色 |
| country | atlas_outline_relief_water_noroad_obsidian |
暗色 — 黑曜石极致暗色 |
| province | atlas_dashed |
铁路虚线+省界,省级尺度 |
输出附带 _legend.yaml(颜色图例)、.sh(复现脚本)。GeoJSON/Parquet 导出需在主题中设置 "export_layers": true。
地形底图 (--relief)
基于 hongzhao (鸿爪) 的地形烘焙算法,从 AWS Terrarium DEM 瓦片生成山影地形。
# 全国山河叙事地图
cityposter --lat 34.26 --lon 108.94 -dc 中国 \
-t atlas_outline_relief -d 8000000 -W 16 -H 9
# 城市级地形底图
cityposter --lat 39.9042 --lon 116.4074 -dc 北京 -t noir --relief
特性:
- 自动选取 zoom 级别(5km→z14, 8000km→z6)
- 16 线程并行下载 + tqdm 进度条,缓存至
~/.cache/cityposter/terrarium/ - Natural Earth 陆地遮罩 → 陆海分离着色
- Mercator→WGS-84 重投影(大范围自动修正变形)
- 输出分辨率按
--dpi × -H自动适配(--dpi 300 -H 9→ 2700px) - 省界 Parquet 缓存、铁路分组 pickle 缓存
- 所有参数均可通过
cityposter/rendering/relief_config.toml调整
高程配色预设 (elevation_preset)
主题 JSON 中通过 "elevation_preset" 切换配色,内置 10 套:
| 预设 | 风格 | 海岸线 |
|---|---|---|
hongzhao (默认) |
经典山河配色 — 蓝海绿谷金丘褐山白峰 | 无 |
hongzhao_shore |
经典山河 + 白色浪花岸线 | -15m 白浪 |
ink |
水墨灰度 — 墨海灰陆,适配 shuimo / japanese_ink | 无 |
warm_earth |
暖色大地 — 暖青海 + 赭石琥珀,适配 terracotta | 无 |
forest |
森林绿调 — 湖绿海 + 深绿陆,适配 forest / emerald | 无 |
alpine |
高山雪峰 — 冰蓝海 + 岩灰→纯白峰,高对比 | 无 |
coastal |
白岸蓝海 — 深蓝海 + 0m 纯白海岸线 | 0m 白岸 |
midnight_shore |
午夜海图 — 墨蓝深海 + 冷白浪花 + 暗绿→亮白峰 | -15m 冷白浪 |
noir_shore |
暖黑夜 — 暖黑蓝海 + 暗金浪线 + 暗琥珀陆地 | -15m 暗金浪 |
obsidian_shore |
黑曜石 — 近纯黑深海 + 灰线浪花 + 极暗绿→纯白峰 | -15m 灰线 |
水系 (--water)
cityposter --lat 34.26 --lon 108.94 -dc 中国 \
-t atlas_outline_relief_water -d 8000000 -W 16 -H 9
加载 Natural Earth 1:50m 河流 (LineString) 和湖泊 (Polygon),在省界与铁路之间渲染。
渐变遮罩 (gradient)
海报上下边缘的渐变雾化效果,可在主题 JSON 中通过 gradient 对象配置:
{
"gradient": {
"enabled": true,
"color": "#ece2c8",
"top": { "height": 0.25, "opacity": 1.0 },
"bottom": { "height": 0.25, "opacity": 1.0 }
}
}
| 字段 | 默认 | 说明 |
|---|---|---|
enabled |
true |
总开关 |
color |
paper_color / bg |
渐变颜色 |
top.height |
0.25 |
顶部雾占画面比例(0 = 无) |
top.opacity |
1.0 |
顶部雾最大不透明度 |
bottom.height |
0.25 |
底部雾高度 |
bottom.opacity |
1.0 |
底部雾最大不透明度 |
所有 53 个主题均已配置,按需调参即可。
图层架构
详见 doc/LAYERS.md。
所有主题 (53)
| 主题 | 名称 | 风格 |
|---|---|---|
autumn |
Autumn | 秋日橙红 |
blueprint |
Blueprint | 建筑蓝图 |
brutalist_concrete |
Brutalist Concrete | 粗野主义 |
carbon_fiber |
Carbon Fiber | 碳纤维黑 |
contrast_zones |
Contrast Zones | 高对比度 |
copper_patina |
Copper Patina | 铜绿氧化 |
cotton_candy |
Cotton Candy | 棉花糖粉紫 |
cyberpunk_neon |
Cyberpunk Neon | 赛博朋克 |
desert_rose |
Desert Rose | 沙漠玫瑰 |
emerald |
Emerald City | 翡翠绿 |
forest |
Forest | 森林绿 |
forest_moss |
Forest Moss | 苔藓绿金 |
gilded_noir |
Gilded Noir | 黑金奢华 |
glitch_purple |
Glitch Purple | 故障紫绿 |
gongqiang |
宫墙 Gongqiang | 红底鎏金 |
gradient_roads |
Gradient Roads | 渐变道路 |
japanese_ink |
Japanese Ink | 日式水墨 |
lavender_mist |
Lavender Mist | 薰衣草雾 |
matcha_latte |
Matcha Latte | 抹茶拿铁 |
mediterranean_summer |
Mediterranean Summer | 地中海蓝橙 |
mediterranean_summer_plus |
Mediterranean Summer + Rail | 地中海+铁路 |
midnight_blue |
Midnight Blue | 午夜蓝金 |
monochrome_blue |
Monochrome Blue | 单色蓝 |
neon_cyberpunk |
Neon Cyberpunk | 霓虹赛博朋克 |
noir |
Noir | 纯黑白 |
nordic_frost |
Nordic Frost | 北欧冰霜 |
ocean |
Ocean | 海洋蓝 |
ocean_abyss |
Ocean Abyss | 深海深渊 |
pastel_dream |
Pastel Dream | 梦幻粉彩 |
qingzhuan |
青砖 Qingzhuan | 胡同灰砖 |
red_alert |
Red Alert | 红色警报 |
royal_velvet |
Royal Velvet | 皇家天鹅绒 |
sakura_branch |
Sakura Branch | 樱花粉 |
shuimo |
水墨 Shuimo | 水墨白底 |
solarized_dark |
Solarized Dark | Solarized 暗色 |
sulfur_slate |
Sulfur & Slate | 硫磺金灰 |
sunset |
Sunset | 落日橙粉 |
terra_clay |
Terra Clay | 陶土暖色 |
terracotta |
Terracotta | 地中海陶 |
vintage_nautical |
Vintage Nautical | 复古航海 |
warm_beige |
Warm Beige | 暖米色 |
Credit
Forked from maptoposter by Ankur Gupta. MIT License.
SinoGDB data derived from OpenStreetMap, processed by QGIS.
Metadata
Release files for cityposter 0.2.13
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cityposter-0.2.13.tar.gz | 77.9 kB | Without provenance | Details for cityposter-0.2.13.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cityposter-0.2.13-py3-none-any.whl | Python 3 | none | any | Details for cityposter-0.2.13-py3-none-any.whl |
Total release size: 159.2 kB
Release files / cityposter-0.2.13.tar.gz
| Download URL | cityposter-0.2.13.tar.gz |
|---|---|
| Size | 77.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2c90b20de8e0a0c6fb5901271b7dbe2a38ff118915e7dd8eaeb824756be5e739
|
|
BLAKE2b-256 checksum How to use checksums |
a4a3570261feb05b6e02aca9d4f37e58ca39aa1e16f350bcc56981b28115222e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / cityposter-0.2.13-py3-none-any.whl
| Download URL | cityposter-0.2.13-py3-none-any.whl |
|---|---|
| Size | 81.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a455613ffd823cb10951256a4d34bb5091d0cce507fe374d733c26d8188402a8
|
|
BLAKE2b-256 checksum How to use checksums |
cde0e94a076d4ccb3c83977465c90648e649c3f61c4c526a0dffcfaf15c0241d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for cityposter 0.2.13
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.