258 lines
9.7 KiB
Markdown
258 lines
9.7 KiB
Markdown
# 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 数组。
|