# 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 ```