#!/usr/bin/env python3 """生成并部署福冈湾 20 海里 NewPec / MSIL 对比页所需静态资产。""" from __future__ import annotations import json import shutil from pathlib import Path ROOT = Path(__file__).resolve().parent WEB_ROOT = Path("/mnt/sda1/www/newpec") MSIL_ROOT = Path("/root/sourceserver/seaknow/msil_fukuoka_pbf") STYLE_ROOT = Path("/root/sourceserver/seaknow/msil_sprite_style_v1") LEFT_CACHE = WEB_ROOT / "exported_auto/tile.mapple-on.jp__newpec-mvt-20251001__z___x___y_.pbf/tiles" LEFT_TILES = "http://192.168.200.184/newpec/exported_auto/tile.mapple-on.jp__newpec-mvt-20251001__z___x___y_.pbf/tiles/{z}/{x}/{y}.pbf" RIGHT_TILES = "http://192.168.200.184/newpec/msil-fukuoka-20nm/pbf/{z}/{x}/{y}.pbf" TIDE_TILES = "http://192.168.200.184/newpec/exported_auto/tile.mapple-on.jp__tide-mvt__z___x___y_.pbf/tiles/{z}/{x}/{y}.pbf" ENGAN_TILES = "http://192.168.200.184/newpec/exported_auto/tile.mapple-on.jp__engan-mvt__z___x___y_.pbf/tiles/{z}/{x}/{y}.pbf" MAPPLE_TILES = "http://192.168.200.184/newpec/exported_auto/tile.mapple-on.jp__mapple_a_vlight__z___x___y_.png/tiles/{z}/{x}/{y}.png" OLD_SPRITE = "https://tile.mapple-on.jp/newpec-symbols-20251001/sprite" OLD_GLYPHS = "https://tile.mapple-on.jp/glyphs/{fontstack}/{range}.pbf" LOCAL_SEMANTIC_SPRITE = "http://192.168.200.184/newpec/sprite-semantic/sprite" def load_json(path: Path) -> dict: return json.loads(path.read_text(encoding="utf-8")) def write_json(value: dict, filename: str) -> None: for directory in (ROOT / "src/pbf", WEB_ROOT / "domain"): directory.mkdir(parents=True, exist_ok=True) (directory / filename).write_text( json.dumps(value, ensure_ascii=False, indent=2) + "\n", encoding="utf-8" ) def build_local_newpec_style() -> dict: style = load_json(WEB_ROOT / "style.json") style["name"] = "NewPec 福冈湾 20 海里本地缓存海图(20251001)" style["sprite"] = OLD_SPRITE style["glyphs"] = OLD_GLYPHS style["sources"]["newpec"]["tiles"] = [LEFT_TILES] style["sources"]["newpec"]["maxzoom"] = 9 style["sources"]["tide"]["tiles"] = [TIDE_TILES] style["sources"]["engan"]["tiles"] = [ENGAN_TILES] style["sources"]["mapple"]["tiles"] = [MAPPLE_TILES] return style def build_left_style() -> dict: # 必须与 navsea-compare-kyushu-semantic-icon-v1.html 的左侧完全一致。 return load_json(ROOT / "src/pbf/style.navsea-newpec-kyushu-icon-test-v1.json") def build_right_style() -> dict: # 复用已验证可显示的 GSI 陆地底图;海图对象仅来自 MSIL PBF。 base = build_left_style() msil = load_json(STYLE_ROOT / "msil_fukuoka_standalone_style.json") base["name"] = "MSIL 福冈湾 20 海里海图(MSIL PBF + 本地陆地底图)" base["sprite"] = LOCAL_SEMANTIC_SPRITE base["sources"] = { key: value for key, value in base["sources"].items() if key == "mapple" } base["sources"]["msil-fukuoka"] = msil["sources"]["msil-fukuoka"] base["sources"]["msil-fukuoka"]["tiles"] = [RIGHT_TILES] base["layers"] = [ layer for layer in base["layers"] if "source" not in layer or layer["source"] == "mapple" ] overlay_layers = [layer for layer in msil["layers"] if layer["type"] != "background"] for layer in overlay_layers: if layer["id"] == "msil-fixed-fishery-area-fill": layer["paint"] = { "fill-pattern": "fill-daytime-900", "fill-opacity": 0.9, } elif layer["id"] == "msil-depth-contour": layer["paint"] = { "line-color": [ "match", ["get", "depth_m"], 20, "#6acfff", 50, "#4f9fd0", "#62bde8", ], "line-width": [ "match", ["get", "depth_m"], 20, 1.4, 50, 1.1, 1, ], "line-opacity": 1, } overlay_layers.append({ "id": "msil-depth-contour-label", "type": "symbol", "source": "msil-fukuoka", "source-layer": "depth_contour", "minzoom": 8, "maxzoom": 24, "layout": { "symbol-placement": "line", "symbol-spacing": 220, "text-field": ["to-string", ["coalesce", ["get", "depth_m"], ["get", "Depth"], ""]], "text-font": ["NotoSansCJK-Regular"], "text-size": ["interpolate", ["linear"], ["zoom"], 8, 9, 12, 11, 16, 12], "text-allow-overlap": True, "text-ignore-placement": True, "text-rotation-alignment": "viewport", }, "paint": { "text-color": "#172b3a", "text-halo-color": "rgba(255,255,255,0.88)", "text-halo-width": 1.2, }, }) base["layers"].extend(overlay_layers) return base def deploy_msil_tiles() -> None: source = MSIL_ROOT / "output/pbf" target = WEB_ROOT / "msil-fukuoka-20nm/pbf" if not source.is_dir(): raise FileNotFoundError(source) target.parent.mkdir(parents=True, exist_ok=True) shutil.copytree(source, target, dirs_exist_ok=True) shutil.copy2(MSIL_ROOT / "output/coverage_20nm.geojson", target.parent / "coverage_20nm.geojson") shutil.copy2(MSIL_ROOT / "output/manifest.json", target.parent / "manifest.json") def main() -> None: if not LEFT_CACHE.is_dir(): raise FileNotFoundError(f"未找到左侧 NewPec 缓存瓦片目录:{LEFT_CACHE}") write_json(build_left_style(), "style.newpec-fukuoka-20nm-cache-20251001.json") write_json(build_right_style(), "style.msil-fukuoka-20nm-v1.json") deploy_msil_tiles() print("已生成 source 与 domain 样式,并部署 MSIL 福冈湾 20 海里瓦片。") if __name__ == "__main__": main()