Files
CM95/docs/CM95_S52_NavSea运行时呈现契约_v1.md
2026-09-19 15:56:37 +08:00

258 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CM95 S-52 NavSea 运行时呈现契约 v1
## 1. 目标
本契约定义 NavSea 如何消费 CM95 Delivery PBF 中的 S-52 海图事实,并在用户修改水深、安全等深线或颜色设置后立即重新呈现,而不重新生成、下载或替换 PBF。
本契约只规定数据与算法责任边界,不在 CM95 Server 中实现 NavSea UI,也不把 NavSea Store/业务生命周期引入 PBF Builder。
## 2. 总体责任
### CM95/PBF 负责
- 几何;
- 原始水深事实的规范化数值;
- Lookup identity 与静态 S-52 Presentation 提示;
- 与用户设置无关的属性派生;
- runtime CSP 所需的最小事实;
- 不可从单个 Feature 自身恢复的必要空间上下文摘要。
### NavSea Runtime 负责
- 当前用户的水深颜色设置;
- `shallowContour / safetyContour / safetyDepth / deepContour`;
- `twoShades`;
- safety contour 实际选择;
- SOUNDG 深/浅字形;
- OBSTRN/WRECKS isolated danger;
- isolated danger 引起的 DisplayBase / priority promotion;
- 设置变化后的即时重算和 MapLibre style 更新。
## 3. Runtime Settings
建议 NavSea 运行时形成一个统一的只读快照,例如:
```text
S52MarinerRuntimeSettings
shallowContourM
safetyContourM
safetyDepthM
deepContourM
twoShades
depthColorRules
```
`depthColorRules` 属于 NavSea 现有的用户自定义显示能力,可以独立于 S-52 四个标准深度阈值。服务器不得把用户颜色写入 PBF。
一次重算必须使用同一个 settings snapshot,避免 DEPARE、DEPCNT、SOUNDG 与 hazard 在同一帧使用不同设置。
## 4. PBF Runtime 字段
### DEPARE / DRGARE
主要字段:
- `depth_min_m`
- `depth_max_m`
- `s52_runtime_csp = DEPARE01 | DEPARE02`
`chart_fill_style` 仅作为当前 NavSea 既有 style 的兼容语义,不应覆盖精确 `depth_min_m/depth_max_m` 的事实地位。
### DEPCNT
主要字段:
- `contour_depth_m`
- `least_depth_m`(兼容)
- `s52_runtime_csp = DEPCNT02`
- `s52_quapos_code`(有值时)
### SOUNDG
主要字段:
- `depth_value_m`
- `s52_sounding_depth_m`
- `s52_sounding_swept`
- `s52_sounding_low_quality`
- `s52_runtime_csp = SOUNDG02`
### OBSTRN / UWTROC / WRECKS
主要字段:
- `s52_hazard_depth_m`
- `s52_surrounding_max_drval1_m`
- `s52_surrounding_min_drval2_m`
- `s52_watlev_code`
- `s52_expsou_code`
- `s52_catobs_code`
- `s52_catwrk_code`
- `s52_quapos_code`
- `s52_quasou_codes`
- `s52_tecsou_codes`
- `s52_status_codes`
- `s52_runtime_csp = OBSTRN04 | WRECKS02`
数组类 code 在 Delivery MVT 中以 JSON 字符串保存,NavSea Adapter 负责一次标准化解析,不由 MapLibre style 直接解析 JSON。
## 5. DEPARE 运行时规则
NavSea 可以有两层规则:
1. 用户自定义 `depthColorRules` 优先决定颜色;
2. 未启用自定义颜色时,可按 S-52 `DEPARE01/02` 的 shallow/safety/deep/twoShades 规则得到标准颜色角色。
颜色计算以 PBF 的精确 `depth_min_m/depth_max_m` 为输入。用户修改阈值只改变已有 DEPARE polygon 的显示,不生成原海图不存在的新等深边界,也不在客户端重新切割 polygon。
因此,例如原始海图区间为 `5–10m`,用户将颜色阈值设为 `7m`,NavSea 可以按规则重新给整个 `5–10m` 区域着色,但不能假装原数据中存在一条精确的 `7m` 面边界。
## 6. DEPCNT 与 safety contour
`contour_depth_m` 是事实;`s52_is_safety_contour` 是运行时结果。
规则语义保持:
- 若存在与 `safetyContourM` 相等的实际等深线,选该深度;
- 否则选择下一条更深的实际等深线;
- 不允许服务器把默认 `3m` 的选择永久写入 runtime PBF。
这里不能只靠单个 Feature 的 MapLibre expression 完成“下一条更深”判断,因为它需要知道可用 contour depth 集合。
NavSea Runtime 因此需要维护稳定的 `ContourCatalog`(按当前有效海图/尺度上下文的已知等深值排序),先计算:
```text
effectiveSafetyContourM = min(depth >= safetyContourM)
```
再把该值注入 DEPCNT style expression。
若当前没有足够的 ContourCatalog 信息,必须 fail-closed:不错误突出某一条线为 safety contour。后续若 Runtime 收集 catalog 的成本过高,可在 PBF 契约增加相邻等深值元数据,但 v1 不先制造新的冗余字段。
## 7. SOUNDG 运行时规则
SOUNDG 的数值深度、扫测状态和质量状态是事实;`SOUNDS* / SOUNDG*` 前缀及最终 symbol sequence 属于运行时结果。
核心规则:
```text
depth <= safetyDepthM -> shallow sounding family
otherwise -> normal sounding family
```
随后根据 swept / low-quality 和数值位数生成最终 S-52 symbol sequence。
用户修改 `safetyDepthM` 后只需重新计算当前可见 SOUNDG 的 presentation,不重新加载 PBF。
## 8. Hazard / isolated danger 运行时规则
OBSTRN/WRECKS 必须根据同一个 `safetyContourM` settings snapshot 重新执行对应 CSP。
PBF 中的 hazard depth、WATLEV、EXPSOU、QUASOU 等是输入事实;以下均为运行时输出,不能直接信任旧 tile 中的固定值:
- isolated danger yes/no;
- `ISODGR51` 等最终符号;
- DisplayBase promotion;
- Hazards priority promotion;
- hazard 内附带 sounding 的 shallow/normal 字形。
当前 PBF 已将相交 DEPARE 的必要深度摘要一起交付,避免 NavSea 为每个 hazard 再做昂贵的 polygon 空间相交。
## 9. 静态 Presentation
以下不依赖水深 mariner settings 的属性仍可直接消费 PBF 物化结果:
- LIGHTS05 静态结果;
- TOPMAR01;
- 静态 TX/TE;
- 静态 SY/LS/LC/AP/AC/CA;
- `s52_symbol_sequence` / `s52_line_sequence`;
- `s52_symbol_rotation_deg`;
- 静态 `OP` 已应用后的 `s52_display_priority`。
NavSea 不应为这些规则重复实现一套与 Server 不同的 Lookup 解释器。
## 10. MapLibre Adapter 边界
建议 NavSea 增加一个纯 Presentation Adapter,而不是把判断分散到各个 UI/Layer:
```text
PBF feature properties
+
S52MarinerRuntimeSettings snapshot
+
ContourCatalog
↓
S52RuntimePresentationAdapter
↓
normalized render properties / style expressions
↓
MapLibre
```
Adapter 不获取网络、不修改用户设置、不拥有 PBF 下载生命周期,只做确定性转换。
## 11. 设置变化
用户修改任何 mariner setting 后:
1. 形成新的 settings snapshot;
2. 更新 effective safety contour;
3. 重新生成/更新 DEPARE、DEPCNT、SOUNDG、hazard 对应 style/runtime properties;
4. 请求 MapLibre repaint;
5. 不清 tile cache,不重新下载 PBF,不重新生成 Server 数据。
禁止继续显示基于旧 settings 推导的 safety contour / isolated danger / sounding shallow 状态。
## 12. Fail-closed
- 缺少精确水深事实时,不凭颜色或旧派生字段反推水深;
- 缺少 ContourCatalog 时,不伪造 safety contour;
- hazard 所需事实不足时,保留普通危险物显示,但不错误声明 isolated danger;
- JSON code 字段解析失败时,视为空集合并记录诊断;
- 运行时设置无效时回退 NavSea 明确定义的默认 settings snapshot,而不是使用 PBF 内历史派生值。
## 13. v1 暂未纳入
`Plain / Symbolized Boundaries` 会改变 Area Lookup Table 选择,尚未完全纳入上述 runtime Adapter。第一版继续沿用当前 boundary table 编译路径;待 NavSea/Style Compiler 能同时持有 Plain 与 Symbolized 两套 Area rule 后再统一运行时切换。
## 14. 接入门槛
NavSea 正式消费 runtime PBF 前至少验证:
- 修改水深颜色不触发 PBF 网络请求;
- 修改 safety depth 后 SOUNDG 即时变化;
- 修改 safety contour 后 DEPCNT 和 hazard 使用同一个新值;
- runtime PBF 中不存在旧固定 `s52_is_safety_contour` / `s52_isolated_danger` 等结果;
- reference PBF 仍可用于 OpenCPN 对照;
- 同一设置、同一 Feature 输入必须得到确定性相同输出。
## 15. LIGHTS05 多呈现补充
同一个物理航标可能通过同一 `cell_id + _cm93_relation20_raw` 关联多条 `LIGHTS` 记录,例如不同颜色、不同扇区或不同灯质。
`navigation_marks` 仍保持“一座实体航标 = 一个主 Feature”,不得为了多个灯光记录复制实体 beacon / buoy / tower。
当同一 composite group 包含两条或以上 `LIGHTS` 时,Delivery PBF 必须增加:
- `s52_light_presentations`
该字段在 MVT 中保存为 JSON 字符串,解析后是数组。数组中每一项对应一条源 `LIGHTS`,保存该记录已经由同一 S-52 Lookup/CSP 解析出的 presentation facts,例如:
- `s52_csp_resolved=LIGHTS05`
- `s52_display_priority / s52_display_category`
- `s52_light_mode`
- `s52_light_symbol_code`
- `s52_arc_outline_color / width`
- `s52_arc_color / width`
- `s52_arc_start_deg / end_deg`
- `s52_arc_radius_mm / s52_arc_sector_radius_mm`
- `s52_light_label_text / s52_text_literal`
- `source_record_index`,仅用于同一 composite 内稳定区分各 LIGHTS presentation。
主 Feature 上原有的标量 LIGHTS 字段继续保留,用于向后兼容;它们代表当前确定性选择的主 LIGHTS presentation。Runtime 若发现 `s52_light_presentations`,必须以数组为完整集合,不得只消费主 Feature 上的单组标量字段。
`CA(...)` 的弧半径与 sector leg 半径是屏幕毫米单位,不是地理距离。Runtime renderer 负责按当前屏幕 DPI / pixel ratio 转换成屏幕像素,并按 S-52/OpenCPN 语义绘制 outline、彩色弧和 sector legs。不得把 CA 圆弧预烘焙成 PBF 地理几何。
Release finalize 在 Builder Contract `cm95pbf-builder/0.4.11-s52-multi-light-presentations` 起必须核对 build report 与 PBF 中 multi-light group / light presentation record 数量一致,并拒绝损坏、缺项或非 `LIGHTS05` 的 presentation 数组。