feat: finalize Kyushu S-52 0.4.12 release
This commit is contained in:
@@ -44,6 +44,7 @@
|
|||||||
{"name": "facility_boundary_area", "capabilities": ["fill", "line", "symbol", "text"]},
|
{"name": "facility_boundary_area", "capabilities": ["fill", "line", "symbol", "text"]},
|
||||||
{"name": "facility_boundary_outline", "capabilities": ["line", "symbol", "text"]},
|
{"name": "facility_boundary_outline", "capabilities": ["line", "symbol", "text"]},
|
||||||
{"name": "facility_boundary_point", "capabilities": ["symbol", "text"]},
|
{"name": "facility_boundary_point", "capabilities": ["symbol", "text"]},
|
||||||
|
{"name": "fixed_fishing_gear_area", "capabilities": ["fill", "line", "symbol", "text"]},
|
||||||
{"name": "land_area", "capabilities": ["fill", "line", "symbol", "text"]},
|
{"name": "land_area", "capabilities": ["fill", "line", "symbol", "text"]},
|
||||||
{"name": "navigation_hazard_area", "capabilities": ["fill", "line", "symbol", "text"]},
|
{"name": "navigation_hazard_area", "capabilities": ["fill", "line", "symbol", "text"]},
|
||||||
{"name": "navigation_hazard_outline", "capabilities": ["line", "symbol", "text"]},
|
{"name": "navigation_hazard_outline", "capabilities": ["line", "symbol", "text"]},
|
||||||
|
|||||||
270
docs/报告/CM95_S52_0.4.12_OpenCPN覆盖与危险物修复报告_v1.md
Normal file
270
docs/报告/CM95_S52_0.4.12_OpenCPN覆盖与危险物修复报告_v1.md
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
# CM95 S-52 0.4.12 OpenCPN 覆盖与危险物修复报告 v1
|
||||||
|
|
||||||
|
日期:2026-09-20
|
||||||
|
|
||||||
|
## 1. 结论
|
||||||
|
|
||||||
|
CM95 九州 S-52 0.4.12 已完成新的全量 PBF 生产、Source→PBF presentation conservation 审计、release finalize、release-scoped S-52 style 编译、runtime capability 审计以及实际浏览器回归。
|
||||||
|
|
||||||
|
正式 Release:
|
||||||
|
|
||||||
|
`cm95-d1-62a85bd40d3a-57e72826db1d`
|
||||||
|
|
||||||
|
Builder Contract:
|
||||||
|
|
||||||
|
`cm95pbf-builder/0.4.12-opencpn-cm93-coverage`
|
||||||
|
|
||||||
|
Production Pipeline:
|
||||||
|
|
||||||
|
`cm95pbf-production/2.3-opencpn-cm93-coverage`
|
||||||
|
|
||||||
|
Plan ID:
|
||||||
|
|
||||||
|
`57e72826db1d3e3e69f0b3b084bef4fb9469b5edc47dc0030fc2ec3e46adecf9`
|
||||||
|
## 2. 本阶段修复
|
||||||
|
|
||||||
|
### 2.1 M_COVR 语义
|
||||||
|
|
||||||
|
Builder 的 coverage 选择改为与 OpenCPN CM93 quilt 语义一致:
|
||||||
|
|
||||||
|
- 只有显式 `M_COVR` / `chart_coverage` 几何可以定义有效 chart coverage;
|
||||||
|
- 不再在 cell 缺少 M_COVR 时,把 `chart_cell bbox` 当成 coverage;
|
||||||
|
- 避免空或不完整的高细节 cell 用整个索引 bbox 错误遮挡较粗尺度内容;
|
||||||
|
- 独立 Source→PBF 守恒审计器同步采用同一 coverage 语义,避免 audit scope 与 Builder 分叉。
|
||||||
|
|
||||||
|
### 2.2 FSHHAV → FSHFAC
|
||||||
|
|
||||||
|
按 OpenCPN CM93 `CreateS57Obj()` 的类替换规则:
|
||||||
|
|
||||||
|
`FSHHAV → FSHFAC`
|
||||||
|
|
||||||
|
修正 Delivery mapping:
|
||||||
|
|
||||||
|
- FSHHAV AREA → `fixed_fishing_gear_area`
|
||||||
|
- FSHHAV POINT → `s52_points`
|
||||||
|
- 保留 S-52 `FSHHAV02` area pattern / dashed line;
|
||||||
|
- 保留 S-52 `FSHHAV01` point symbol;
|
||||||
|
- 不再把 FSHHAV 错误表达成 `fish_reef`。
|
||||||
|
|
||||||
|
全新 Release 扫描结果:
|
||||||
|
|
||||||
|
- `fixed_fishing_gear_area` 中 FSHFAC occurrence:769
|
||||||
|
- `s52_points` 中 FSHFAC occurrence:4022
|
||||||
|
- 新 FSHFAC layer 中 `fish_reef` occurrence:0
|
||||||
|
|
||||||
|
### 2.3 OBSTRN04 / WRECKS02 点危险物 Runtime
|
||||||
|
|
||||||
|
Web compare 增加 point runtime renderer,读取 PBF 中 mariner-neutral runtime facts,在当前 mariner defaults 下动态选择 S-52 symbol。
|
||||||
|
|
||||||
|
当前支持的 point symbol 包括:
|
||||||
|
|
||||||
|
- `ISODGR51`
|
||||||
|
- `DANGER01 / DANGER51 / DANGER52`
|
||||||
|
- `UWTROC03 / UWTROC04`
|
||||||
|
- `OBSTRN01 / OBSTRN03 / OBSTRN11`
|
||||||
|
- `WRECKS01 / WRECKS04 / WRECKS05`
|
||||||
|
- `LNDARE01`
|
||||||
|
|
||||||
|
OpenCPN `OBSTRN04` 可引用但 chartsymbols 中不存在的 `DANGER53` 继续 fail-closed,不自行创造替代资源。
|
||||||
|
|
||||||
|
当前 OBSTRN/WRECKS runtime capability 定义为 `PREVIEW_ONLY`,因为 point symbol 已实现,但 AREA/LINE 最终 runtime portrayal 仍未完成。
|
||||||
|
## 3. Production 结果
|
||||||
|
|
||||||
|
- planned jobs:5065
|
||||||
|
- PASS:5065
|
||||||
|
- FAILED:0
|
||||||
|
- PBF files:5064
|
||||||
|
- reports:5065
|
||||||
|
- explicit empty tile:1
|
||||||
|
- planned output features:476120
|
||||||
|
- report output features:476120
|
||||||
|
- decoded PBF features:476120
|
||||||
|
- tile footprint contract:PASS
|
||||||
|
- S-52 resource contract:PASS
|
||||||
|
- resource defined:1107
|
||||||
|
- resource active:977
|
||||||
|
- S-52 runtime data contract:PASS
|
||||||
|
- release failures:[]
|
||||||
|
|
||||||
|
Runtime CSP counts:
|
||||||
|
|
||||||
|
- DEPARE01:47516
|
||||||
|
- DEPCNT02:46189
|
||||||
|
- OBSTRN04:45633
|
||||||
|
- SOUNDG02:146728
|
||||||
|
- WRECKS02:909
|
||||||
|
## 4. Multi-LIGHTS 与 Presentation Conservation
|
||||||
|
|
||||||
|
Release finalize 的 multi-light contract:
|
||||||
|
|
||||||
|
- required:true
|
||||||
|
- status:PASS
|
||||||
|
- report multi-light groups:357
|
||||||
|
- PBF multi-light groups:357
|
||||||
|
- report light presentation records:745
|
||||||
|
- PBF light presentation records:745
|
||||||
|
- failure count:0
|
||||||
|
|
||||||
|
0.4.12 最初 finalize 时因版本判断仍只匹配 `0.4.11-s52-multi-light-presentations` 字符串,曾把该 contract 错误标为 NOT_APPLICABLE。
|
||||||
|
|
||||||
|
已修正为使用 `_builder_contract_at_least(..., (0,4,11))`,重新 finalize 后 0.4.12 正确执行 multi-light 硬门槛并 PASS。
|
||||||
|
|
||||||
|
独立 Source→PBF presentation conservation:
|
||||||
|
|
||||||
|
- expected multi-light groups:187
|
||||||
|
- actual multi-light groups:187
|
||||||
|
- expected presentation records:390
|
||||||
|
- actual presentation records:390
|
||||||
|
- missing:0
|
||||||
|
- unexpected:0
|
||||||
|
- signature mismatch:0
|
||||||
|
- tile occurrence presentation drift:0
|
||||||
|
- tile occurrence scope mismatch:0
|
||||||
|
- source resolution failure:0
|
||||||
|
- PBF parse failure:0
|
||||||
|
- failures:[]
|
||||||
|
|
||||||
|
Artifact:
|
||||||
|
|
||||||
|
`build/audits/cm95_s52_kyushu_v4_presentation_conservation.json`
|
||||||
|
|
||||||
|
Manifest 中该 contract 状态:PASS。
|
||||||
|
## 5. Release-scoped S-52 Style
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
`build/s52_style_compiler_release_57e72826db1d/style.s52.json`
|
||||||
|
|
||||||
|
第一次编译正确发现新 source layer 尚未进入 compiler contract:
|
||||||
|
|
||||||
|
- `SOURCE_LAYER_CONTRACT_GAP: fixed_fishing_gear_area`
|
||||||
|
- AP materialized coverage gap:769
|
||||||
|
- LS materialized coverage gap:769
|
||||||
|
|
||||||
|
这证明 PBF 已有 FSHFAC area presentation facts,但完整 style 尚未消费该新 layer。
|
||||||
|
|
||||||
|
修复:
|
||||||
|
|
||||||
|
`config/s52/cm95_s52_style_compiler_v1.json`
|
||||||
|
|
||||||
|
加入:
|
||||||
|
|
||||||
|
`fixed_fishing_gear_area: fill / line / symbol / text`
|
||||||
|
|
||||||
|
重新编译结果:
|
||||||
|
|
||||||
|
- hard_gate_failures:[]
|
||||||
|
- resource contract:PASS
|
||||||
|
- compiled layers:140
|
||||||
|
- PBF count:5064
|
||||||
|
- feature count:476120
|
||||||
|
- AP gap:0
|
||||||
|
- LS gap:0
|
||||||
|
- style bytes:1549579
|
||||||
|
|
||||||
|
因此 FSHFAC area 不再只是“PBF 有数据”,完整 S-52 style 也已实际消费 AP/LS presentation。
|
||||||
|
## 6. Runtime Capability Audit
|
||||||
|
|
||||||
|
CA 单项:
|
||||||
|
|
||||||
|
- RUNTIME_CA feature count:1276
|
||||||
|
- status:IMPLEMENTED
|
||||||
|
- fidelity:S52_SCREEN_MM
|
||||||
|
- audit:PASS
|
||||||
|
|
||||||
|
Artifact:
|
||||||
|
|
||||||
|
`build/audits/cm95_s52_kyushu_v4_runtime_ca_capability.json`
|
||||||
|
|
||||||
|
完整 Web target strict audit:
|
||||||
|
|
||||||
|
- RUNTIME_CA:IMPLEMENTED
|
||||||
|
- RUNTIME_DEPARE:PREVIEW_ONLY
|
||||||
|
- RUNTIME_DEPCNT:PREVIEW_ONLY
|
||||||
|
- RUNTIME_SOUNDG:PREVIEW_ONLY
|
||||||
|
- RUNTIME_OBSTRN:PREVIEW_ONLY
|
||||||
|
- RUNTIME_WRECKS:PREVIEW_ONLY
|
||||||
|
|
||||||
|
因此 full runtime capability audit 仍为:
|
||||||
|
|
||||||
|
`FAIL — runtime_capability_not_implemented`
|
||||||
|
|
||||||
|
这是预期且正确的严格结果,不影响 Data Release PASS,也不得据此声称当前 Web compare 已实现完整 S-52 runtime parity。
|
||||||
|
|
||||||
|
Artifact:
|
||||||
|
|
||||||
|
`build/audits/cm95_s52_kyushu_v4_web_runtime_capability.json`
|
||||||
|
## 7. 实际浏览器回归
|
||||||
|
|
||||||
|
### 7.1 OBSTRN / WRECKS
|
||||||
|
|
||||||
|
测试位置约:
|
||||||
|
|
||||||
|
`130.277626E, 33.692775N`
|
||||||
|
|
||||||
|
真实 Chrome + MapLibre:
|
||||||
|
|
||||||
|
- Production v4 / 0.4.12 页面已加载
|
||||||
|
- `runtime-preview-hazard-symbols` layer 存在
|
||||||
|
- cm95 source loaded
|
||||||
|
- queryRenderedFeatures:38
|
||||||
|
- 实际出现的 runtime symbols 包括:
|
||||||
|
- DANGER51
|
||||||
|
- UWTROC03
|
||||||
|
- UWTROC04
|
||||||
|
- `leftMap.isStyleLoaded() = true`
|
||||||
|
|
||||||
|
截图:
|
||||||
|
|
||||||
|
`/tmp/cm95_v4_hazard_runtime.png`
|
||||||
|
|
||||||
|
### 7.2 Multi-LIGHTS / CA
|
||||||
|
|
||||||
|
测试位置:
|
||||||
|
|
||||||
|
`130.78248061577605E, 34.09885081506925N`
|
||||||
|
|
||||||
|
实际 runtime 仍得到两条 sector:
|
||||||
|
|
||||||
|
- source record 3077:LITYW,66° → 106°
|
||||||
|
- source record 3078:LITYW,116° → 320°
|
||||||
|
|
||||||
|
Canvas non-transparent pixels:4427。
|
||||||
|
|
||||||
|
因此 0.4.12 coverage / FSHFAC 修正没有破坏 0.4.11 已通过的 multi-LIGHTS / CA 闭环。
|
||||||
|
## 8. 18888
|
||||||
|
|
||||||
|
比较服务器已经切换到:
|
||||||
|
|
||||||
|
`cm95-d1-62a85bd40d3a-57e72826db1d`
|
||||||
|
|
||||||
|
Release-scoped style:
|
||||||
|
|
||||||
|
`build/s52_style_compiler_release_57e72826db1d/style.s52.json`
|
||||||
|
|
||||||
|
页面标识:
|
||||||
|
|
||||||
|
`Production v4 / 0.4.12`
|
||||||
|
|
||||||
|
当前 `/health`:
|
||||||
|
|
||||||
|
- release_status:PASS
|
||||||
|
- pbf_file_count:5064
|
||||||
|
- decoded_pbf_features:476120
|
||||||
|
- s52_runtime_contract:PASS
|
||||||
|
- s52_light_presentation_contract:PASS
|
||||||
|
- s52_presentation_conservation_contract:PASS
|
||||||
|
|
||||||
|
Style / sprite 资源均返回 HTTP 200。
|
||||||
|
|
||||||
|
## 9. 剩余边界
|
||||||
|
|
||||||
|
0.4.12 Data Release 已可正式使用。
|
||||||
|
|
||||||
|
仍未完成的是完整 runtime portrayal,而不是 PBF 数据 release:
|
||||||
|
|
||||||
|
- DEPARE / DEPCNT:仍为默认 mariner settings preview
|
||||||
|
- SOUNDG:仍未实现完整 S-52 glyph composition
|
||||||
|
- OBSTRN / WRECKS:当前只完成 Point symbol runtime,AREA/LINE pending
|
||||||
|
|
||||||
|
因此下一阶段如继续追求与 OpenCPN 的完整视觉一致性,应优先完成上述 runtime CSP,而不是再次重建当前 0.4.12 PBF。
|
||||||
@@ -440,8 +440,8 @@ def finalize_release(
|
|||||||
s52_runtime_leaks = Counter()
|
s52_runtime_leaks = Counter()
|
||||||
s52_runtime_fact_counts = Counter()
|
s52_runtime_fact_counts = Counter()
|
||||||
s52_runtime_unknown_fact_exceptions = Counter()
|
s52_runtime_unknown_fact_exceptions = Counter()
|
||||||
light_presentation_required = str(plan.get("builder_contract_version") or "").startswith(
|
light_presentation_required = _builder_contract_at_least(
|
||||||
"cm95pbf-builder/0.4.11-s52-multi-light-presentations"
|
plan.get("builder_contract_version"), (0, 4, 11)
|
||||||
)
|
)
|
||||||
pbf_multi_light_groups = 0
|
pbf_multi_light_groups = 0
|
||||||
pbf_light_presentation_records = 0
|
pbf_light_presentation_records = 0
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="toolbar">
|
<div id="toolbar">
|
||||||
<strong>九州 S-52 PBF 对比</strong>
|
<strong>九州 S-52 PBF 对比</strong>
|
||||||
<span class="meta">左:Production v3 / 0.4.11 本地 PBF 右:extentfix 原始数据源</span>
|
<span class="meta">左:Production v4 / 0.4.12 本地 PBF 右:extentfix 原始数据源</span>
|
||||||
<label><input id="sync-toggle" type="checkbox" checked />同步视图</label>
|
<label><input id="sync-toggle" type="checkbox" checked />同步视图</label>
|
||||||
<button id="reset-btn" type="button">重置九州</button>
|
<button id="reset-btn" type="button">重置九州</button>
|
||||||
<button id="debug-toggle-btn" type="button">调试</button>
|
<button id="debug-toggle-btn" type="button">调试</button>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
<section class="pane" id="left-pane">
|
<section class="pane" id="left-pane">
|
||||||
<div id="left-map" class="map"></div>
|
<div id="left-map" class="map"></div>
|
||||||
<canvas id="left-ca-overlay" class="ca-overlay" aria-hidden="true"></canvas>
|
<canvas id="left-ca-overlay" class="ca-overlay" aria-hidden="true"></canvas>
|
||||||
<div class="pane-title"><b>左:九州 Production v3 / 0.4.11</b><span id="left-state" class="state">等待参考 style…</span></div>
|
<div class="pane-title"><b>左:九州 Production v4 / 0.4.12</b><span id="left-state" class="state">等待参考 style…</span></div>
|
||||||
<div id="left-inspector" class="inspector empty">点击任一侧海图,对比同一位置的 Feature。</div>
|
<div id="left-inspector" class="inspector empty">点击任一侧海图,对比同一位置的 Feature。</div>
|
||||||
<div class="divider-label">LOCAL</div>
|
<div class="divider-label">LOCAL</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -598,8 +598,8 @@ function cloneReferenceForLocal(referenceStyle){
|
|||||||
source.minzoom=5;
|
source.minzoom=5;
|
||||||
source.maxzoom=12;
|
source.maxzoom=12;
|
||||||
source.bounds=[128.0,29.5,132.5,34.8];
|
source.bounds=[128.0,29.5,132.5,34.8];
|
||||||
source.attribution="CM95 九州 S-52 Production 0.4.11 multi-light";
|
source.attribution="CM95 九州 S-52 Production 0.4.12 OpenCPN coverage";
|
||||||
style.name=(style.name || "NavSea") + " / Kyushu Production v3 / 0.4.11";
|
style.name=(style.name || "NavSea") + " / Kyushu Production v4 / 0.4.12";
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,7 +612,7 @@ function prepareS52Style(raw){
|
|||||||
source.minzoom=5;
|
source.minzoom=5;
|
||||||
source.maxzoom=12;
|
source.maxzoom=12;
|
||||||
source.bounds=[128.0,29.5,132.5,34.8];
|
source.bounds=[128.0,29.5,132.5,34.8];
|
||||||
source.attribution="CM95 九州 S-52 Production 0.4.11 multi-light";
|
source.attribution="CM95 九州 S-52 Production 0.4.12 OpenCPN coverage";
|
||||||
style.sprite=location.origin + "/s52/sprite";
|
style.sprite=location.origin + "/s52/sprite";
|
||||||
if(referenceStyleTemplate && referenceStyleTemplate.glyphs){
|
if(referenceStyleTemplate && referenceStyleTemplate.glyphs){
|
||||||
style.glyphs=referenceStyleTemplate.glyphs;
|
style.glyphs=referenceStyleTemplate.glyphs;
|
||||||
@@ -670,9 +670,9 @@ leftMap.on("style.load",function(){
|
|||||||
const sources=Object.keys((leftMap.getStyle() || {}).sources || {});
|
const sources=Object.keys((leftMap.getStyle() || {}).sources || {});
|
||||||
if(sources.includes("cm95")){
|
if(sources.includes("cm95")){
|
||||||
installRuntimePreviewLayers(leftMap);
|
installRuntimePreviewLayers(leftMap);
|
||||||
setState(leftState,"Production v3 / 0.4.11 / S-52 style" + (debugRuntimePreview.checked ? " + runtime preview" : ""),"ok");
|
setState(leftState,"Production v4 / 0.4.12 / S-52 style" + (debugRuntimePreview.checked ? " + runtime preview" : ""),"ok");
|
||||||
}else if(sources.includes("navsea_delivery")){
|
}else if(sources.includes("navsea_delivery")){
|
||||||
setState(leftState,"Production v3 / 0.4.11 / extentfix style","ok");
|
setState(leftState,"Production v4 / 0.4.12 / extentfix style","ok");
|
||||||
}
|
}
|
||||||
applyDebugStyles();
|
applyDebugStyles();
|
||||||
refreshLightArcFeatures();
|
refreshLightArcFeatures();
|
||||||
@@ -733,7 +733,7 @@ debugLeftS52.addEventListener("change",function(){
|
|||||||
debugRuntimePreview.addEventListener("change",function(){
|
debugRuntimePreview.addEventListener("change",function(){
|
||||||
if(leftMap.getSource("cm95")){
|
if(leftMap.getSource("cm95")){
|
||||||
installRuntimePreviewLayers(leftMap);
|
installRuntimePreviewLayers(leftMap);
|
||||||
setState(leftState,"Production v3 / 0.4.11 / S-52 style" + (debugRuntimePreview.checked ? " + runtime preview" : ""),"ok");
|
setState(leftState,"Production v4 / 0.4.12 / S-52 style" + (debugRuntimePreview.checked ? " + runtime preview" : ""),"ok");
|
||||||
applyDebugStyles();
|
applyDebugStyles();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
RELEASE_ID = "cm95-d1-62a85bd40d3a-1c27f0a66f6b"
|
RELEASE_ID = "cm95-d1-62a85bd40d3a-57e72826db1d"
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
@@ -28,7 +28,7 @@ def main():
|
|||||||
manifest_path = release_dir / "release_manifest_v1.json"
|
manifest_path = release_dir / "release_manifest_v1.json"
|
||||||
html_path = web_root / "kyushu_compare.html"
|
html_path = web_root / "kyushu_compare.html"
|
||||||
assets_root = project_root / "build" / "fukuoka_s52_web" / "site" / "assets"
|
assets_root = project_root / "build" / "fukuoka_s52_web" / "site" / "assets"
|
||||||
s52_style_path = project_root / "build" / "s52_style_compiler_release_1c27f0a66f6b" / "style.s52.json"
|
s52_style_path = project_root / "build" / "s52_style_compiler_release_57e72826db1d" / "style.s52.json"
|
||||||
s52_sprite_root = project_root / "build" / "s52_resources_v2" / "final"
|
s52_sprite_root = project_root / "build" / "s52_resources_v2" / "final"
|
||||||
|
|
||||||
required = [
|
required = [
|
||||||
|
|||||||
Reference in New Issue
Block a user