Files
pbf/tools/style-visual-object/README.md

786 lines
21 KiB
Markdown
Raw 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.
# Style Visual Object Tool
## 目标
本工具只做一件事:
> 从一份 Style JSON 以及它使用的 Sprite / Glyph 中,独立提取和生成 Visual Object。
工具输出的是匿名、可比较、可审计的 Visual Object,不负责给 Visual Object 赋予 NavSea 标准 Layer 名称,也不负责解释 Provider 的业务字段。
---
## 最重要原则:先生成 Visual Object,再做语义和 Layer 对齐
本工具必须严格遵守以下顺序:
```text
任意 Provider Style + Sprite / Glyph
↓
Style Visual Object Tool
↓
Anonymous Visual Object Catalog
↓
与 Standard Visual Object Catalog 比较
↓
MATCH / PARTIAL / UNKNOWN
↓
最后才允许赋予标准 Layer 名称或 Semantic
```
### 禁止走捷径
在 Visual Object 生成阶段,以下信息即使存在,也只能作为 provenance / audit 信息保存,**不得用于决定 Visual Object 属于哪个标准 Layer 或 Semantic**:
- `source-layer` 名称
- Style Layer `id`
- Provider 名称
- `canonical_object_type`
- S-52 / CM95 对象类名称
- S-52 symbol code 的文字含义
- 任何看起来与 NavSea 标准 Layer 同名或相似的字段
- 任何 Provider 私有业务字段名称
例如,某个 Provider 的 Style 中即使存在:
```text
source-layer = navigation_marks
```
本工具也不得因此把该 Visual Object 定义为 NavSea 的 `navigation_marks`。
它只能记录:
```text
provenance.source_layer = navigation_marks
```
真正的 Layer 名称必须在 Visual Object 生成完成后,通过与标准 Visual Object 的比较结果确定。
---
## Provider-neutral
本工具必须完全独立于具体 Provider。
同一套代码应能够处理:
- NavSea Style
- CM95 Style
- 未来 Provider B / C / D
- 任意符合支持范围的 MapLibre Style
主逻辑中禁止出现类似:
```text
if provider == "cm95"
if source_layer == "navigation_marks"
if symbol_code == "BOYCAN63" then ...
```
这类 Provider-specific Semantic 判断。
Provider-specific 名称可以进入 provenance,但不能进入 Visual Object 分类逻辑。
---
## 输入
第一阶段输入仅包括:
```text
Style JSON
Sprite JSON + PNG
Glyph(Style 使用时)
```
Visual Object 提取本身不要求读取 PBF。
如果 Style 中使用数据驱动表达式,例如:
```json
["get", "chart_icon_image"]
```
或:
```json
["get", "s52_symbol_code"]
```
工具必须保留为动态视觉参数,不得为了得到具体值去读取 PBF、猜测字段含义或套用 Provider 规则。
---
## 输出
建议至少生成:
```text
catalog.json
catalog.html
previews/
audit.json
```
其中每个 Visual Object 至少记录:
- 匿名 Visual Object ID
- geometry role
- Style Layer 原始顺序 / z-order
- 参与组成的 Render Components
- icon / line / fill / pattern / circle / text
- Sprite 实际视觉资源
- 动态视觉参数
- 出现条件 / Style filter
- 组件数量与组合关系
- Preview
- provenance
- 无法解析或无法确定的部分
---
## Visual Signature
用于后续跨 Provider 比较的核心是 Visual Signature,而不是 Provider 字段名称。
Visual Signature 应主要表达:
```text
geometry role
+
ordered render components
+
sprite visual
+
fill
+
line
+
pattern
+
text role
+
component multiplicity
+
component composition
+
style order
+
visual conditions / variants
```
后续 Visual Matcher 应基于这些视觉结构进行比较。
Provider 原始字段只作为辅助审计证据,不作为主要匹配依据。
---
## source-layer 的地位
`source-layer` 在本工具中只具有两个作用:
1. 帮助确定 Style Layer 的数据来源和可组合范围;
2. 作为 provenance / debug / audit 信息输出。
它**不是 Semantic,也不是最终 Layer 分类结果**。
不得执行:
```text
source-layer 名称
→ 直接得到 NavSea 标准 Layer
```
正确流程必须是:
```text
Style + Sprite
→ Visual Object
→ Visual Match
→ 标准 Layer / Semantic
```
---
## Standard Visual Object
NavSea 当前 Style 也必须使用同一套 Style Visual Object Tool 生成 Visual Object。
不得在 Tool 内置 NavSea Layer 规则。
NavSea 之所以成为 Standard,不是因为 Tool 对 NavSea 使用特殊逻辑,而是在 Tool 生成 Visual Object 之后,由独立的标准定义/人工确认把这些 Visual Object 与 NavSea 标准 Layer 关联起来。
因此:
```text
NavSea Style
→ Anonymous Visual Object Catalog
→ 标准确认
→ Standard Visual Object Catalog
```
其他 Provider:
```text
Provider Style
→ Anonymous Visual Object Catalog
→ 与 Standard Visual Object Catalog 比较
→ 标准 Layer
```
---
## 不属于本工具的职责
本工具不负责:
- PBF 数据读取和 Feature 实例化
- Provider 字段翻译
- CM95 专用判断
- NavSea 专用判断
- Semantic 命名
- 标准 Layer 命名
- Feature grouping
- 危险性判断
- 船舶吃水相关 Planning / Danger 判断
- 跨 Provider 的最终匹配决策
这些属于后续独立阶段或独立 Tool。
---
## 实现约束
后续实现必须满足:
- 未知 Style expression 必须显式标记 UNKNOWN / UNSUPPORTED,不得静默忽略;
- 必须保留 Style 原始顺序;
- 必须保留组件 multiplicity,不能用 set 去重破坏组合;
- 必须保留动态表达式,不得伪造成确定值;
- Sprite 必须根据 atlas metadata 提取真实视觉资源;
- 不得通过坐标接近、名字相似或 Provider 字段名自动拼接/分类 Visual Object;
- 不得因为某个 source-layer 与 NavSea 标准 Layer 同名就直接判定 MATCH;
- Visual Object 的生成和 Visual Object 的标准匹配必须是两个独立阶段。
---
## 一句话验收标准
> 给工具任意一套 Style + Sprite,即使它完全不知道这是什么 Provider、也没有任何 PBF 数据,仍然能够独立生成匿名 Visual Object Catalog;只有在该 Catalog 生成完成后,才允许进入与 NavSea Standard Visual Object Catalog 的比较和 Layer 命名阶段。
---
## NavSea Standard Visual Object Catalog 冻结规则
NavSea 的 Visual Object 与标准 Layer 名在首次完成生成、确认和命名后,应视为 Standard Visual Object Catalog 的冻结基线。
正常情况下:
```text
NavSea Anonymous Visual Object
↓
人工/标准确认 Layer 名
↓
Standard Visual Object Catalog
↓
冻结
```
冻结后,后续 CM95、Provider B、Provider C 等只能使用该 Standard Visual Object Catalog 进行 Visual Object 匹配和 Layer 命名。
除非用户明确要求重建、重新生成、修订标准或升级 Standard Catalog 版本,否则禁止:
- 每次处理新 Provider 时重新生成 NavSea Visual Object;
- 自动重新计算或改变 NavSea Visual Object ID;
- 自动改变已经确认的标准 Layer 名;
- 因 CM95 或其他 Provider 的数据特点反向修改 NavSea Standard Catalog;
- 用新的 Provider 匹配结果覆盖现有标准基线。
如果确实需要修改 Standard Visual Object Catalog,必须作为显式的标准升级处理,并保留旧版本,不得静默覆盖。
因此正常跨 Provider 工作流固定为:
```text
已冻结的 NavSea Standard Visual Object Catalog
│
│ 作为只读标准
▼
Provider Anonymous Visual Object
│
▼
Visual Matcher
│
▼
标准 Layer 命名结果
```
一句话原则:
> NavSea Standard Visual Object Catalog 是标准输入,不是每次 Provider 解析时重新生成的临时产物。
---
## Visual Object Layer Assignment 的补充硬规则
### 1. Sprite 存在不等于 Style 会绘制
Sprite atlas 中存在某个资源,只能说明资源可用,不能说明当前 Style 会实际引用它。
Anonymous Visual Object Catalog 只能从 Style 的正向可达规则生成:
```text
Style 明确允许的资源
→ 进入 Anonymous Visual Object Catalog
仅存在于 Sprite、但当前 Style 没有正向可达路径的资源
→ 不进入 Catalog
```
尤其不得把 `!match`、`!=` 等排除条件中的值误当成候选 Visual Object。
### 2. 同一视觉类可能对应多个标准 Layer
如果 NavSea Standard Visual Object Catalog 中同一实际视觉图形被多个标准 Layer 复用,则 Visual Matcher 不能仅凭图形强行选一个 Layer。
必须输出:
```text
AMBIGUOUS
candidateStandardLayers:
- layer_a
- layer_b
```
例如危险物公共符号可以同时被多个标准 Layer 使用;这种歧义是 Standard Catalog 自身的事实,不应由 Matcher 擅自消除。
### 3. 禁止整个匿名 group 继承单一 Layer
Style 的一个匿名 group 可能允许多个不同视觉家族,尤其是通用 S-52 Style。
因此禁止:
```text
group 命中一个视觉锚点
→ 整个 group 继承该 Layer
```
Layer Assignment 必须以单个 Visual Object / Visual Resource 为基本单位。
Group 只用于:
- 组合范围审计;
- Style provenance;
- 结果分布检查。
### 4. Layer Assignment 状态
正式状态固定为:
```text
MATCH
PARTIAL
AMBIGUOUS
COMPONENT
UNKNOWN
```
含义:
- `MATCH`:实际图形基本一致,可以直接作为标准 Layer 锚点;
- `PARTIAL`:不是同一完整图形,但视觉家族或组件关系足以支持唯一标准 Layer;
- `AMBIGUOUS`:视觉证据只能得到多个标准 Layer 候选,禁止强行选一个;
- `COMPONENT`:明确只是完整 Visual Object 的组成部分,不单独分配 Layer;可选记录组件类型;
- `UNKNOWN`:当前证据不足,不命名。
未知和歧义都是合法结果,禁止为了提高覆盖率而静默猜测。
---
## 人工确认 UI:CM95 Visual Object Reviewer
最终 Layer Assignment 必须允许人工确认。项目内提供独立 Web Reviewer:
```text
tools/style-visual-object/reviewer/
├── review_server.py
└── web/
├── index.html
├── app.js
└── style.css
```
默认启动:
```text
python3 tools/style-visual-object/reviewer/review_server.py --host 0.0.0.0 --port 18083
```
### 人工确认单位
Reviewer 以 **CM95 当前 Style 正向可达的唯一 Visual Resource** 为确认单位。
当前基线为 150 个资源。一个人工决定会应用到该视觉资源在 Anonymous Catalog 中的所有 occurrence,但不会修改 Anonymous Catalog 本身。
### 主审查界面必须隐藏 Provider 语义信息
为了避免人工被字段名或已有 source-layer 名称带偏,主审查界面默认只能看到:
- 匿名 Visual Object ID;
- 实际图形;
- component role;
- geometry role;
- occurrence 数;
- NavSea Standard Visual Object 候选;
- 标准 Layer;
- 当前人工决定。
以下 CM95 原始信息默认隐藏:
- resource key;
- source-layer;
- Style Layer id;
- Provider provenance。
只有用户主动展开“审计信息”后才能读取这些内容。
### 人工状态
人工决定固定使用:
```text
MATCH
PARTIAL
AMBIGUOUS
COMPONENT
UNKNOWN
```
规则:
- MATCH / PARTIAL:必须选择且只能选择一个标准 Layer;
- AMBIGUOUS:必须选择至少两个候选标准 Layer;
- COMPONENT:不选择标准 Layer、不绑定 Standard Visual Object;可选记录顶标、浮标主体、立标主体、灯光、附加标记、面填充图案、线型图案、文字或其他组件;
- UNKNOWN:不选择标准 Layer;
- Standard Visual Object 可以选择,也可以不选择;
- 人工确认优先于机器建议;
- 未人工确认的项目在最终人工导出时保持 UNKNOWN,不自动继承机器建议。
### 人工结果保存
增量人工决定保存到:
```text
tools/style-visual-object/output/cm95-manual-review/manual-review-v1.json
```
点击“生成当前人工确认结果”后生成:
```text
tools/style-visual-object/output/cm95-manual-review/
├── reviewed-anchors-manual-v1.json
└── assignment/
├── cm95-layer-assignment-v1.json
├── cm95-layer-assignment-v1.csv
└── cm95-layer-assignment-v1.html
```
人工确认过程不得覆盖:
- `navsea-standard/standard-catalog.json`;
- `cm95-anonymous/anonymous-catalog.json`;
- 既有自动/辅助建议文件。
NavSea Standard Catalog 继续保持 FROZEN,只作为只读标准库使用。
---
## Reviewer 中文名称显示规则
人工 Reviewer 中,CM95 与 NavSea Standard Visual Object 均应优先显示中文名称,帮助人工理解和确认。
中文名称来源分两类:
1. CM95:
- 优先读取当前 CM95 仓库中的 S-52 symbol / line / area-pattern metadata;
- 保留 S-52 原始英文 `description`;
- 生成独立的中文显示译名;
- 中文译名属于工程 UI enrichment,不冒充 IHO 官方中文译名。
2. NavSea Standard:
- 依据冻结 Standard Visual Object 的语义资源键和标准 Layer 生成中文显示名;
- 标准 Layer 同时显示中文名和原始 Layer ID。
名称补充表:
```text
tools/style-visual-object/output/reference-name-enrichment-v1.json
```
固定原则:
> 中文名、英文说明、S-52 code 只用于 UI 显示和人工理解,不得参与 Visual Matcher、自动聚类或 Layer Assignment。
Reviewer 主界面显示优先级:
```text
中文名称
→ 实际图形
→ 中文标准 Layer
→ 原始 code / 英文说明(辅助)
```
已有机器建议也必须显示:
```text
标准对象中文名
+
标准 Layer 中文名
+
MATCH / PARTIAL / AMBIGUOUS / COMPONENT / UNKNOWN
```
不得只显示资源 key 或 Layer ID 让用户自行猜测。
---
## Reviewer 宽屏固定确认布局
Reviewer 在宽屏下采用固定三栏工作区:
```text
左:CM95 当前 Visual Object
中:NavSea Standard 候选(竖排、内部滚动)
右:人工判断(固定可见)
```
固定要求:
- 主页面不得为了点击 MATCH / PARTIAL / AMBIGUOUS / COMPONENT / UNKNOWN 或保存结果而要求纵向滚动;
- NavSea Standard 候选采用竖排列表,并在候选区域内部滚动;
- 标准 Layer 列表在人工判断面板内部滚动;
- `保存并下一个 / 仅保存 / 撤销` 始终保持在右侧人工判断区可见;
- 左侧 CM95 队列独立滚动;
- 审计信息默认折叠,不抢占主要确认空间;
- 窄屏才允许退回上下布局。
---
## Standard Visual Object 缺失时的 Layer-only 人工命名
外部 Provider(例如 CM95 / S-52)的视觉内容可能多于当前 NavSea Standard Visual Object Catalog。
因此:
> 找不到对应的 NavSea Standard Visual Object,不等于无法确定标准 Layer。
人工 Reviewer 必须支持两种最终确认路径:
```text
A. 有对应标准图标
Provider Visual Object
→ Standard Visual Object
→ Standard Layer
assignment_mode = VISUAL_OBJECT_MATCH
B. 没有对应标准图标,但所属 Layer 可以人工确定
Provider Visual Object
→ Standard Layer
assignment_mode = LAYER_ONLY
standard_resource_key = null
```
Layer-only 的要求:
- 必须由人工明确选择标准 Layer;
- 不得伪造一个不存在的 Standard Visual Object;
- 不得因为没有对应图标就强制设为 UNKNOWN;
- 中文名称、S-52 官方英文说明和实际视觉可以作为人工理解证据;
- 这些名称仍不进入自动 Visual Matcher;
- 当前 Reviewer 中,点击“没有对应标准图标,只确认所属 Layer”会清除 Standard Visual Object 绑定,并保留唯一 Layer。
状态建议:
- 有明确对应完整图形时可使用 MATCH;
- 无对应标准图标但 Layer 明确时使用 PARTIAL + LAYER_ONLY;
- 只能确定多个可能 Layer 时使用 AMBIGUOUS;
- 连 Layer 也无法确定时才使用 UNKNOWN。
---
## COMPONENT:只作为完整 Visual Object 的组成部分
当当前显示的 S-52 / CM95 图形只是一个主体、顶标、灯光或其他附加组件时,不应强迫用户给它最终 Layer。
Reviewer 必须允许:
```text
status = COMPONENT
assignment_mode = COMPONENT_ONLY
standard_layer = null
standard_resource_key = null
```
可选 `component_kind`:
```text
topmark 顶标
buoy_body 浮标主体
beacon_body 立标主体
light 灯光
auxiliary_mark 附加标记
fill_pattern 面填充图案
line_pattern 线型图案
text 文字
other 其他组件
```
`COMPONENT` 与 `UNKNOWN` 必须区分:
- `COMPONENT`:已经知道它只是完整对象的一部分;
- `UNKNOWN`:当前连它的作用/归属关系也无法可靠判断。
后续 Composite Visual Object 阶段再把 COMPONENT 与其他组件组合,最终 Layer 应尽量由完整 Visual Object 确认。
---
## Reviewer 最可能候选提示
Reviewer 的 NavSea Standard 候选可以提供一个 **UI-only 的“最可能”提示**,帮助人工快速判断。
综合参考只用于界面提示,来源包括:
- Visual Matcher 的实际图形相似度;
- CM95 中文显示名与 NavSea Standard 中文显示名的文字相似度;
- 已有 reviewed visual suggestion 是否支持同一标准对象或同一 Layer。
界面规则:
- 综合排序第一的候选中文名称标红;
- 显示“最可能”标签;
- 同时显示“视觉 xx% / 综合 xx%”;
- 即使是第一名,综合分较低时也必须保留低分,不能隐藏不确定性;
- 红色提示不得自动选择 Standard Visual Object;
- 不得自动写入人工决定;
- 不参与最终 Layer Assignment。
一句话:
> 红色“最可能”只是人工审查提示,不是系统确认结果。
宽屏布局同时调整为:当前 CM95 对象区域更窄,NavSea Standard 视觉候选区域更宽,右侧人工判断继续固定显示。
---
## Provider Layer Classifier:当前工作的最终目标
当前多源 PBF 对应工作的目标不是寻找“外部 Provider 图标等于 NavSea 哪个图标”,而是:
> 把外部 Provider 的对象正确分类到现有 NavSea Standard Layer。
因此正式流程分成两层:
```text
第一层:Provider-neutral Style Visual Object Tool
Style + Sprite
→ Anonymous Visual Object
第二层:Provider Layer Classifier
Anonymous Visual Object
+ Provider 官方语义资料
+ 实际视觉证据
+ 可选 Standard Visual Object 参考
→ NavSea Standard Layer
→ 人工确认
```
关键规则:
1. `Style Visual Object Tool` 仍然不知道 NavSea Layer、CM95 语义或 Provider 私有分类,继续保持 Provider-neutral。
2. `Provider Layer Classifier` 可以使用 Provider 自己的官方语义资料。CM95 当前使用 S-52 metadata 的官方英文 `description`,再提供中文显示译名。
3. Provider 的 `source-layer` 仍不得作为分类依据,只保留 provenance/audit。
4. Standard Visual Object 一一对应不是最终目标,也不是 Layer 命名的强制前提。
5. 没有对应 NavSea 图标,但 Provider 语义足以确定 Layer 时,允许直接 `LAYER_ONLY`。
6. 当前图形只是顶标、灯光、主体、pattern 等组件时使用 `COMPONENT`,不单独分配最终 Layer。
7. 只有连 Layer 都无法可靠判断时才使用 `UNKNOWN`。
### CM95 语义 Layer 规则
当前 CM95 分类规则独立保存:
```text
tools/style-visual-object/cm95_semantic_layer_rules_v1.json
```
规则使用 S-52 官方 description 和资源类型进行声明式分类,例如:
```text
tower, black/white, full-chart and simplified
→ 对象大类:陆上塔状构筑物
→ onshore_structure_point
beacon tower, red, full-chart
→ 对象大类:航标塔体
→ navigation_marks
topmark for buoys ...
→ COMPONENT / topmark
```
这些规则属于 Provider Layer Classifier,不得回写进通用 Style Visual Object extraction。
### Reviewer 中间区域
Reviewer 中间主要区域现在显示 `NavSea Layer 建议`,综合参考:
- S-52 官方语义;
- 实际视觉相似度;
- 已有 reviewed visual suggestion。
语义证据优先于“长得像”。例如普通 `tower` 即使视觉上很像 beacon,也应优先按 S-52 的 tower 语义归到 `onshore_structure_point`。
Standard Visual Object 图标被降为折叠的辅助参考区,不再作为主要任务。
---
## Git 冻结基线与固定校验命令
CM95 v1 人工分类完成后,以下内容属于应进入 Git 的冻结基线:
- 工具实现:`style_vo_tool.py`、`visual_anchor_matcher.py`、`build_reference_names.py`、`apply_reviewed_layer_assignment.py`;
- Provider 分类规则:`cm95_semantic_layer_rules_v1.json`;
- 人工 Reviewer:`reviewer/`;
- 固定校验逻辑:`validate_cm95_classification.py`;
- NavSea Frozen Standard Catalog 与 CM95 Anonymous Catalog;
- S-52 中文名称 enrichment、视觉辅助结果;
- 150 项人工确认;
- 最终 occurrence 级 Layer Assignment;
- 固定校验报告和最终中文报告。
固定校验命令:
```bash
python3 tools/style-visual-object/validate_cm95_classification.py
```
提交前必须满足:
```text
RESULT: PASS
```
`WARN` 允许存在,但只能表示“人工结果与后续语义建议不同,需要时复核”;不得自动覆盖人工结果。
当前权威结果路径:
```text
tools/style-visual-object/output/cm95-manual-review/manual-review-v1.json
tools/style-visual-object/output/cm95-manual-review/reviewed-anchors-manual-v1.json
tools/style-visual-object/output/cm95-manual-review/assignment/cm95-layer-assignment-v1.json
tools/style-visual-object/output/cm95-manual-review/validation-report-v1.json
```
当前最终报告:
```text
tools/style-visual-object/output/CM95_Visual_Object_Layer命名报告_v2.md
```