Initial import of NavSea pbf project

This commit is contained in:
OpenAI Codex
2026-03-17 19:48:15 +08:00
commit 5f3f7409b3
84 changed files with 43889 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
# NavSea Semantic Overlay Validation System
## Purpose
Validate the NavSea semantic overlay without touching rendering logic, style configuration, or vector tile structure.
## Inputs
The task reads the existing semantic overlay and audit tables in database `pbf_analysis`, including:
- `canonical_layer_rules`
- `canonical_object_rules`
- `object_geometry_allowlist`
- `pbf_relayer_candidates`
- `pbf_render_compatibility`
- `pbf_detection_catalog`
- `style_layers`
- `features`
- `tile_density`
## Execution
Rebuild the semantic overlay metadata and then run validation:
```bash
.venv/bin/python navsea_relayer.py
.venv/bin/python navsea_semantic_validation.py
```
## Validation Tables
The validation task creates or refreshes:
- `classification_validation`
- `geometry_consistency`
- `style_render_equivalence`
- `detection_catalog_integrity`
- `spatial_anomalies`
- `semantic_validation_summary`
## Current Design Notes
- Rendering compatibility is verified at database level only.
- `canonical_object_rules` is the stable object-level rule source.
- `object_geometry_allowlist` is the geometry whitelist used to separate valid multi-geometry objects from true anomalies.
- `spatial_anomalies` is intentionally lightweight and currently focuses on tile-density and tile-index anomalies.
## Success Criteria
- No render equivalence break
- No classification errors
- No geometry consistency errors
- No detection catalog integrity errors
- Spatial anomalies limited to acceptable warnings

View File

@@ -0,0 +1,229 @@
# NavSea Weather Server
Task: WeatherServer_GridBuilder
Architecture: NavSea V11
Codex: codex6
Status: TODO
---
# 1 任务目标
实现 Weather Grid Builder 模块。
功能:
将 GRIB 数据解析为统一的 Weather Grid 数据结构。
输入:
data/grib/*.grib2
输出:
data/grid/*.json
Weather Grid 将作为:
Vector Tile Generator
Routing Engine
Weather Analysis
的基础数据源。
---
# 2 输入数据
GRIB 文件来自 Downloader。
示例:
data/grib/
20260312_00_f000.grib2
20260312_00_f003.grib2
20260312_00_f006.grib2
变量:
UGRD
VGRD
APCP
PRMSL
TMP
---
# 3 Weather Grid 数据结构
每个 grid 点结构:
{
"lat": float,
"lon": float,
"wind_speed": float,
"wind_dir": float,
"rain": float,
"temp": float,
"pressure": float
}
说明:
lat 纬度
lon 经度
wind_speed m/s
wind_dir 度
rain mm
temp 摄氏度
pressure hPa
---
# 4 风速计算
使用 U/V 分量计算:
wind_speed = sqrt(u² + v²)
---
# 5 风向计算
公式:
wind_dir = (atan2(u, v) * 180 / π + 360) % 360
结果:
0360°
---
# 6 Grid Builder 输出
文件:
data/grid/
示例:
grid_20260312_00_f000.json
结构:
{
"time": "20260312_00_f000",
"points": [...]
}
---
# 7 创建文件
weather_server/grid/grid_builder.py
---
# 8 实现代码
```python
import os
import json
import numpy as np
import xarray as xr
INPUT_DIR = "data/grib"
OUTPUT_DIR = "data/grid"
os.makedirs(OUTPUT_DIR, exist_ok=True)
def compute_wind(u, v):
speed = np.sqrt(u**2 + v**2)
direction = (np.degrees(np.arctan2(u, v)) + 360) % 360
return speed, direction
def process_file(path):
ds = xr.open_dataset(path, engine="cfgrib")
u = ds["u10"].values
v = ds["v10"].values
rain = ds["tp"].values
pressure = ds["msl"].values
temp = ds["t2m"].values
lat = ds.latitude.values
lon = ds.longitude.values
wind_speed, wind_dir = compute_wind(u, v)
points = []
for i in range(len(lat)):
for j in range(len(lon)):
point = {
"lat": float(lat[i]),
"lon": float(lon[j]),
"wind_speed": float(wind_speed[i][j]),
"wind_dir": float(wind_dir[i][j]),
"rain": float(rain[i][j]),
"temp": float(temp[i][j]),
"pressure": float(pressure[i][j])
}
points.append(point)
return points
def main():
for file in os.listdir(INPUT_DIR):
if not file.endswith(".grib2"):
continue
path = os.path.join(INPUT_DIR, file)
print("processing", file)
points = process_file(path)
output = os.path.join(
OUTPUT_DIR,
f"grid_{file.replace('.grib2','')}.json"
)
data = {
"time": file.replace(".grib2",""),
"points": points
}
with open(output, "w") as f:
json.dump(data, f)
print("saved", output)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,215 @@
# NavSea Weather Server
Task: WeatherServer_GridBuilder_v2
Architecture: NavSea V11
Codex: codex6
Status: TODO
---
# 1 任务目标
升级 Grid Builder
grid_builder.py → GridBuilder v2
目标:
1 裁剪日本区域 grid
2 使用数组结构保存 grid
3 大幅减少 JSON 文件大小
---
# 2 当前问题
旧版 GridBuilder
生成全球 grid
1440 × 721
≈ 1,038,240 points
JSON 文件:
≈ 215MB
这是不可接受的。
Downloader 已经只下载:
120E 150E
20N 50N
GridBuilder 必须只输出这个区域。
---
# 3 区域范围
REGION
lon_min = 120
lon_max = 150
lat_min = 20
lat_max = 50
理论 grid
(150-120)/0.25 = 120
(50-20)/0.25 = 120
≈ 14400 grid points
---
# 4 新 Grid 数据结构
旧结构:
points list
{
"points":[
{lat,lon,...}
]
}
新结构:
grid arrays
{
"time": "...",
"lat": [...],
"lon": [...],
"wind_speed": [...],
"wind_dir": [...],
"rain": [...],
"temp": [...],
"pressure": [...]
}
优点:
1 文件更小
2 读取更快
3 tile generator 更容易
---
# 5 创建文件
weather_server/grid/grid_builder_v2.py
---
# 6 实现代码
```python
import os
import json
import numpy as np
import xarray as xr
INPUT_DIR = "data/grib"
OUTPUT_DIR = "data/grid"
os.makedirs(OUTPUT_DIR, exist_ok=True)
REGION = {
"lon_min":120,
"lon_max":150,
"lat_min":20,
"lat_max":50
}
def compute_wind(u, v):
speed = np.sqrt(u**2 + v**2)
direction = (np.degrees(np.arctan2(u, v)) + 360) % 360
return speed, direction
def process_file(path):
ds = xr.open_dataset(path, engine="cfgrib")
u = ds["u10"].values
v = ds["v10"].values
rain = ds["tp"].values
pressure = ds["msl"].values
temp = ds["t2m"].values
lat = ds.latitude.values
lon = ds.longitude.values
wind_speed, wind_dir = compute_wind(u, v)
lat_idx = np.where(
(lat >= REGION["lat_min"]) &
(lat <= REGION["lat_max"])
)[0]
lon_idx = np.where(
(lon >= REGION["lon_min"]) &
(lon <= REGION["lon_max"])
)[0]
lat_region = lat[lat_idx]
lon_region = lon[lon_idx]
wind_speed = wind_speed[np.ix_(lat_idx, lon_idx)]
wind_dir = wind_dir[np.ix_(lat_idx, lon_idx)]
rain = rain[np.ix_(lat_idx, lon_idx)]
temp = temp[np.ix_(lat_idx, lon_idx)]
pressure = pressure[np.ix_(lat_idx, lon_idx)]
return {
"lat": lat_region.tolist(),
"lon": lon_region.tolist(),
"wind_speed": wind_speed.tolist(),
"wind_dir": wind_dir.tolist(),
"rain": rain.tolist(),
"temp": temp.tolist(),
"pressure": pressure.tolist()
}
def main():
for file in os.listdir(INPUT_DIR):
if not file.endswith(".grib2"):
continue
path = os.path.join(INPUT_DIR, file)
print("processing", file)
grid = process_file(path)
output = os.path.join(
OUTPUT_DIR,
f"grid_{file.replace('.grib2','')}.json"
)
data = {
"time": file.replace(".grib2",""),
"grid": grid
}
with open(output, "w") as f:
json.dump(data, f)
print("saved", output)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,248 @@
# NavSea Weather Server
Task: WeatherServer_VectorTileGenerator
Architecture: NavSea V11
Codex: codex6
Status: TODO
---
# 1 任务目标
实现 Vector Tile Generator。
功能:
将 Weather Grid JSON 转换为 MapLibre Vector Tile (PBF)。
输入:
data/grid/*.json
输出:
output/weather/{time}/{z}/{x}/{y}.pbf
用于 NavSea 客户端加载天气图层。
---
# 2 使用库
需要安装:
pip install mercantile
pip install mapbox-vector-tile
---
# 3 输入数据
GridBuilder v2 生成:
data/grid/
grid_20260312_00_f000.json
grid_20260312_00_f003.json
结构:
{
"time": "...",
"grid": {
"lat": [...],
"lon": [...],
"wind_speed": [[...]],
"wind_dir": [[...]],
"rain": [[...]],
"temp": [[...]],
"pressure": [[...]]
}
}
grid 尺寸:
121 × 121
---
# 4 Tile Zoom 设计
Weather tile 只需要 4 个 zoom
2
4
6
8
---
# 5 Tile 输出结构
output/weather/
time/
z/
x/
y.pbf
示例:
output/weather/20260312_00_f000/4/10/7.pbf
---
# 6 Feature 结构
每个 grid 点 → 一个 feature
geometry
POINT(lon lat)
properties
{
"ws": wind_speed
"wd": wind_dir
"r": rain
"t": temp
"p": pressure
}
字段缩写减少 tile 大小。
---
# 7 创建文件
weather_server/tiles/vector_tile_generator.py
---
# 8 实现代码
```python
import os
import json
import mercantile
import mapbox_vector_tile
GRID_DIR = "data/grid"
OUTPUT_DIR = "output/weather"
ZOOMS = [2,4,6,8]
def load_grid(path):
with open(path) as f:
data = json.load(f)
return data["time"], data["grid"]
def grid_to_features(grid):
lat = grid["lat"]
lon = grid["lon"]
ws = grid["wind_speed"]
wd = grid["wind_dir"]
rain = grid["rain"]
temp = grid["temp"]
pres = grid["pressure"]
features = []
for i in range(len(lat)):
for j in range(len(lon)):
feature = {
"geometry":{
"type":"Point",
"coordinates":[lon[j], lat[i]]
},
"properties":{
"ws":ws[i][j],
"wd":wd[i][j],
"r":rain[i][j],
"t":temp[i][j],
"p":pres[i][j]
}
}
features.append(feature)
return features
def generate_tiles(time, features):
for z in ZOOMS:
tiles = mercantile.tiles(120,20,150,50,z)
for tile in tiles:
bounds = mercantile.bounds(tile)
tile_features = []
for f in features:
lon, lat = f["geometry"]["coordinates"]
if (
bounds.west <= lon <= bounds.east
and bounds.south <= lat <= bounds.north
):
tile_features.append(f)
if not tile_features:
continue
layer = {
"weather": tile_features
}
tile_data = mapbox_vector_tile.encode(layer)
path = os.path.join(
OUTPUT_DIR,
time,
str(z),
str(tile.x)
)
os.makedirs(path, exist_ok=True)
filename = os.path.join(
path,
f"{tile.y}.pbf"
)
with open(filename,"wb") as f:
f.write(tile_data)
print("tile", time, z, tile.x, tile.y)
def main():
for file in os.listdir(GRID_DIR):
if not file.endswith(".json"):
continue
path = os.path.join(GRID_DIR, file)
print("processing", file)
time, grid = load_grid(path)
features = grid_to_features(grid)
generate_tiles(time, features)
if __name__ == "__main__":
main()

528
tasks/classfild.md Normal file
View File

@@ -0,0 +1,528 @@
# NavSea Data Classification & Validation Pipeline
Version: v1.0
Goal:
从当前数据库中的 PBF 数据自动:
1. 解析 at 字段
2. 构建语义属性表
3. 构建对象目录
4. 自动推导对象类型
5. 验证分类正确性
6. 统计 tile 密度
7. 输出 NavSea 分类报告
所有中间结果写入 MySQL 表。
数据库在 192.168.200.184. root/2chi9ks2
可以建立数据库也可以使用python代码必要的时候可以下载所需的包。
---
# TASK 1
Parse AT Attributes
Goal:
解析 properties 表中 k='at' 的 JSON 字符串。
Create Table:
```sql
CREATE TABLE IF NOT EXISTS at_attributes (
feature_id BIGINT,
k VARCHAR(100),
v TEXT
);
```
Logic:
1. 查询
```sql
SELECT feature_id, v
FROM properties
WHERE k='at';
```
2. v 是 JSON array
Example:
```
[["レイヤ","航路標識点"],["形状分類","シーバース灯"],["灯色","W (白)"]]
```
3. 解析后写入:
```
feature_id | k | v
--------------------
2682088 | レイヤ | 航路標識点
2682088 | 形状分類 | シーバース灯
2682088 | 灯色 | W (白)
```
Implementation:
Python
Libraries:
```
pymysql
json
```
Output:
```
table: at_attributes
```
---
# TASK 2
Build Feature Semantic Table
Goal:
将 feature + vt_layer + at 属性合并。
Create Table:
```sql
CREATE TABLE feature_semantic AS
SELECT
f.id AS feature_id,
f.vt_layer,
f.geom_type,
MAX(CASE WHEN a.k='分類' THEN a.v END) AS class_name,
MAX(CASE WHEN a.k='形状分類' THEN a.v END) AS shape_name,
MAX(CASE WHEN a.k='レイヤ' THEN a.v END) AS layer_name
FROM features f
LEFT JOIN at_attributes a
ON f.id = a.feature_id
GROUP BY f.id;
```
Output table:
```
feature_semantic
```
Columns:
```
feature_id
vt_layer
geom_type
class_name
shape_name
layer_name
```
---
# TASK 3
Generate Object Catalog
Goal:
统计所有语义对象。
Create Table:
```sql
CREATE TABLE object_catalog AS
SELECT
layer_name,
class_name,
shape_name,
vt_layer,
geom_type,
COUNT(*) AS feature_count
FROM feature_semantic
GROUP BY
layer_name,
class_name,
shape_name,
vt_layer,
geom_type;
```
Output:
```
object_catalog
```
Purpose:
得到完整对象目录。
Example:
```
魚礁 | p施設 | Point | 24683
灯台 | p航路標識群 | Point | 18000
等深線 | L等深線 | Line | 440000
```
---
# TASK 4
Geometry Consistency Check
Goal:
检查对象是否使用一致 geometry。
Create Table:
```sql
CREATE TABLE geometry_consistency AS
SELECT
class_name,
geom_type,
COUNT(*) AS feature_count
FROM feature_semantic
GROUP BY class_name, geom_type;
```
Output:
```
geometry_consistency
```
Purpose:
发现异常对象。
Example anomaly:
```
灯台 | Polygon
```
---
# TASK 5
Candidate Object Type Detection
Goal:
自动推导 object_type。
规则优先级:
1 class_name
2 shape_name
3 vt_layer
Create Table:
```sql
CREATE TABLE object_type_candidates AS
SELECT
feature_id,
COALESCE(class_name, shape_name, vt_layer) AS object_type,
geom_type
FROM feature_semantic;
```
Output:
```
object_type_candidates
```
---
# TASK 6
Object Type Statistics
Goal:
统计对象数量。
Create Table:
```sql
CREATE TABLE object_type_stats AS
SELECT
object_type,
geom_type,
COUNT(*) AS feature_count
FROM object_type_candidates
GROUP BY object_type, geom_type;
```
Output:
```
object_type_stats
```
Purpose:
识别主要对象。
---
# TASK 7
Style Cross Reference
Goal:
分析 style.json。
Extract:
```
layer_id
source-layer
icon-image
line-color
fill-color
```
Create Table:
```sql
CREATE TABLE style_layers (
layer_id VARCHAR(200),
source_layer VARCHAR(200),
icon VARCHAR(200),
line_color VARCHAR(200),
fill_color VARCHAR(200)
);
```
Join:
```sql
CREATE TABLE style_mapping AS
SELECT
s.layer_id,
s.icon,
o.object_type,
o.geom_type
FROM style_layers s
JOIN object_type_candidates o
ON s.source_layer = o.object_type;
```
Output:
```
style_mapping
```
Purpose:
确认对象 → 图标关系。
---
# TASK 8
Tile Density Analysis
Goal:
统计 tile feature 密度。
Create Table:
```sql
CREATE TABLE tile_density AS
SELECT
z,
x,
y,
COUNT(*) AS feature_count
FROM features
GROUP BY z,x,y;
```
Output:
```
tile_density
```
---
# TASK 9
Tile Density Top 100
Create Table:
```sql
CREATE TABLE tile_density_top100 AS
SELECT *
FROM tile_density
ORDER BY feature_count DESC
LIMIT 100;
```
Purpose:
识别高密度 tile。
---
# TASK 10
Spatial Sanity Checks
Goal:
发现明显错误。
Examples:
Navigation lights not point:
```sql
CREATE TABLE anomaly_navigation_geom AS
SELECT *
FROM feature_semantic
WHERE class_name='灯台'
AND geom_type!='Point';
```
Reef not point/polygon:
```sql
CREATE TABLE anomaly_reef_geom AS
SELECT *
FROM feature_semantic
WHERE class_name='魚礁'
AND geom_type NOT IN ('Point','Polygon');
```
---
# TASK 11
NavSea Classification Report
Generate markdown:
```
navsea_classification_report.md
```
Content:
## Dataset Summary
Total features:
```sql
SELECT COUNT(*) FROM features;
```
Total object types:
```sql
SELECT COUNT(DISTINCT object_type)
FROM object_type_candidates;
```
---
## Top Object Types
```sql
SELECT *
FROM object_type_stats
ORDER BY feature_count DESC
LIMIT 50;
```
---
## Geometry Consistency
```
geometry_consistency
```
---
## Style Mapping
```
style_mapping
```
---
## Tile Density
```
tile_density_top100
```
---
# Final Deliverables
Database Tables:
```
at_attributes
feature_semantic
object_catalog
geometry_consistency
object_type_candidates
object_type_stats
style_layers
style_mapping
tile_density
tile_density_top100
anomaly_navigation_geom
anomaly_reef_geom
```
Final Document:
```
navsea_classification_report.md
```
---
# Execution
Single command:
```
python navsea_audit.py
```
Pipeline:
```
parse_at
→ semantic_table
→ object_catalog
→ classification
→ validation
→ report
```
---
# Success Criteria
The system must allow answering:
1 What objects exist
2 How many features each object has
3 What geometry they use
4 How they are styled
5 Whether classification is consistent
6 Whether tile density is reasonable

151
tasks/firsttest.md Normal file
View File

@@ -0,0 +1,151 @@
# NavSea Weather Server Step-1
GRIB 解析环境测试
目标:
验证服务器可以正确解析 GRIB 文件。
---
# 1 安装系统依赖
在 Linux 服务器执行:
apt update
apt install -y python3 python3-pip
apt install -y libeccodes0 libeccodes-dev
apt install -y python3-eccodes
---
# 2 安装 Python 库
pip3 install cfgrib
pip3 install xarray
pip3 install numpy
---
# 3 下载测试 GRIB 文件
创建测试目录:
mkdir weather_test
cd weather_test
下载 NOAA GFS 示例:
wget https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.20260312/00/atmos/gfs.t00z.pgrb2.0p25.f003 -O test.grib2
(如果日期目录不存在,可以换最新日期)
---
# 4 创建测试脚本
创建文件:
test_grib.py
内容:
import xarray as xr
file = "test.grib2"
print("Opening GRIB file...")
ds = xr.open_dataset(file, engine="cfgrib")
print("Dataset loaded")
print(ds)
print("\nVariables:")
print(ds.data_vars)
---
# 5 运行测试
python3 test_grib.py
如果成功,你会看到类似输出:
Dataset loaded
Dimensions:
latitude: 721
longitude: 1440
Variables:
u10
v10
t2m
msl
tp
---
# 6 测试读取风数据
修改脚本:
import xarray as xr
import numpy as np
file = "test.grib2"
ds = xr.open_dataset(file, engine="cfgrib")
u = ds['u10']
v = ds['v10']
speed = np.sqrt(u**2 + v**2)
print("Wind sample:")
print(speed.values[0][0])
---
# 7 成功标志
如果成功运行:
说明:
GRIB解析正常
Python环境正常
可以进入 Weather Server 开发
---
# 8 常见错误
错误:
eccodes library not found
解决:
apt install libeccodes-dev
---
# 9 完成后下一步
下一步开发:
GRIB Downloader
模块:
weather_server/downloader/gfs_downloader.py
负责:
自动下载 GFS GRIB 数据。

413
tasks/pbf/AllPbf.md Normal file
View File

@@ -0,0 +1,413 @@
# NavSea Server Codex Tasks v2
Architecture: NavSea V11 / Codex6
Scope: **Server Side Only**
---
# Global Rules全局强制规则
以下规则适用于所有 NavSea Server Tasks。
## Rule 1 — 必须保留原始 PBF 属性
语义系统 **不得删除或覆盖任何原始 PBF feature 属性**
必须保留包括但不限于:
* 日文对象名称
* 海图原始属性
* 灯塔信息
* 深度信息
* 渔区信息
* 海图符号属性
* 任何原始 metadata
语义字段只能 **新增**,不能替换。
示例:
```
class = 灯
shape = 灯標
name = 大島灯台
```
新增语义字段:
```
canonical_object_type = navigation_aid_light
object_family = navigation_aid
detection_class = navigation_mark
```
---
## Rule 2 — 不得修改 style.json 依赖属性
任何被 style.json 使用的属性字段 **必须保持不变**
典型字段包括:
```
source_layer
class
shape
name
symbol
depth
type
category
```
语义系统 **不得重命名或删除这些字段**
---
## Rule 3 — 语义字段只能新增
NavSea Semantic Overlay 只能增加字段,例如:
```
canonical_object_type
object_family
detection_class
capability
detection_key
```
不得改变:
```
geometry
source_layer
original_attributes
```
---
# Task 01 — Semantic Overlay Validation System v2
## 任务目标
构建验证系统,确保语义重建不会破坏原始 PBF 渲染结构。
验证内容包括:
* feature 数量一致
* geometry 类型一致
* style 渲染一致
* 原始属性完整保留
## 输入表
Codex 自动检测:
```
canonical_layer_rules
pbf_relayer_candidates
pbf_render_compatibility
pbf_detection_catalog
```
## 输出验证表
```
classification_validation
geometry_consistency
style_render_equivalence
attribute_preservation_check
semantic_validation_summary
```
## 新增验证
必须新增:
```
attribute_preservation_check
```
用于确认:
```
原始 PBF 属性未丢失
```
---
# Task 02 — Object Taxonomy Builder v2
## 任务目标
建立稳定的海图对象分类体系。
## 输出表
```
navsea_object_taxonomy
```
## 字段
```
canonical_object_type
object_family
detection_class
description
```
## 示例
```
rock → hazard → obstacle
wreck → hazard → obstacle
reef → hazard → obstacle
light → navigation_aid → navigation_mark
```
## 约束
Taxonomy 不能改变:
```
source_layer
original_attributes
```
---
# Task 03 — Object Capability System v2
## 任务目标
定义海图对象在航行中的能力capability
## 输出表
```
navsea_object_capabilities
```
## 字段
```
canonical_object_type
capability
```
## 示例
```
rock → collision
wreck → collision
reef → grounding
fishery → entangle
light → navigation_mark
breakwater → wave_barrier
```
## 目的
使检测系统可以查询:
```
所有 collision 对象
所有 grounding 对象
```
---
# Task 04 — Detection Object View v2
## 任务目标
创建统一检测对象视图。
## 视图
```
navsea_detection_objects
```
## 字段
```
feature_id
geometry
canonical_object_type
object_family
detection_class
capability
detection_key
```
## 数据来源
```
pbf_relayer_candidates
navsea_object_taxonomy
navsea_object_capabilities
```
## 约束
该视图:
```
只读
不修改原始数据
```
---
# Task 05 — Spatial Index Builder v2
## 任务目标
优化空间查询性能。
当前数据规模:
```
~6.6 million features
```
## Codex 任务
自动分析 geometry 字段并创建空间索引。
优化查询:
```
半径查询
航线走廊查询
船舶前方查询
```
## 目标对象
```
navsea_detection_objects
semantic feature tables
```
## 约束
不得改变表结构。
---
# Task 08 — Semantic Layer Coverage Report v2
## 任务目标
统计语义系统覆盖率。
检测:
```
未分类对象
layer 覆盖率
canonical_object 覆盖率
```
## 输出表
```
semantic_layer_coverage
canonical_object_coverage
source_layer_coverage
unclassified_features
coverage_summary
```
## 用途
发现:
```
规则遗漏
新对象
数据异常
```
---
# Task 09 — Vector Tile Semantic Drift Detection v2
## 任务目标
检测 PBF 更新导致的语义漂移。
## 检测内容
```
新对象类型
source_layer 变化
geometry 类型变化
属性结构变化
语义规则冲突
```
## 输出表
```
semantic_drift_summary
new_object_types
source_layer_drift
geometry_drift
attribute_drift
rule_conflict_report
```
## 用途
确保新 PBF 数据不会破坏语义系统。
---
# 推荐执行顺序
```
1 Semantic Overlay Validation
2 Semantic Coverage Report
3 Object Taxonomy
4 Object Capability
5 Detection Object View
6 Spatial Index Builder
7 Drift Detection
```
---
# 最终服务器结构
完成全部任务后服务器语义系统结构:
```
PBF
Semantic Reconstruction
Taxonomy
Capability
Detection Objects
Spatial Index
Validation / Drift Monitoring
```
该结构确保:
```
PBF 稳定
原始属性保留
style.json 可安全重建
```
---

View File

@@ -0,0 +1,107 @@
# NavSea 映射关系数据库固化方案 v1
版本v1
用途:把“旧版原始字段 / 层名 / 取值”和“新版标准化字段 / 语义 / 渲染语义”的关系正式固化到数据库里,作为后续规则审计、问题排查和构建回放的基础。
## 1 当前落地位置
本版已在 `pbf_analysis` 中建立以下正式对象:
- `navsea_rule_bundle`
- `navsea_source_layer_rules`
- `navsea_field_name_rules`
- `navsea_field_value_rules`
- `navsea_taxonomy_rules`
- `navsea_render_rules`
- `navsea_mapping_registry_vw`
- `navsea_legacy_to_new_mapping_vw`
- `navsea_new_to_legacy_mapping_vw`
## 2 规则源文件
数据库中的规则来自以下版本化文件:
- [navsea_rule_bundle_v1.yaml](/root/weather/tasks/pbf/mappings/navsea_rule_bundle_v1.yaml)
- [navsea_source_layer_rules_v1.yaml](/root/weather/tasks/pbf/mappings/navsea_source_layer_rules_v1.yaml)
- [navsea_field_name_rules_v1.yaml](/root/weather/tasks/pbf/mappings/navsea_field_name_rules_v1.yaml)
- [navsea_field_value_rules_v1.yaml](/root/weather/tasks/pbf/mappings/navsea_field_value_rules_v1.yaml)
- [navsea_taxonomy_rules_v1.yaml](/root/weather/tasks/pbf/mappings/navsea_taxonomy_rules_v1.yaml)
- [navsea_render_rules_v1.yaml](/root/weather/tasks/pbf/mappings/navsea_render_rules_v1.yaml)
## 3 同步脚本
同步脚本:
- [navsea_mapping_registry_sync.py](/root/weather/navsea_mapping_registry_sync.py)
- [navsea_mapping_registry.py](/root/weather/navsea_mapping_registry.py)
作用:
- 建表
- 从 YAML 导入 bundle / layer / field / value / taxonomy / render 规则
- 生成统一审计视图
- 在运行时由 builder 直接读取数据库规则,不再在多个文件中重复维护同一份映射常量
## 4 双向查询口径
旧版查新版:
```sql
SELECT *
FROM navsea_legacy_to_new_mapping_vw
WHERE legacy_key = '分類番号' AND legacy_value = '428';
```
新版查旧版:
```sql
SELECT *
FROM navsea_new_to_legacy_mapping_vw
WHERE new_key = 'chart_fill_style' AND new_value = 'fish_reef_area';
```
## 5 当前 v1 覆盖内容
- `source-layer` 日文层名到标准层名
- 旧字段名到标准字段名
- 关键旧字段取值到标准值
- taxonomy 规则
- render 规则
## 6 当前边界
本版已经把映射关系正式固化到了数据库里,并且 builder 已开始直接消费数据库规则,当前已接入:
- `source-layer` 标准化
- 旧字段值到新字段值的标准化
- 首批 render 规则
但还没有把 builder 的全部 `infer_*` 分支完全改造成“只从数据库执行规则”。
当前状态是:
- 规则资产已经固化在数据库
- 代码侧只保留兜底逻辑,数据库规则优先
- 后续可以逐步把执行层切到数据库规则驱动
## 6.1 未决对象处理规则
本体系中的“兜底”不等于“静默归入一个大筐”。
当前执行约束是:
- 如果没有命中特定 render 规则,不允许把 `REN-FALLBACK` 当成正常命中结果
- 这类对象会被标记为 `trace_status = needs_review`
- builder 会在每次构建后自动输出一份 `mapping_audit` 报告
- 报告中会列出未决对象的来源层、对象类型、几何类型、样本 `fid` 和原因
这条约束的目的是:
- 不让未覆盖对象悄悄混进“正常渲染”
- 不让规则缺口被一个泛化 fallback 掩盖
- 让后续补规则时有明确的对象清单
## 7 建议下一步
- 增加 `navsea_feature_rule_trace` 的数据库写入
- 让 builder 在 engineering 口径记录实际命中的 `taxonomy_rule_id` / `render_rule_id`
- 逐步把 `infer_*` 硬编码分支迁移到规则表执行

View File

@@ -0,0 +1,153 @@
# NavSea Codex Task
# Object Taxonomy Manual Review Package Generator
Architecture: NavSea V11 / Codex6 Scope: Server Side Documentation /
Review Preparation
------------------------------------------------------------------------
# Task Name
NavSea_Object_Taxonomy_Manual_Review_Package
------------------------------------------------------------------------
# Task Goal
Generate a manual review package for NavSea object taxonomy definition.
This task prepares a human-reviewable object classification package so
that the user can confirm:
1. canonical object naming
2. object family assignment
3. detection class assignment
4. whether mixed geometry objects should be unified or split
5. whether some source layers are container layers rather than semantic
layers
------------------------------------------------------------------------
# Inputs
object_catalog object_type_stats feature_semantic object_type_candidates
canonical_layer_rules canonical_object_rules pbf_source_object_stats
pbf_detection_catalog
Optional reference:
style_layers style_mapping
------------------------------------------------------------------------
# Output
NavSea_Object_Taxonomy_Manual_Review.md
------------------------------------------------------------------------
# Required Structure of the Review Document
## 1 Review Objective
Explain that this package is for manual confirmation of:
- canonical object type naming
- family grouping
- detection grouping
- geometry unification or splitting
- ambiguous object handling
------------------------------------------------------------------------
## 2 Review Priority Groups
Priority A --- Immediate navigation safety relevance
Examples: hazards, wrecks, rocks, reefs, dangerous obstacles, navigation
marks, channels, anchorage, restricted areas, fishery hazards
Priority B --- Navigation context / operational relevance
Examples: boundaries, facilities, subsea cables / pipelines, port
structures, land structures relevant to navigation
Priority C --- Background / rendering objects
Examples: labels, land background, rendering support layers
------------------------------------------------------------------------
## 3 Manual Review Candidate Table
Required columns:
review_priority layer_name class_name shape_name vt_layer
observed_geom_types total_feature_count suggested_canonical_object_type
suggested_canonical_family suggested_detection_class
suggested_review_reason needs_manual_review
needs_manual_review values:
YES NO
------------------------------------------------------------------------
## 4 Ambiguity Categories
### Multi-Geometry Ambiguity
Same object appearing as multiple geometry types.
### Navigation Meaning Ambiguity
Objects implying collision / grounding / entanglement risk.
### Source Layer Container Ambiguity
Layers that may act as container or rendering layers.
### Regulatory / Boundary Ambiguity
Objects representing legal or navigational boundaries.
------------------------------------------------------------------------
## 5 First-Pass Recommended Review Scope
Focus first on classes similar to:
航行危険障害物 投錨注意障害物 航路標識点 航路境界等 錨泊地等
施設・境界線等 海岸線等深線等 漁具定置箇所
------------------------------------------------------------------------
## 6 Proposed Review Decisions
Each candidate object should include:
Candidate Object Suggested canonical_object_type Suggested
canonical_family Suggested detection_class Reason Manual confirmation
required
------------------------------------------------------------------------
## 7 Layer Review Appendix
Columns:
source_layer semantic_granularity current_rule_guess review_reason
needs_manual_review
------------------------------------------------------------------------
## 8 Review Outcome Guidance
The user will confirm:
1 Confirm canonical object naming 2 Confirm family grouping 3 Confirm
detection grouping 4 Confirm geometry unification 5 Confirm container
layers
------------------------------------------------------------------------

View File

@@ -0,0 +1,36 @@
# NavSea PBF Schema v1
用途:定义 NavSea Vector Tile 的数据结构。
## 顶层字段
- identity
- chart_semantics
- labels
- light
- hazard
- area
- source_legacy
## identity
- fid
- canonical_object_type
- canonical_family
- detection_key
- render_layer
## chart_semantics
- chart_render_type
- chart_symbol_family
- chart_symbol_code
- chart_priority
- chart_visibility_min
- chart_visibility_max
## labels
- chart_label_text
- chart_label_subtext
- chart_label_anchor

View File

@@ -0,0 +1,226 @@
# NavSea PBF Schema v2
版本v2 Draft
用途:定义 NavSea 交付用 Vector Tile 的字段结构,兼顾渲染、碰撞、检索和旧海图兼容。
## 1 设计目标
v2 schema 要同时满足四件事:
- 保持旧海图渲染内容不明显缩水
- 支撑新的语义渲染体系
- 支撑碰撞检测和检索
- 控制字段职责,避免样式继续直接依赖大量原始编码
## 2 字段分组
v2 建议把交付字段分成 8 组:
- identity
- taxonomy
- render_semantics
- labels
- light
- hazard_area
- normalized_numeric
- source_legacy
## 3 identity
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `fid` | string | 是 | NavSea 自有对象标识,使用可逆算法生成的 16 进制字符串 |
| `fid_legacy_raw` | integer/string | 否 | 旧版原始 `fid`,建议只保留在 engineering 口径或 SQL trace |
| `fid_algo_id` | string | 否 | `fid` 生成算法标识,例如 `feistel32_aes_cyclewalk_v1` |
| `fid_key_id` | string | 否 | `fid` 生成时使用的密钥标识 |
| `render_layer` | string | 是 | 交付瓦片中的目标图层名 |
| `source_layer` | string | 否 | 原始图层名,建议保留到工程版或过渡期交付版 |
说明:
- 对“只做图片渲染”的产品可以弱化 `fid`
- 对当前 NavSea 的交付目标,不建议删除 `fid`
- 不建议继续直接暴露旧版原始 `fid`
- 建议基于 `tasks/pbf/fiddecode.md` 的可逆算法生成 NavSea 自有 `fid`
- 工程实现建议使用 `signed int32` 全域作为 legacy `fid` 的可逆映射范围
## 4 taxonomy
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `canonical_family` | string | 是 | 大类语义 |
| `canonical_object_type` | string | 是 | 细粒度对象类型 |
| `detection_key` | string | 是 | 用于检测和规则系统的稳定分类键 |
| `semantic_key` | string | 否 | 内部语义归并键,过渡期可保留 |
## 5 render_semantics
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `chart_render_type` | string | 是 | `symbol` / `line` / `fill` / `label` / `none` |
| `chart_symbol_family` | string | 否 | 符号族,例如 `navigation_light``hazard``depth_mark` |
| `chart_symbol_code` | string | 否 | 稳定符号码,例如 `lighthouse``rock_awash` |
| `chart_line_style` | string | 否 | 线型预设,例如 `boundary_dashed``contour_major` |
| `chart_fill_style` | string | 否 | 面填充预设,例如 `depth_zone_0_5``reef_area` |
| `chart_text_style` | string | 否 | 文字样式预设,例如 `place_name_sea``light_label` |
| `chart_priority` | integer | 是 | 绘制优先级,用于层级和碰撞 |
| `chart_visibility_min` | integer | 否 | 最小显示 zoom |
| `chart_visibility_max` | integer | 否 | 最大显示 zoom |
| `chart_collision_group` | string | 否 | 文本或符号碰撞组,例如 `place_label``light_label` |
说明:
- `chart_render_type``chart_priority` 建议作为最基础必填渲染字段
- 样式层优先读取 `chart_*` 字段,不再优先读取旧编码
## 6 labels
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `chart_label_text` | string | 否 | 主标注文本 |
| `chart_label_subtext` | string | 否 | 次级标注,例如灯略记 |
| `chart_label_anchor` | string | 否 | `top` / `bottom` / `left` / `right` / `center` |
| `chart_label_dx` | number | 否 | X 偏移 |
| `chart_label_dy` | number | 否 | Y 偏移 |
说明:
- 旧样式中的 `名称``名称補助``日本語地名``英文字地名` 仍可保留
- 新样式应优先使用 `chart_label_*`
## 7 light
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `light_color_code` | string | 否 | `white` / `red` / `green` / `yellow` / `mixed` |
| `light_character_code` | string | 否 | `Fl` / `Oc` / `Iso` / `F` / `V-AIS` |
| `light_sector_mode` | string | 否 | `sector` / `omni` / `none` |
| `light_arc_code` | string | 否 | 灯弧附加表达,是否交付由产品决定 |
说明:
- 灯弧本身可以不渲染
- 但灯质、灯色、略记对检索和标签仍有价值
## 8 hazard_area
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `hazard_class` | string | 否 | `rock` / `reef` / `wreck` / `obstruction` / `shoal` |
| `hazard_severity` | string | 否 | `critical` / `major` / `minor` / `context` |
| `area_usage_class` | string | 否 | `anchorage` / `route` / `fishery` / `restricted` / `water` |
## 9 normalized_numeric
建议把部分旧数值字段归一化,方便检索和规则判断。
| 字段 | 类型 | 必填 | 来源建议 |
| --- | --- | --- | --- |
| `depth_value_m` | number | 否 | 由 `水深値(m)` 归一化 |
| `clearance_height_m` | number | 否 | 由 `高さ(m)` 归一化 |
| `least_depth_m` | number | 否 | 由 `高さ/深度(m)` 中深度语义归一化 |
| `bearing_deg` | number | 否 | 由 `角度` 归一化 |
说明:
- 这些字段主要服务于检索、检测和统一显示
- 原始字段在过渡期可并存
## 10 source_legacy
以下字段是根据当前旧 `style.json` 的实际依赖,建议在 v2 过渡期继续保留的旧字段:
- `分類番号`
- `形状分類番号`
- `表示用番号`
- `灯色`
- `灯略記`
- `明弧/分孤`
- `表示位置`
- `名称`
- `名称補助`
- `日本語地名`
- `英文字地名`
- `水深値(m)`
- `高さ(m)`
- `高さ/深度(m)`
- `角度`
说明:
- 当前旧样式实际还使用了船舶动态字段 `cog``sog``hdg``length``rot``delay`
- 这些字段来自其他源,不属于 NavSea 静态海图对象 schema 的核心范围
## 11 v2 最低交付要求
每个 NavSea feature 至少应满足:
- `fid`
- `canonical_family`
- `canonical_object_type`
- `detection_key`
- `render_layer`
- `chart_render_type`
- `chart_priority`
## 12 工程版与交付版
建议分两种输出口径:
### 12.1 delivery schema
用途:前端渲染、检索、碰撞、正式交付。
保留:
- identity
- taxonomy
- render_semantics
- labels
- light
- hazard_area
- normalized_numeric
- 关键 `source_legacy`
### 12.2 engineering schema
用途:调试、抽查、问题复盘、映射核验。
在 delivery schema 基础上可额外保留:
- `fid_legacy_raw`
- `fid_algo_id`
- `fid_key_id`
- 更完整的原始 `at`
- 更多 `source_layer` / 原始属性
- 临时校验字段
## 13 v2 与当前 builder 的差距
当前 `navsea_tile_builder.py` 已经输出:
- 原始全部属性
- `canonical_object_type`
- `canonical_family`
- `semantic_key`
- `detection_key`
- `render_layer`
当前尚未系统输出的 v2 关键字段包括:
- `chart_render_type`
- `chart_symbol_family`
- `chart_symbol_code`
- `chart_line_style`
- `chart_fill_style`
- `chart_text_style`
- `chart_priority`
- `chart_visibility_min`
- `chart_visibility_max`
- `chart_label_*`
- `light_*`
- `hazard_*`
- `area_usage_class`
- `normalized_numeric`
这部分是 builder 下一阶段的主要补齐目标。

View File

@@ -0,0 +1,331 @@
# NavSea PBF v1 渲染语义契约草案
版本Draft v1
用途:用于 NavSea PBF 重构讨论与 Codex 实现参考
---
# 1 重构目标
NavSea 当前 PBF 渲染依赖大量旧海图编码字段,例如:
- 分類番号
- 形状分類番号
- 表示用番号
- 灯色
- 灯略記
- 明弧 / 分孤
- 表示位置
这些字段本质上是 **旧海图绘制编码**,而不是稳定的语义描述。
当前系统同时存在两种表达:
1. 旧海图渲染编码
2. 新的语义分类字段
但缺少一层专门表达 **“海图上应该如何表达该对象”** 的语义层。
因此本重构目标是建立:
NavSea PBF 的稳定 **渲染语义契约层**
---
# 2 三层模型
NavSea 渲染体系应拆分为三层:
## A 层:对象语义层
回答:
**这个对象是什么**
示例字段:
- canonical_object_type
- canonical_family
- detection_key
示例值:
- 港湾灯台
- 暗岩
- 魚礁
- 港則法境界
---
## B 层:渲染语义层
回答:
**在海图上应该如何表达**
示例字段:
- chart_render_type
- chart_symbol_family
- chart_symbol_code
- chart_priority
- chart_visibility_min
- chart_visibility_max
---
## C 层:样式实现层
由 MapLibre Style 决定:
- 颜色
- 线型
- 图标
- 填充
- 文字样式
样式层应尽量只依赖:
- chart_* 渲染语义字段
- 少量 legacy 字段
---
# 3 建议的核心渲染字段
## 3.1 主渲染字段
| 字段 | 类型 | 说明 |
|-----|------|------|
| chart_render_type | string | symbol / line / fill / label / none |
| chart_symbol_family | string | 符号族 |
| chart_symbol_code | string | 符号代码 |
| chart_priority | integer | 渲染优先级 |
| chart_visibility_min | integer | 最小显示 zoom |
| chart_visibility_max | integer | 最大显示 zoom |
---
## 3.2 标签字段
| 字段 | 类型 |
|-----|------|
| chart_label_text | string |
| chart_label_subtext | string |
| chart_label_anchor | string |
| chart_label_dx | number |
| chart_label_dy | number |
---
## 3.3 灯标字段
| 字段 | 类型 |
|-----|------|
| light_color_code | string |
| light_character_code | string |
| light_sector_mode | string |
| light_arc_code | string |
示例:
light_color_code = white
light_character_code = Fl
light_sector_mode = sector
---
## 3.4 危险物字段
| 字段 | 类型 |
|-----|------|
| hazard_class | string |
| hazard_severity | string |
hazard_class 示例:
- rock
- reef
- wreck
- obstruction
- shoal
hazard_severity 示例:
- critical
- major
- minor
- context
---
## 3.5 区域字段
| 字段 | 类型 |
|-----|------|
| area_usage_class | string |
示例:
- anchorage
- route
- fishery
- restricted
- facility
- land
- water
---
# 4 不建议直接写入 PBF 的字段
以下字段如果直接写入 PBF可能会锁死样式
- chart_line_style
- chart_fill_style
- chart_text_style
原因:
这些字段已经接近 **样式预设名称**,而不是语义。
例如:
depth_zone_0_5
boundary_dashed
place_name
未来若更换视觉风格,会产生耦合。
因此建议 PBF 只表达:
- line semantic
- fill semantic
- label role
具体视觉样式交由 Style 决定。
---
# 5 建议保留的 legacy 字段
为了兼容旧样式与历史数据,建议继续保留:
分類番号
形状分類番号
表示用番号
灯色
灯略記
明弧
分孤
表示位置
名称
名称補助
日本語地名
英文字地名
用途:
- 样式兜底
- 检索
- 历史兼容
---
# 6 Feature 示例
## 灯台
{
"fid": 12345678,
"canonical_object_type": "港湾灯台",
"canonical_family": "navigation_aid",
"detection_key": "symbol:港湾灯台",
"chart_render_type": "symbol",
"chart_symbol_family": "navigation_light",
"chart_symbol_code": "lighthouse",
"chart_priority": 900,
"chart_visibility_min": 7,
"chart_label_text": "鷹島灯台",
"chart_label_subtext": "Fl W 5s",
"light_color_code": "white",
"light_character_code": "Fl"
}## 鱼礁危险区
{
"fid": 23456789,
"canonical_object_type": "魚礁",
"canonical_family": "hazard",
"detection_key": "mixed:魚礁",
"chart_render_type": "fill",
"chart_symbol_family": "hazard",
"chart_symbol_code": "reef_area",
"hazard_class": "reef",
"hazard_severity": "major",
"chart_priority": 850
}
---
# 7 建议的实现顺序
阶段 1
出瓦片流程新增 chart_* 字段。
阶段 2
PBF 同时包含:
- 新 taxonomy 字段
- 新 chart semantics
- legacy 字段
阶段 3
样式优先读取:
chart_render_type
chart_symbol_family
chart_symbol_code
缺失时回退 legacy 字段。
阶段 4
逐步减少样式对 legacy 编码依赖。
---
# 8 第一阶段优先实现对象
建议优先完成四类对象:
1 灯标 / 航标
2 危险点对象
3 危险面对象(鱼礁 / 礁盘 / 障碍区)
4 边界对象
原因:
这些对象最依赖旧编码,也是最复杂的渲染类型。
---
# 9 结论
NavSea PBF 不应继续依赖旧海图编码作为核心渲染逻辑。
正确方向是:
**原始属性****样式实现** 之间建立稳定的 **渲染语义层**
该层应:
- 表达稳定语义
- 不锁定具体视觉样式
- 支持新旧样式共存
- 为检测、检索、渲染提供统一数据面

View File

@@ -0,0 +1,334 @@
# NavSea 可逆标准化审计方案 v1
版本v1 Draft
用途:定义 NavSea 可逆标准化规则的审计方案,用于验证标准化过程是否完整、可逆、稳定、可重复、对渲染无破坏。
## 1 审计目标
本审计方案要验证五件事:
- 原始信息有没有丢
- 标准化规则有没有被正确应用
- 每个结果能不能回查
- 同一规则重复执行是否稳定
- 标准化后渲染和业务能力有没有被破坏
## 2 审计对象
审计覆盖以下对象:
- 规则文件
- SQL 规则表
- feature trace 表
- delivery `pbf`
- engineering `pbf`
- style 消费关系
## 3 审计维度
## 3.1 完整性审计
检查是否所有需要标准化的对象都进入了规则体系。
检查项:
- 每个实际出现的 `source_layer_jp` 都有标准化规则
- 每个实际出现的关键原始字段都有保留策略
- 每个 delivery feature 都有对应 trace
## 3.2 可逆性审计
检查是否能从标准值回查原始值。
检查项:
- `source_layer_std` 是否能映射回 `source_layer_jp`
- 标准化字段是否有对应规则 ID
- feature 是否能查到 bundle 版本
## 3.3 稳定性审计
检查相同输入在相同规则版本下是否得到相同输出。
检查项:
- 同一输入重复运行结果一致
- 同一 `rule_id + revision` 输出不漂移
## 3.4 渲染兼容审计
检查标准化后是否破坏当前样式表现。
检查项:
- style 引用的 layer 是否仍然存在
- 关键对象是否仍能显示
- 旧兼容表现是否没有异常缩水
## 3.5 业务可用性审计
检查标准化后是否仍满足检索、碰撞、点击、排障需求。
检查项:
- `fid` 是否保留
- taxonomy 字段是否保留
- 关键内容型日文字段是否保留
- trace 是否可回查
## 4 审计表设计
建议新增以下审计表:
- `navsea_normalization_audit_run`
- `navsea_normalization_coverage_audit`
- `navsea_normalization_reversibility_audit`
- `navsea_normalization_stability_audit`
- `navsea_render_compatibility_audit`
## 5 每次审计运行应记录
建议在 `navsea_normalization_audit_run` 中记录:
- `audit_run_id`
- `bundle_id`
- `bundle_version`
- `source_snapshot`
- `target_scope`
- `started_at`
- `finished_at`
- `status`
- `notes`
## 6 审计检查项
## 6.1 规则覆盖检查
目标:确认没有“实际数据里出现,但没有规则”的对象。
建议 SQL
- 所有实际出现的 `source_layer_jp`
- 左连接 `navsea_source_layer_rules`
- 找出未命中项
通过标准:
- 未命中数量必须为 `0`
## 6.2 原值保留检查
目标:确认原始关键字段没有在工程体系中丢失。
检查字段:
- `fid`
- `fid_legacy_raw`
- `source_layer_jp`
- `分類番号`
- `形状分類番号`
- `表示用番号`
- `名称`
- `日本語地名`
- `at_raw`
通过标准:
- engineering 口径中必须可回查
## 6.2.1 `fid` 可逆检查
目标:确认 NavSea 自有 `fid` 不是旧 `fid` 原样外露,且能可逆回查。
检查项:
- `delivery` / `engineering``fid` 是否为 16 进制字符串
- `fid_legacy_raw` 是否保留于 engineering / trace
- `fid_algo_id` 是否存在
- `fid_key_id` 是否存在
- 是否可通过 `decrypt_number``fid_navsea_int` 还原 `fid_legacy_raw`
通过标准:
- 抽样回解正确率必须为 `100%`
- 不允许出现“新 `fid` 与旧 `fid` 只是格式改写”的情况
## 6.3 规则追溯检查
目标:确认每个标准化结果都有 trace。
检查项:
- `source_layer_std` 是否有 `source_layer_rule_id`
- `canonical_object_type` 是否有 `taxonomy_rule_id`
- `chart_*` 是否有 `render_rule_id`
通过标准:
- 关键标准化字段 trace 覆盖率必须达到 `100%`
## 6.4 可逆回查检查
目标:确认能从标准值回查原值。
抽样要求:
- 随机抽样 `fid`
- 随机抽样 `source_layer_std`
- 随机抽样 `canonical_object_type`
- 随机抽样 `chart_symbol_code`
检查:
- 是否能回查 `fid_legacy_raw`
- 是否能回查原始 `source_layer_jp`
- 是否能回查 `source_fields_used_json`
- 是否能回查规则文件版本
## 6.5 重放一致性检查
目标:确认相同输入反复执行不会漂移。
方法:
1. 使用同一 bundle 版本运行两次
2. 比较以下字段:
- `source_layer_std`
- `canonical_family`
- `canonical_object_type`
- `detection_key`
- `chart_render_type`
- `chart_symbol_code`
通过标准:
- 差异率必须为 `0`
## 6.6 delivery / engineering 差异检查
目标:确认 delivery 简化没有破坏回查能力。
检查项:
- delivery 是否去掉了一部分原值字段
- engineering 是否仍保留完整 trace
- 是否能通过 `fid` 从 delivery 回查到 engineering / SQL trace
通过标准:
- 回查链条必须完整
## 6.7 渲染覆盖检查
目标:确认标准化后 style 仍消费当前存在的 `source-layer`
检查项:
- 数据侧实际 `source-layer` 集合
- 样式侧引用的 `source-layer` 集合
- 差集
通过标准:
- 若目标是“全覆盖样式”,差集必须为 `0`
- 若目标是“有意忽略样式”,必须给出 ignore 清单和理由
## 7 审计输出
每次审计至少输出四类结果:
### 7.1 覆盖报告
内容:
- 实际 `source-layer`
- 已映射数量
- 未映射数量
- 未映射列表
### 7.2 可逆性报告
内容:
- 可回查率
- 无 trace feature 数量
- 缺失规则 ID 数量
### 7.3 稳定性报告
内容:
- 两次重放差异数
- 差异字段分布
- 受影响 feature 列表
### 7.4 渲染兼容报告
内容:
- style 消费的 `source-layer`
- 数据存在但样式未消费的层
- 关键对象抽样截图或抽样核验结果
## 8 审计频率
建议分三类:
### 8.1 每次规则变更后
必须执行:
- 规则覆盖检查
- 规则追溯检查
- 可逆回查检查
### 8.2 每次大批量构建后
必须执行:
- delivery / engineering 差异检查
- 渲染覆盖检查
- 抽样渲染兼容检查
### 8.3 每次 bundle 升级前
必须执行:
- 重放一致性检查
- 差异审计
## 9 不通过条件
出现以下任一情况,审计应判定不通过:
- 实际出现的 `source-layer` 无规则
- 关键标准化字段无 trace
- 无法从标准值回查原值
- 同版本重复执行结果漂移
- delivery 无法通过 `fid` 回查 engineering / SQL trace
- 样式消费覆盖与目标不符且无明确豁免
## 10 v1 最低可执行方案
如果要先快速落地,建议第一阶段至少做到:
1.`source-layer` 标准化规则表
2.`fid` 标准化规则文件和 `fid` 可逆回查检查
3. 在 trace 表中补 `source_layer_rule_id`
4. 建立 `source_layer_jp -> source_layer_std` 覆盖审计
5. 建立 `fid -> trace` 回查检查
6. 每次样式更新都跑 `source-layer` 覆盖差集
## 11 结论
NavSea 的可逆标准化不能只靠规则文档存在,必须配套审计。
审计的核心不是“看起来转换成功”,而是验证:
- 原值未丢
- 规则有据
- 结果可回查
- 重放可一致
- 渲染不被破坏
只有规则和审计同时成立,标准化这件事才算真正严谨。

View File

@@ -0,0 +1,356 @@
# NavSea 可逆标准化规则 v1
版本v1 Draft
用途:定义 NavSea 在“日文原始数据 -> 标准化字段/层名/渲染语义”过程中必须遵循的可逆标准化规则,确保转换严谨、可追溯、可回退、可重复执行。
## 1 目标
NavSea 的标准化不是“清洗掉旧数据”,而是:
- 保留原始信息
- 新增标准化结果
- 记录完整映射过程
- 允许从标准化结果反查原始值
一句话原则:
> 标准化只能增加表达层,不能破坏原始信息层。
## 2 适用范围
本规则适用于以下对象:
- 日文 `source-layer`
- 原始日文字段名
- 原始日文字段值
- taxonomy 标准化字段
- render 语义字段
- 输出 `pbf`
- SQL 规则表与 trace 表
## 3 核心原则
### 3.1 原始值不可丢
所有参与标准化的关键输入都必须有原始保留位。
包括但不限于:
- 原始 `source-layer`
- 原始字段名
- 原始字段值
- 原始 `at`
- 原始 `fid`
### 3.2 标准化结果必须新增,不可覆盖原值
禁止直接把原值物理改写成标准值后不留痕迹。
正确做法:
- 原值保留
- 标准值新增
- 二者由规则表与 trace 表关联
### 3.3 每一步标准化都必须有规则来源
任何标准化结果都必须能回答:
- 是哪条规则做的
- 规则版本是什么
- 使用了哪些原始字段
### 3.4 每一步标准化都必须可逆
可逆的含义不是“自动完全恢复所有原始结构”,而是:
- 能从标准值回查原始值
- 能从 feature 回查到规则和版本
- 能重演同一批输入得到同一批输出
### 3.5 delivery 可以简化engineering 不可失真
delivery `pbf` 可以只暴露必要字段。
但 engineering `pbf` / SQL 审计表必须保留足够信息,支持回查。
## 4 不可做的事
以下操作在 v1 规则下视为禁止:
- 直接删除原始 `source-layer`,且不保留 `source_layer_jp`
- 直接删除原始字段值,且不保留原值副本
- 在 SQL 里手工改结果,不回写规则文件
- 在代码里加临时 if 分支,不形成规则 ID 和版本
- 只保留标准化结果,不保留 trace
## 5 字段分层
NavSea 标准化后,字段应分成三层。
### 5.1 原始层
职责:完整保留输入信息。
建议字段:
- `source_layer_jp`
- `original_properties_json`
- `at_raw`
- `fid`
- 原始 `分類番号`
- 原始 `形状分類番号`
- 原始 `表示用番号`
- 原始 `名称`
- 原始 `日本語地名`
### 5.2 标准化层
职责:输出结构化、可消费的标准字段。
建议字段:
- `source_layer_std`
- `canonical_family`
- `canonical_object_type`
- `detection_key`
- `chart_render_type`
- `chart_symbol_family`
- `chart_symbol_code`
- `chart_line_style`
- `chart_fill_style`
- `chart_text_style`
### 5.3 trace 层
职责:连接“原始层”和“标准化层”。
建议字段:
- `normalization_bundle_id`
- `source_layer_rule_id`
- `taxonomy_rule_id`
- `render_rule_id`
- `rule_revision`
- `source_fields_used_json`
- `trace_status`
## 6 可逆标准化对象
## 6.1 `source-layer` 标准化
建议采用双字段:
- `source_layer_jp`
- `source_layer_std`
示例:
- `source_layer_jp = P錨泊地等`
- `source_layer_std = anchorage_area`
要求:
- 原始日文层名不可直接丢弃
- 标准层名必须来自规则表,不得手工散落在代码里
## 6.1.1 `fid` 标准化
NavSea 不应直接对外继续使用旧版原始 `fid` 作为最终对象 ID。
规则要求:
- `delivery` / `engineering` 对外主 `fid` 使用 NavSea 自有 `fid`
- NavSea 自有 `fid` 由旧版 `fid``tasks/pbf/fiddecode.md` 中的可逆算法生成
- 生成结果使用 16 进制字符串表达
建议定义:
- `fid_legacy_raw`:旧版原始整数 `fid`
- `fid_navsea_int`:经过可逆加密后的非负整数
- `fid`:最终对外使用的 16 进制字符串,例如固定宽度大写 HEX
- `fid_algo_id`:例如 `feistel32_aes_cyclewalk_v1`
- `fid_key_id`:用于标识采用了哪把密钥
建议生成规则:
1. 读取旧版 `fid`
2. 使用 `fiddecode.md` 中的 `encrypt_number` 算法生成 `fid_navsea_int`
3.`fid_navsea_int` 编码为固定宽度 16 进制字符串
4. 在 engineering / trace 中保留 `fid_legacy_raw`
补充口径:
- `fid` 可逆算法沿用 `fiddecode.md` 中的 Feistel + AES cycle-walking 方案
- 为保证对真实历史数据全覆盖,工程实现应采用 `signed int32` 全域
- 不应把示例文档中的局部样本范围误当成生产限制
要求:
- `fid` 必须可逆回查到 `fid_legacy_raw`
- 不允许只保留新 `fid`,却丢失旧 `fid`
- 不允许直接把旧 `fid` 原样转成 HEX 当作“新 `fid`
## 6.2 原始字段名标准化
对原始字段名建议也采用双字段表达。
例如:
- `field_name_jp = 形状分類番号`
- `field_name_std = shape_class_code`
注意:
- 这里只是定义映射关系
- 不代表 delivery `pbf` 必须立刻把所有原字段名换掉
## 6.3 原始字段值标准化
例如:
- `灯色 = 1` -> `light_color_code = white`
- `形状分類番号 = 335` -> `nav_mark_variant = vais`
要求:
- 原值保留
- 标准值新增
- 必须记录规则 ID
## 7 保留策略
## 7.1 必须保留的原始日文内容
以下属于“内容型日文”,不能因为标准化就删除:
- `名称`
- `名称補助`
- `日本語地名`
- `灯略記`
- 其他对展示、检索、业务解释有价值的原始说明文本
## 7.2 可标准化但需保留原值的结构型日文
以下属于“结构型日文”,可以标准化,但必须保留原值:
- 日文 `source-layer`
- 原始字段名
- `at` 中的结构型键值
- 旧样式直接消费的技术性编码字段
## 7.3 delivery 可隐藏engineering 必保留
对结构型日文建议:
- delivery `pbf` 可以只暴露标准字段
- engineering `pbf` / SQL 审计表必须保留原值和映射关系
## 8 规则文件要求
为保证可逆与可重复,以下规则必须文件化:
- `source-layer` 标准化规则
- taxonomy 规则
- render 规则
- 字段名标准化规则
- 字段值标准化规则
建议目录:
```text
tasks/pbf/mappings/
navsea_fid_rules_v1.yaml
navsea_source_layer_rules_v1.yaml
navsea_taxonomy_rules_v1.yaml
navsea_render_rules_v1.yaml
navsea_field_name_rules_v1.yaml
navsea_field_value_rules_v1.yaml
navsea_rule_bundle_v1.yaml
```
## 9 SQL 结构要求
为保证可逆与可查询,建议至少有以下表:
- `navsea_rule_bundle`
- `navsea_source_layer_rules`
- `navsea_taxonomy_rules`
- `navsea_render_rules`
- `navsea_field_name_rules`
- `navsea_field_value_rules`
- `navsea_feature_rule_trace`
## 10 feature trace 最低要求
每个被标准化的 feature 至少应记录:
- `feature_id`
- `fid`
- `fid_legacy_raw`
- `fid_navsea_int`
- `fid_algo_id`
- `fid_key_id`
- `source_layer_jp`
- `source_layer_std`
- `normalization_bundle_id`
- `source_layer_rule_id`
- `taxonomy_rule_id`
- `render_rule_id`
- `source_fields_used_json`
- `trace_status`
## 11 delivery / engineering 输出要求
## 11.1 delivery pbf
目的:给前端渲染和检索使用。
要求:
- 可适度简化字段
- 但不能影响业务使用
- 若隐藏原值,必须仍可通过 SQL trace 回查
## 11.2 engineering pbf
目的:审计、复盘、问题定位。
要求:
- 保留原值
- 保留标准值
- 保留规则 ID
- 保留 bundle 版本
## 12 可逆性验收条件
只有同时满足以下条件,才可称为“可逆标准化”:
1. 能从标准值回查原始值
2. 能从 feature 回查规则 ID 和版本
3. 能重放同一批输入并得到同一批输出
4. 原始内容型日文未被误删
5. delivery 的简化不影响 engineering 的回查能力
## 13 v1 落地建议
第一阶段建议先做到:
1. 所有日文 `source-layer` 增加 `source_layer_std`
2. `fid` 改为 NavSea 自有 16 进制 `fid`
3. 新增 `fid` 规则文件和 `fid` trace 字段
4. 新增 `source-layer` 规则文件
5. 在 trace 表中记录 `source_layer_rule_id`
6. 保留原始内容型日文字段
7. 严禁在没有 trace 的情况下直接删除原始结构字段
## 14 结论
NavSea 的标准化必须是:
- 可逆的
- 可追溯的
- 可重复执行的
- 区分原始层、标准化层和 trace 层的
换句话说,标准化不是“替换”,而是“带证据的映射”。

View File

@@ -0,0 +1,30 @@
# NavSea Object → Render Mapping Table v1
版本v1 Draft
用途:定义对象语义到渲染语义的映射。
canonical_object_type → chart_render_type / chart_symbol_family / chart_symbol_code
## 灯标
| canonical_object_type | render_type | symbol_family | symbol_code |
|---|---|---|---|
| 港湾灯台 | symbol | navigation_light | lighthouse |
| 灯柱 | symbol | navigation_light | light_beacon |
| 灯浮標 | symbol | navigation_light | light_buoy |
## 危险物
| canonical_object_type | render_type | symbol_family | symbol_code |
|---|---|---|---|
| 暗岩 | symbol | hazard | rock_awash |
| 岩礁 | symbol | hazard | reef |
| 沈船 | symbol | hazard | wreck |
| 障害物 | symbol | hazard | obstruction |
## 区域
| canonical_object_type | render_type | symbol_family | symbol_code |
|---|---|---|---|
| 魚礁 | fill | hazard | reef_area |
| 錨地 | fill | usage_area | anchorage_area |

View File

@@ -0,0 +1,165 @@
# NavSea Object -> Render Mapping Table v2
版本v2 Draft
用途:定义对象语义到渲染语义的映射规则,作为 `taxonomy -> render_semantics` 的中间规范。
## 1 设计原则
- 先按 `canonical_object_type` 映射
- 再按几何类型和旧字段细化具体样式
- 样式层优先读取 `chart_*` 字段
- 旧字段只保留为细节兜底,不再作为主判定入口
## 2 输出字段
映射表的目标输出至少包括:
- `chart_render_type`
- `chart_symbol_family`
- `chart_symbol_code`
- `chart_line_style`
- `chart_fill_style`
- `chart_text_style`
- `chart_priority`
- `chart_label_text`
- `chart_label_subtext`
- `light_color_code`
- `light_character_code`
- `hazard_class`
- `hazard_severity`
- `area_usage_class`
## 3 首批强制覆盖对象
下表是建议优先落地的 v2 核心映射对象。
| canonical_family | canonical_object_type | geometry | chart_render_type | symbol_family | symbol_or_style | priority | legacy_detail_dependency |
| --- | --- | --- | --- | --- | --- | --- | --- |
| navigation_aid | 港湾灯台 | Point | symbol | navigation_light | `chart_symbol_code=lighthouse` | 900 | `灯色` `灯略記` `表示用番号` |
| navigation_aid | 灯柱 | Point | symbol | navigation_light | `chart_symbol_code=light_beacon` | 890 | `灯色` `灯略記` `形状分類番号` |
| navigation_aid | 灯浮標 | Point | symbol | navigation_light | `chart_symbol_code=light_buoy` | 880 | `灯色` `灯略記` `形状分類番号` |
| navigation_aid | AIS航标 | Point | symbol | navigation_light | `chart_symbol_code=vais` | 870 | `表示用番号` |
| navigation_aid | 浮標 | Point | symbol | navigation_mark | `chart_symbol_code=buoy` | 860 | `形状分類番号` `表示用番号` |
| navigation_aid | 立標 | Point | symbol | navigation_mark | `chart_symbol_code=beacon` | 860 | `形状分類番号` `表示用番号` |
| hazard | 暗岩 | Point | symbol | hazard | `chart_symbol_code=rock_awash` | 910 | `分類番号` |
| hazard | 岩礁 | Point | symbol | hazard | `chart_symbol_code=reef` | 900 | `分類番号` |
| hazard | 礁盘 | Polygon | fill | hazard | `chart_fill_style=reef_area` | 860 | `分類番号` |
| hazard | 魚礁 | Polygon | fill | hazard | `chart_fill_style=reef_area` | 850 | `分類番号` `表示用番号` |
| hazard | 沈船 | Point | symbol | hazard | `chart_symbol_code=wreck` | 905 | `分類番号` |
| hazard | 障害物 | Point | symbol | hazard | `chart_symbol_code=obstruction` | 895 | `分類番号` |
| hazard | 潜堤 | Line/Polygon | line/fill | hazard | `chart_line_style=submerged_reef` / `chart_fill_style=hazard_area` | 845 | `分類番号` |
| depth | 水深点 | Point | label | depth_mark | `chart_text_style=depth_text` | 700 | `水深値(m)` |
| depth | 水深区 | Polygon | fill | depth_zone | `chart_fill_style=depth_zone_*` | 650 | `分類番号` |
| depth | 等深线 | LineString | line | contour | `chart_line_style=contour_major_or_minor` | 640 | `表示用番号` |
| depth | 概略等深线 | LineString | line | contour | `chart_line_style=contour_overview` | 620 | `表示用番号` |
| boundary | 危険界 | LineString | line | boundary | `chart_line_style=hazard_boundary` | 800 | `分類番号` |
| boundary | 基本线 | LineString | line | boundary | `chart_line_style=baseline` | 780 | `分類番号` |
| boundary | 航路境界 | LineString | line | boundary | `chart_line_style=route_boundary` | 770 | `分類番号` |
| usage_area | 航路 | Polygon/LineString | fill/line | usage_area | `chart_fill_style=route_area` / `chart_line_style=route_axis` | 760 | `分類番号` |
| usage_area | 錨地 | Polygon | fill | usage_area | `chart_fill_style=anchorage_area` | 750 | `分類番号` |
| usage_area | 錨泊地 | Polygon | fill | usage_area | `chart_fill_style=anchorage_area` | 750 | `分類番号` |
| usage_area | 漁業区 | Polygon | fill | usage_area | `chart_fill_style=fishery_area` | 740 | `分類番号` |
| usage_area | パイロットステーション | Point | symbol | usage_area | `chart_symbol_code=pilot_station` | 735 | `表示用番号` |
| facility | 防波堤 | LineString/Polygon | line/fill | facility | `chart_line_style=breakwater` | 730 | `分類番号` |
| facility | 橋梁 | LineString | line | facility | `chart_line_style=bridge` | 725 | `高さ(m)` |
| facility | 海底电缆 | LineString | line | facility | `chart_line_style=subsea_cable` | 720 | `分類番号` |
| facility | 高さ制限 | Point/LineString | label/line | facility | `chart_text_style=clearance_label` | 715 | `高さ(m)` `高さ/深度(m)` |
| seabed | 底質 | Point | label | seabed | `chart_text_style=seabed_text` | 500 | `名称` |
| place | 海上地名 | Point | label | place | `chart_text_style=place_name_sea` | 450 | `日本語地名` `英文字地名` |
| place | 陆上地名 | Point | label | place | `chart_text_style=place_name_land` | 440 | `日本語地名` `英文字地名` |
## 4 细化规则
### 4.1 灯标对象
主映射依据:
- `canonical_object_type`
细化字段:
- `灯色 -> light_color_code`
- `灯略記 -> light_character_code``chart_label_subtext`
- `名称 -> chart_label_text`
- `表示用番号` / `形状分類番号` 决定具体 icon 变体
说明:
- 灯弧不必作为核心渲染对象单独保留
-`明弧/分孤` 可以继续保留,用于特殊产品或工程校验
### 4.2 危险物
主映射依据:
- `canonical_object_type`
细化输出:
- `hazard_class`
- `hazard_severity`
建议:
- `暗岩``沈船` 默认 `hazard_severity >= major`
- `魚礁` 按区域危险对象处理,但允许叠加 `area_usage_class=fishery`
### 4.3 水深和等深线
建议:
- 水深点统一转成 `chart_render_type=label`
- 水深区统一转成 `chart_render_type=fill`
- 等深线和概略等深线统一转成 `chart_render_type=line`
细化:
- `表示用番号` 或原 line layer 类型决定 `contour_major` / `contour_minor` / `contour_overview`
### 4.4 边界和区域
建议:
- “区域本体”与“边界线”分别映射
- 航路、锚地、鱼业区优先落到 `usage_area`
- 基本线、危险界、航路境界优先落到 `boundary`
## 5 label 映射规则
| 对象类型 | chart_label_text | chart_label_subtext | chart_text_style |
| --- | --- | --- | --- |
| 港湾灯台 / 灯柱 / 灯浮標 | `名称` | `灯略記` | `light_label` |
| 水深点 | 格式化 `depth_value_m` | 空 | `depth_text` |
| 海上地名 | `日本語地名` 优先,其次 `英文字地名` | 空 | `place_name_sea` |
| 陆上地名 | `日本語地名` 优先,其次 `英文字地名` | 空 | `place_name_land` |
| 高さ制限 | 规范化高度文本 | 空 | `clearance_label` |
## 6 v2 映射必须输出的附加字段
除了图形类型本身,映射表还应尽量输出:
- `chart_priority`
- `chart_visibility_min`
- `chart_visibility_max`
- `chart_collision_group`
原因:
- 这些字段能把样式层里的很多散乱 zoom/filter 规则收回到数据侧
## 7 v2 当前缺口
相较 v1本表仍需继续扩充以下对象
- 导灯
- 灯船
- 信号所
- 制限区域
- 未测深区
- 干出区
- 海底管线
- 岸壁 / 栈桥 / 码头
- 海底线
- 水文现象对象
这些建议作为 v2.1 的扩展项。

View File

@@ -0,0 +1,56 @@
# NavSea Taxonomy v1对象语义分类体系
版本v1 Draft
用途:定义 NavSea 的对象语义分类Object Taxonomy
taxonomy 只回答一个问题:
> 这个对象是什么
而不涉及如何绘制。
## 结构
canonical_family → canonical_object_type
## canonical_family
- navigation_aid 航标
- buoy 浮标
- hazard 危险物
- depth 水深
- boundary 边界
- facility 港口设施
- usage_area 使用区域
- landmark 地标
- place 地名
- seabed 海床
- hydro_feature 水文现象
## 示例
navigation_aid
- 灯台
- 港湾灯台
- 灯柱
- 灯浮標
- AIS航标
hazard
- 暗岩
- 岩礁
- 礁盘
- 沈船
- 障害物
- 危険物
- 浅滩
depth
- 水深点
- 水深区
- 等深线
taxonomy 与渲染无关。

View File

@@ -0,0 +1,306 @@
# NavSea Taxonomy v2
版本v2 Draft
用途:定义 NavSea 的对象语义分类体系Object Taxonomy为渲染、检索、碰撞检测和统计分析提供稳定的对象身份。
taxonomy 只回答一个问题:
> 这个对象是什么
taxonomy 不直接回答怎么画,也不直接替代旧海图字段。
## 1 设计原则
### 1.1 taxonomy 与 render 分层
- `canonical_family` / `canonical_object_type` 负责语义归类
- `chart_*` 字段负责渲染表达
- 旧字段如 `分類番号``形状分類番号``表示用番号` 仍可在过渡期保留,用于兼容旧样式细节
### 1.2 family 必须互斥
`canonical_family` 必须尽量稳定、互斥、可统计。
例如:
- `buoy` 不再单独作为 family
- 灯浮标、灯柱、灯台、AIS 航标统一归到 `navigation_aid`
- `place` 只表示地名,不包含设施或标志物
### 1.3 object_type 可以细分
`canonical_object_type` 允许保留更细粒度的对象名,用于:
- 检索
- 规则判断
- 语义统计
- 到渲染语义的映射
## 2 taxonomy 层级
结构:
`canonical_family -> canonical_object_type`
## 3 canonical_family 定义
### 3.1 navigation_aid
定义:用于导航指示、警示、定位或电子助航的对象。
典型 object_type
- 灯台
- 港湾灯台
- 灯柱
- 灯浮標
- 導灯
- 灯船
- 浮標
- 立標
- AIS航标
- 信号所
说明:
- 原 v1 中的 `buoy` 并入本 family
- “浮标是不是灯浮标”属于 object_type 层的问题,不在 family 层拆开
### 3.2 hazard
定义:对航行、锚泊或作业形成风险的对象、区域或状态。
典型 object_type
- 暗岩
- 岩礁
- 礁盘
- 魚礁
- 沈船
- 障害物
- 危険物
- 浅滩
- 潜堤
- 洞穴/穴
说明:
- 鱼礁虽然可能带有利用属性,但从航行风险角度优先归到 `hazard`
- 若后续需要区分“危险物”和“人工利用构造”,可通过 `hazard_class``area_usage_class` 细分,而不是拆 family
### 3.3 depth
定义:描述水深、水深区、等深线和相关深度表达的对象。
典型 object_type
- 水深点
- 水深区
- 等深线
- 概略等深线
- 干出区
- 未测深区
### 3.4 boundary
定义:描述法律、管理、航路或危险范围边界的对象。
典型 object_type
- 基本线
- 危険界
- 航路境界
- 港則法による境界
- 制限区域境界
- 管辖边界
### 3.5 facility
定义:人工建造的固定设施、结构物和工程对象。
典型 object_type
- 防波堤
- 岸壁
- 栈桥
- 桥梁
- 海底电缆
- 海底管线
- 陆上构造物
- 水上设施
说明:
- “设施”与“边界”分离
- “设施”与“地标”分离
### 3.6 usage_area
定义:表达水域或区域用途、限制或功能属性的对象。
典型 object_type
- 錨地
- 錨泊地
- 漁業区
- 航路
- パイロットステーション
- 禁止区域
- 制限区域
说明:
- 如果对象主要表达“用途”而不是“实体构造”,优先归到本 family
### 3.7 landmark
定义:用于识别、定位或视觉参照的显著对象,但不属于典型助航设施。
典型 object_type
- 山顶
- 烟囱
-
- 目标物
- 显著建筑
### 3.8 place
定义:地名和位置名称。
典型 object_type
- 海上地名
- 陆上地名
- 岬角地名
- 港名
说明:
- 只表示名称,不表示实体类别
-`facility` 分离,避免“有名字的设施”误归到 place
### 3.9 seabed
定义:描述海床性质、底质和海底表面特征的对象。
典型 object_type
- 底質
- 海底地形
- 海底线
### 3.10 hydro_feature
定义:描述流、潮、涌浪、水流方向等水文现象的对象。
典型 object_type
- 潮流
- 流向
- 渦流
- 浪向
## 4 taxonomy 命名规则
### 4.1 family 命名
- 使用稳定英文 snake_case
- 面向系统处理
- 不与具体样式实现耦合
### 4.2 object_type 命名
- 允许使用与业务更贴近的中文或日文对象名
- 但同义词必须收敛到单一标准写法
建议:
- 输出层面统一使用当前已采用的 `canonical_object_type`
- 数据治理时维护“原始名 -> 标准对象名”的映射表
## 5 v2 首批强制覆盖对象
以下对象建议作为 v2 taxonomy 的首批强制覆盖范围,因为它们同时影响旧样式兼容和后续语义渲染:
- 港湾灯台
- 灯柱
- 灯浮標
- AIS航标
- 暗岩
- 岩礁
- 礁盘
- 魚礁
- 沈船
- 障害物
- 潜堤
- 水深点
- 水深区
- 等深线
- 概略等深线
- 危険界
- 基本线
- 航路
- 航路境界
- 錨地
- 錨泊地
- 漁業区
- 防波堤
- 橋梁
- 海底电缆
- 底質
- 海上地名
- 陆上地名
- 高さ制限
## 6 taxonomy 与旧字段的关系
taxonomy 不替代旧字段,但要尽量减少下游直接理解旧字段的负担。
建议职责划分如下:
- `canonical_family`:供统计、筛选、检索、碰撞分类使用
- `canonical_object_type`:供精细语义判断和渲染映射使用
- 旧字段:仅在兼容旧样式细节时保留
## 7 v2 边界决策
### 7.1 不再单独使用 buoy family
原因:
- 会与 `navigation_aid` 重叠
- 对检索和渲染映射帮助有限
### 7.2 鱼礁优先归到 hazard
原因:
- 当前产品目标明确包含碰撞检测
- 航行风险语义优先级高于用途语义
补充表达:
- 若需要表达作业用途,可通过渲染语义或 `area_usage_class=fishery` 补充
### 7.3 航路归到 usage_area航路边界归到 boundary
原因:
- 区分“区域本身”和“边界线”
- 有利于样式层分别控制 fill 和 line
## 8 v2 输出要求
每个交付 feature 至少应满足:
-`canonical_family`
-`canonical_object_type`
-`detection_key`
如果对象未完成 taxonomy 映射,不能直接输出为空,应至少回退到:
- `canonical_family = unknown`
- `canonical_object_type = 未分类对象`
并进入后续人工补录清单。

View File

@@ -0,0 +1,21 @@
# NavSea Tile Generation Pipeline v1
描述 NavSea 从原始数据到 Vector Tile 的流程。
raw hydro data
taxonomy classification
canonical_object_type
render mapping table
chart semantic fields
vector tile PBF
MapLibre style rendering
该流程实现:
数据 → 语义 → 渲染 → 屏幕。

View File

@@ -0,0 +1,249 @@
# NavSea Tile Generation Pipeline v2
版本v2 Draft
用途:定义 NavSea 从原始海图数据到交付 Vector Tile 的生产流程和质量要求。
## 1 目标
v2 pipeline 不是简单“改字段名”,而是把交付链路明确拆成:
`原始数据 -> 语义分类 -> 渲染语义 -> 字段物化 -> PBF 交付 -> 样式渲染`
同时满足:
- 旧内容兼容
- 新样式迁移
- 检索和碰撞可用
- 工程可验证
## 2 输入
### 2.1 原始输入
- 原始 Vector Tile`/home/wwwroot/newpec/exported_auto/tile.mapple-on.jp__newpec-mvt-20260106__z___x___y_.pbf/tiles`
- 原始要素属性:包括 `fid``分類番号``形状分類番号``表示用番号``名称``灯色`
### 2.2 数据库输入
当前数据库中已具备或部分具备:
- taxonomy 归类结果
- render_layer 归并结果
- detection 分类结果
现有 builder 查询表:
- `pbf_relayer_candidates`
- `properties`
## 3 输出类型
建议把输出分成两类:
### 3.1 delivery tiles
用途:
- 正式渲染
- 检索
- 碰撞检测
要求:
- 保留关键旧字段
- 输出稳定 taxonomy 字段
- 输出新的 render_semantics 字段
- 不包含过量调试字段
### 3.2 engineering tiles
用途:
- 抽样校验
- 问题定位
- 新旧比对
要求:
- 可保留更完整的原始字段
- 可保留更多校验字段
## 4 v2 标准流程
### 步骤 1读取原始瓦片
`z/x/y` 读取原始 `.pbf`,解码所有 source layer。
要求:
- 保留每个 source layer 的原始 extent
- 不改变 feature geometry
### 步骤 2按 fid/source_layer/geom_type 关联数据库记录
建议匹配键:
- `fid`
- `source_layer`
- `geom_type`
目的:
- 将原始 feature 与数据库里的 taxonomy / detection / render_layer 结果稳定关联
### 步骤 3taxonomy 物化
输出:
- `canonical_family`
- `canonical_object_type`
- `detection_key`
- `semantic_key`(可选)
要求:
- 未命中 taxonomy 的对象要进入 fallback 分类
- 不允许静默输出空语义
### 步骤 4render mapping 物化
依据:
- `canonical_object_type`
- 几何类型
- 必要旧字段
输出:
- `chart_render_type`
- `chart_symbol_family`
- `chart_symbol_code`
- `chart_line_style`
- `chart_fill_style`
- `chart_text_style`
- `chart_priority`
- `chart_visibility_min`
- `chart_visibility_max`
### 步骤 5label / light / numeric 归一化
输出:
- `chart_label_text`
- `chart_label_subtext`
- `light_color_code`
- `light_character_code`
- `depth_value_m`
- `clearance_height_m`
- `least_depth_m`
- `bearing_deg`
要求:
- 同类对象统一字段命名
- 尽量避免样式和检索继续直接解析原始文本字段
### 步骤 6决定输出 layer
建议优先级:
1. 使用数据库已确定的 `render_layer`
2. 若无 `render_layer`,按渲染语义计算默认层
3. 再不行才回退原 `source_layer`
说明:
- v2 的长期方向是减少直接依赖旧 source layer 命名
- 但过渡期允许回退,保证旧 style 不崩
### 步骤 7编码输出 PBF
要求:
- 保持原 feature geometry 不变
- 保持原 layer extent 不变
- 输出写入目标目录 `/home/wwwroot/pbf/{z}/{x}/{y}.pbf`
## 5 质量门禁
v2 pipeline 必须增加明确的 QA 检查。
### 5.1 文件层检查
- 新旧目标区域 `z/x/y.pbf` 文件名集合一致
- 瓦片数一致
- 输出层级目录完整
### 5.2 几何层检查
- 抽样瓦片 extent 一致
- 抽样 feature 数量不异常缩水
- 几何类型不发生意外变化
### 5.3 属性层检查
- `fid` 保留
- taxonomy 字段不为空
- 核心 render 字段存在
- 关键旧字段未被错误清洗
### 5.4 渲染层检查
至少验证以下对象在新样式或兼容样式中可正常显示:
- 灯标体系
- 危险物体系
- 鱼礁/鱼业区
- 水深区和等深线
- 基本线 / 危险界 / 航路境界
- 海上地名 / 陆上地名
## 6 与当前实现的差距
当前 `navsea_tile_builder.py` 已经完成:
- 原始瓦片读取
- 数据库关联
- taxonomy 字段叠加
- `render_layer` 重分层
- 原始 extent 保持
当前还缺:
- 统一的 render mapping 物化
- label/light/numeric 归一化
- delivery 与 engineering 两种输出口径
- 更系统的 QA 报告
## 7 v2 推荐实施顺序
### 阶段 1不破坏现有交付
- 保持当前 builder 可用
- 在 builder 中新增 `chart_*` 字段,不删旧字段
### 阶段 2构建混合样式
- 新样式优先读取 `chart_*`
- 旧字段仅用于灯标细节、危险物图案和少数特例
### 阶段 3建立 QA 报表
- 每次构建输出 coverage / feature count / extent 抽样报告
- 对 taxonomy 未命中项输出清单
### 阶段 4精简交付字段
- 在新样式和检索稳定后,逐步减少无用旧字段
- 但保留 `fid`、taxonomy 和关键兼容字段
## 8 v2 验收标准
一版合格的 v2 delivery tiles 至少应满足:
- 与原始目标区域瓦片文件集合一致
- 抽样瓦片 extent 正确
- 主要对象类型 taxonomy 完整
- `chart_*` 核心字段可用于新样式
- 旧兼容样式仍可显示关键对象
- 检索和碰撞可通过 `fid + taxonomy + normalized_numeric` 使用

View File

@@ -0,0 +1,534 @@
# NavSea 可追溯映射体系设计 v1
版本v1 Draft
用途:定义 NavSea “旧版原始数据 -> 新版语义字段 / 渲染字段”的可追溯映射体系,确保后续可以稳定定位分类错误、渲染错误和规则变更影响。
## 1 目标
这套设计解决的不是“如何分类”本身,而是“分类和渲染映射的过程如何可追溯”。
必须满足:
- 能知道某个 feature 命中了哪条 taxonomy 规则
- 能知道某个 feature 命中了哪条 render 规则
- 能知道规则来自哪个版本
- 能知道规则判断时参考了哪些原始字段
- 能从最终 `pbf``fid` 回查到完整映射过程
一句话概括:
> 最终结果不是终点,规则命中过程也必须被记录成正式资产。
## 2 为什么必须做可追溯
如果只保留结果字段,例如:
- `canonical_family`
- `canonical_object_type`
- `detection_key`
- `chart_render_type`
那后续虽然能看到“结果是什么”,但看不到:
- 为什么会分成这个结果
- 是哪条规则起了作用
- 如果结果错了,到底该改 taxonomy 还是改 render mapping
- 某次规则调整影响了哪些 feature
而 NavSea 后续一定会反复遇到这些问题:
- 某个对象分错类
- 某类对象在新样式里显示错误
- 某次规则升级导致历史区域表现变化
- 检索命中和渲染表现不一致
这时如果没有 trace就只能人工猜。
## 3 设计原则
### 3.1 文件是规则源头
规则的 source of truth 必须是版本可控文件,而不是代码里的隐式判断,也不是数据库里唯一的一份规则。
建议:
- taxonomy 规则放 YAML/CSV 文件
- render mapping 规则放 YAML/CSV 文件
- 文档文件负责解释,不作为程序执行源
### 3.2 SQL 是运行时载体
数据库负责:
- 导入规则
- 物化计算结果
- 记录 feature 命中过程
- 支撑查询和审计
但数据库不是唯一规则源头。
### 3.3 结果和过程都要存
至少要同时存两类数据:
- 规则定义
- feature 命中结果
只存最终结果表不够。
### 3.4 规则必须有稳定 ID
每条规则必须有稳定 `rule_id`,不能只靠“第几条规则”或描述文本识别。
### 3.5 规则必须有版本
每次可影响结果的变更都要有版本号或 bundle 版本。
建议使用:
- `bundle_version`
- `rule_revision`
## 4 总体架构
建议分成 4 层。
### 4.1 规则源文件层
建议目录:
- `tasks/pbf/mappings/navsea_taxonomy_rules_v1.yaml`
- `tasks/pbf/mappings/navsea_render_rules_v1.yaml`
- `tasks/pbf/mappings/navsea_rule_bundle_v1.yaml`
职责:
- 人可读
- 可进入 git
- 可 code review
- 可回滚
### 4.2 规则表层
建议导入 MySQL 生成:
- `navsea_rule_bundle`
- `navsea_taxonomy_rules`
- `navsea_render_rules`
职责:
- 运行时查询
- 规则生效控制
- 按版本执行构建
### 4.3 结果表层
建议生成:
- `navsea_feature_taxonomy_result`
- `navsea_feature_render_result`
- `navsea_feature_rule_trace`
- `navsea_mapping_run`
职责:
- 记录某次构建的命中结果
- 记录 feature 与 rule 的关系
- 记录本次运行使用的规则版本
### 4.4 交付层
交付层包括:
- delivery pbf
- engineering pbf
其中:
- delivery pbf 只保留必要结果字段
- engineering pbf 或内部查询表保留 trace 回查能力
## 5 推荐文件结构
建议新增目录:
```text
tasks/pbf/mappings/
navsea_rule_bundle_v1.yaml
navsea_taxonomy_rules_v1.yaml
navsea_render_rules_v1.yaml
```
建议新增导入脚本:
```text
scripts/pbf/
import_navsea_rules.py
run_navsea_mapping.py
export_navsea_trace_report.py
```
## 6 规则文件设计
## 6.1 bundle 文件
bundle 文件用于声明:
- 当前规则集版本
- taxonomy 规则文件版本
- render 规则文件版本
- 适用范围
- 是否为当前默认版本
示例字段:
- `bundle_id`
- `bundle_version`
- `status`
- `effective_date`
- `taxonomy_ruleset`
- `render_ruleset`
- `notes`
## 6.2 taxonomy 规则文件
每条 taxonomy 规则至少包含:
- `rule_id`
- `rule_revision`
- `priority`
- `enabled`
- `match_scope`
- `match_expr`
- `output.canonical_family`
- `output.canonical_object_type`
- `output.detection_key_template`
- `reason`
其中:
- `rule_id` 是稳定主键,例如 `TAX-NAV-001`
- `rule_revision` 是规则修订号,例如 `3`
- `priority` 用于冲突时排序
- `match_expr` 描述匹配条件
- `reason` 解释为什么有这条规则
## 6.3 render 规则文件
每条 render 规则至少包含:
- `rule_id`
- `rule_revision`
- `priority`
- `enabled`
- `match_expr`
- `output.chart_render_type`
- `output.chart_symbol_family`
- `output.chart_symbol_code`
- `output.chart_line_style`
- `output.chart_fill_style`
- `output.chart_text_style`
- `output.chart_priority`
- `reason`
render 规则的输入通常包括:
- `canonical_object_type`
- `canonical_family`
- geometry type
- 必要旧字段
## 7 match_expr 建议
不建议把匹配逻辑写成自由文本。
建议使用结构化表达,例如:
```yaml
match_expr:
all:
- field: source_layer
op: in
value: [p航路標識群, P航行危険障害物]
- field: class_name
op: contains_any
value: [港湾灯台, 灯柱, 灯浮標]
- field: geom_type
op: eq
value: Point
```
支持的运算建议限制在少数几类:
- `eq`
- `neq`
- `in`
- `contains`
- `contains_any`
- `is_null`
- `not_null`
- `regex`
这样规则可审计、可导入、可执行。
## 8 SQL 表设计
## 8.1 `navsea_rule_bundle`
建议字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `bundle_id` | varchar(64) PK | 规则集 ID |
| `bundle_version` | varchar(32) | 规则集版本 |
| `status` | varchar(20) | `draft` / `active` / `retired` |
| `taxonomy_ruleset` | varchar(64) | taxonomy 文件版本 |
| `render_ruleset` | varchar(64) | render 文件版本 |
| `effective_date` | datetime | 生效时间 |
| `created_at` | datetime | 创建时间 |
| `notes` | text | 备注 |
## 8.2 `navsea_taxonomy_rules`
建议字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `rule_id` | varchar(64) PK | 稳定规则 ID |
| `bundle_id` | varchar(64) | 所属 bundle |
| `rule_revision` | int | 修订号 |
| `priority` | int | 优先级,值越小越先匹配 |
| `enabled` | tinyint | 是否启用 |
| `match_scope` | varchar(32) | `feature` / `layer` / `object` |
| `match_expr_json` | json | 结构化匹配表达式 |
| `canonical_family` | varchar(100) | 输出 family |
| `canonical_object_type` | varchar(191) | 输出 object type |
| `detection_key_template` | varchar(191) | 输出 detection 模板 |
| `rule_reason` | text | 规则说明 |
| `created_at` | datetime | 创建时间 |
| `updated_at` | datetime | 更新时间 |
## 8.3 `navsea_render_rules`
建议字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `rule_id` | varchar(64) PK | 稳定规则 ID |
| `bundle_id` | varchar(64) | 所属 bundle |
| `rule_revision` | int | 修订号 |
| `priority` | int | 优先级 |
| `enabled` | tinyint | 是否启用 |
| `match_expr_json` | json | 匹配表达式 |
| `chart_render_type` | varchar(32) | 输出 |
| `chart_symbol_family` | varchar(64) | 输出 |
| `chart_symbol_code` | varchar(64) | 输出 |
| `chart_line_style` | varchar(64) | 输出 |
| `chart_fill_style` | varchar(64) | 输出 |
| `chart_text_style` | varchar(64) | 输出 |
| `chart_priority` | int | 输出 |
| `chart_visibility_min` | int | 输出 |
| `chart_visibility_max` | int | 输出 |
| `rule_reason` | text | 规则说明 |
| `created_at` | datetime | 创建时间 |
| `updated_at` | datetime | 更新时间 |
## 8.4 `navsea_mapping_run`
记录一次完整构建执行。
建议字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `run_id` | bigint PK | 执行 ID |
| `bundle_id` | varchar(64) | 本次使用的规则集 |
| `run_type` | varchar(32) | `full` / `aoi` / `qa` |
| `tile_scope` | text | 范围说明 |
| `started_at` | datetime | 开始时间 |
| `finished_at` | datetime | 结束时间 |
| `status` | varchar(20) | `running` / `success` / `failed` |
| `source_snapshot` | varchar(128) | 源数据快照标识 |
| `notes` | text | 备注 |
## 8.5 `navsea_feature_rule_trace`
这是最关键的 trace 表。
建议字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `run_id` | bigint | 所属执行 |
| `feature_id` | bigint | 内部 feature 主键 |
| `fid` | varchar(191) | 原始对象标识 |
| `z` | int | tile z |
| `x` | int | tile x |
| `y` | int | tile y |
| `source_layer` | varchar(100) | 原始 layer |
| `geom_type` | varchar(32) | 几何类型 |
| `taxonomy_rule_id` | varchar(64) | 命中的 taxonomy 规则 |
| `taxonomy_rule_revision` | int | taxonomy 修订号 |
| `render_rule_id` | varchar(64) | 命中的 render 规则 |
| `render_rule_revision` | int | render 修订号 |
| `bundle_id` | varchar(64) | 规则集版本 |
| `classification_basis` | varchar(64) | 使用的主要依据 |
| `source_fields_used_json` | json | 实际参与判定的字段和值摘要 |
| `canonical_family` | varchar(100) | 产出结果 |
| `canonical_object_type` | varchar(191) | 产出结果 |
| `detection_key` | varchar(191) | 产出结果 |
| `chart_render_type` | varchar(32) | 产出结果 |
| `chart_symbol_family` | varchar(64) | 产出结果 |
| `chart_symbol_code` | varchar(64) | 产出结果 |
| `chart_line_style` | varchar(64) | 产出结果 |
| `chart_fill_style` | varchar(64) | 产出结果 |
| `chart_text_style` | varchar(64) | 产出结果 |
| `trace_status` | varchar(20) | `matched` / `fallback` / `manual_review` |
| `created_at` | datetime | 记录时间 |
说明:
- `source_fields_used_json` 不要求保存整份原始属性
- 但必须记录本次命中实际使用的关键字段和值摘要
例如:
```json
{
"fid": "123456",
"分類番号": "403",
"表示用番号": "31135504",
"名称": "鷹島灯台",
"geom_type": "Point"
}
```
## 9 交付与追溯分离策略
为了兼顾交付体积和可追溯性,建议分两条线:
### 9.1 delivery pbf
保留:
- 业务必需字段
- taxonomy 结果字段
- render 结果字段
- 必要旧字段
不强制保留:
- 完整 trace 细节
### 9.2 engineering trace
通过以下方式保留完整追溯能力:
- SQL trace 表
- engineering pbf
-`fid` / `feature_id` 回查脚本
建议 engineering pbf 可额外保留:
- `taxonomy_rule_id`
- `render_rule_id`
- `bundle_id`
- `trace_status`
## 10 builder 接入方式
当前 [navsea_tile_builder.py](/root/weather/navsea_tile_builder.py) 是从 `pbf_relayer_candidates` 读取结果并写入 `pbf`
建议改造成两段式:
### 阶段 A规则求值阶段
输入:
- 原始 feature
- 规则表
输出:
- `navsea_feature_taxonomy_result`
- `navsea_feature_render_result`
- `navsea_feature_rule_trace`
### 阶段 BPBF 输出阶段
输入:
- 已物化结果表
输出:
- delivery pbf
- engineering pbf
这样做的好处是:
- “规则判断”与“PBF 编码”解耦
- 同一份判定结果可重复出图
- QA 和回归检查更容易做
## 11 问题排查路径
未来排查一个对象时,建议统一走这条链路:
1. 先从前端或瓦片里拿到 `fid`
2.`fid``feature_id``navsea_feature_rule_trace`
3. 看命中的 `taxonomy_rule_id``render_rule_id`
4. 回到规则表查看该规则定义
5. 必要时回到规则源文件查看变更历史
6. 确认问题属于:
- 原始数据异常
- taxonomy 规则错误
- render 规则错误
- 样式解释错误
## 12 变更管理
建议所有规则变更都遵循:
- 改规则文件
- 提交 git
- 生成新 `bundle_version`
- 导入 SQL
- 执行局部或全量重算
- 输出差异报告
不建议:
- 直接手改结果表
- 直接在 SQL 里无版本地改规则
- 直接在代码里插入一条临时 if 判断后不回写规则文件
## 13 最小可落地版本
如果要尽快开始,建议第一阶段先做到:
1. 新增规则源文件目录
2. 给 taxonomy 和 render 规则都定义 `rule_id`
3. 新增 `navsea_rule_bundle`
4. 新增 `navsea_feature_rule_trace`
5. builder 在出 engineering 数据时至少写出:
- `bundle_id`
- `taxonomy_rule_id`
- `render_rule_id`
- `trace_status`
这样即使规则体系还不完整,也已经具备“能追”的能力。
## 14 结论
NavSea 的“旧版 -> 新版”对应关系,不应只是一套结果字段,也不应只存在于代码里。
它应该被正式建设成一套可追溯资产,包括:
- 可版本化的规则文件
- 可运行的 SQL 规则表
- 可查询的 feature trace 表
- 与 delivery / engineering pbf 配套的回查能力
后续查错、验收、回归、争议复盘,都会依赖这套体系。

344
tasks/pbf/OutPbf.md Normal file
View File

@@ -0,0 +1,344 @@
# NavSea Codex Task
# Karatsu AOI Vector Tile Build
Architecture: NavSea V11 / Codex6
Scope: Server Side Tile Build
---
# Task Name
NavSea_Karatsu_AOI_PBF_Builder
---
# Task Goal
Generate a NavSea Vector Tile dataset for the area surrounding **Karatsu City (唐津市)**.
The tile build must cover approximately:
```
10 nautical mile radius
centered on Karatsu city
```
The tiles must be generated for **all zoom levels supported by NavSea**.
The generated tiles will be used to validate:
- semantic overlay
- render compatibility
- navigation object detection
- tile density behavior
- style compatibility
---
# Output Location
Tiles must be written to:
```
/home/wwwroot/pbf
```
Directory structure must follow standard vector tile layout:
```
/home/wwwroot/pbf/{z}/{x}/{y}.pbf
```
Example:
```
/home/wwwroot/pbf/10/864/440.pbf
```
Existing files in the directory may be overwritten.
---
# AOI Definition
Center location:
```
Karatsu City
Japan
```
Recommended reference coordinate:
```
Lat: 33.4425
Lon: 129.9697
```
Coverage radius:
```
10 nautical miles
≈ 18.52 km
```
Codex may implement this AOI using one of the following:
```
1 center point + radius
2 bounding box derived from radius
3 tile range approximation
```
The resulting tiles must fully cover the requested radius.
---
# Zoom Levels
Tiles must be generated for:
```
z = 0 → 14
```
(Or the maximum zoom available in the dataset.)
---
# Data Sources
Tile features must be built from the validated NavSea semantic dataset.
Primary semantic source:
```
pbf_relayer_candidates
```
Additional required tables:
```
features
properties
at_attributes
feature_semantic
```
These tables must be joined to reconstruct the full feature.
---
# Feature Reconstruction Rules
Each output tile feature must include:
## Geometry
From:
```
features
```
Fields:
```
z
x
y
geom_type
```
The geometry encoding must match the original vector tile geometry.
---
## Original Attributes
All original attributes from:
```
properties
```
must be preserved.
Examples include:
```
class
shape
name
symbol
depth
category
```
These attributes must **not be removed or renamed**.
---
## Semantic Attributes
Additional semantic fields must be included from:
```
pbf_relayer_candidates
```
Including:
```
canonical_object_type
canonical_family
semantic_key
detection_key
render_layer
```
These fields must be **added**, not replacing original fields.
---
# Feature Selection
Features must be selected based on tile coordinates intersecting the AOI.
Selection process:
```
1 determine tile range covering AOI
2 select features matching tile coordinates
3 group features by tile
4 encode each tile
```
---
# Tile Encoding
Each tile must be encoded as a **Mapbox Vector Tile (MVT)**.
Encoding rules:
```
Layer name = render_layer
```
If `render_layer` is null, fallback to:
```
source_layer
```
Geometry must be encoded according to:
```
geom_type
```
---
# Performance Requirements
The tile builder must:
```
avoid full-table scans where possible
use tile coordinate filtering
process tiles incrementally
```
The builder must not attempt to load the entire dataset into memory.
---
# Build Script
Codex must implement a script:
```
navsea_tile_builder.py
```
Capabilities required:
```
AOI tile calculation
database feature extraction
tile grouping
vector tile encoding
parallel tile generation
filesystem output
```
---
# Suggested Execution
The build script should be executable as:
```bash
python navsea_tile_builder.py \
--center-lat 33.4425 \
--center-lon 129.9697 \
--radius-nm 10 \
--zmin 0 \
--zmax 14 \
--output /home/wwwroot/pbf
```
---
# Expected Result
After the build completes, the directory should contain:
```
/home/wwwroot/pbf/
├─ 0/
├─ 1/
├─ 2/
├─ ...
└─ 14/
```
Each containing:
```
{x}/{y}.pbf
```
The tiles must render correctly in MapLibre / OpenCPN / tile viewers.
---
# Verification
After build, the following checks should pass:
```
tiles exist for requested AOI
tile hierarchy is correct
vector tiles decode successfully
original attributes preserved
semantic fields present
```
Example feature should resemble:
```json
{
"class": "灯",
"shape": "灯標",
"name": "唐津灯台",
"canonical_object_type": "navigation_light",
"canonical_family": "navigation_aid",
"detection_key": "nav_light"
}
```
---
# End Task

104
tasks/pbf/fiddecode.md Normal file
View File

@@ -0,0 +1,104 @@
from Crypto.Cipher import AES
import hashlib
import struct
# Example implementation updated for the full signed int32 legacy fid domain.
# This keeps the algorithm reversible for all observed NavSea legacy fid values.
MIN_VAL = -(1 << 31)
MAX_VAL = (1 << 31) - 1
N = MAX_VAL - MIN_VAL + 1 # 4294967296
ROUNDS = 10
DOMAIN_BITS = 32
DOMAIN_SIZE = 1 << DOMAIN_BITS
def _prf(key: bytes, round_no: int, value: int) -> int:
"""
AES-based PRF, returns 16-bit integer.
"""
cipher = AES.new(key, AES.MODE_ECB)
data = struct.pack(">IQ", round_no, value)
block = hashlib.sha256(data).digest()[:16]
out = cipher.encrypt(block)
return int.from_bytes(out[-2:], "big")
def _feistel_permute(x: int, key: bytes, encrypt: bool) -> int:
"""
32-bit Feistel permutation.
"""
if not (0 <= x < DOMAIN_SIZE):
raise ValueError("x out of 32-bit domain")
l = (x >> 16) & 0xFFFF
r = x & 0xFFFF
rounds = range(ROUNDS) if encrypt else reversed(range(ROUNDS))
for rnd in rounds:
if encrypt:
f = _prf(key, rnd, r)
l, r = r, l ^ f
else:
f = _prf(key, rnd, l)
l, r = r ^ f, l
return ((l << 16) | r) & 0xFFFFFFFF
def encrypt_number(x: int, key: bytes) -> int:
"""
Encrypt x in [-2147483648, 2147483647]
Return non-negative integer in [0, N-1]
"""
if len(key) not in (16, 24, 32):
raise ValueError("AES key must be 16, 24, or 32 bytes")
if not (MIN_VAL <= x <= MAX_VAL):
raise ValueError("input out of range")
# Map original range to [0, N-1]
r = x - MIN_VAL
# Cycle-walking into [0, N-1]
while True:
r = _feistel_permute(r, key, True)
if r < N:
return r
def decrypt_number(y: int, key: bytes) -> int:
"""
Decrypt non-negative integer y in [0, N-1]
Return original integer in [-2147483648, 2147483647]
"""
if len(key) not in (16, 24, 32):
raise ValueError("AES key must be 16, 24, or 32 bytes")
if not (0 <= y < N):
raise ValueError("encrypted value out of range")
r = y
# Reverse cycle-walking
while True:
r = _feistel_permute(r, key, False)
if r < N:
return r + MIN_VAL
if __name__ == "__main__":
key = b"example-secret!!" # 16 bytes
samples = [
-2147483648,
-1,
0,
1,
12345678,
2147483647,
]
for x in samples:
enc = encrypt_number(x, key)
dec = decrypt_number(enc, key)
print(f"x={x}, enc={enc}, dec={dec}, ok={x == dec}")

View File

@@ -0,0 +1,123 @@
ruleset: navsea_field_name_rules_v1
bundle_id: navsea-core
version: v1-draft
rules:
- field_name_jp: fid
field_name_std: fid_legacy_raw
field_group: identity
keep_in_delivery: false
keep_in_engineering: true
normalization_class: reversible_identity
notes: Preserve the original legacy fid only in engineering and trace outputs.
- field_name_jp: at
field_name_std: at_raw
field_group: source_legacy
keep_in_delivery: false
keep_in_engineering: true
normalization_class: raw_blob
notes: Raw attribute pack remains engineering-only by default.
- field_name_jp: 分類番号
field_name_std: class_code
field_group: source_legacy
keep_in_delivery: true
keep_in_engineering: true
normalization_class: legacy_render_code
notes: Legacy class code used during transition and audits.
- field_name_jp: 形状分類番号
field_name_std: shape_class_code
field_group: source_legacy
keep_in_delivery: true
keep_in_engineering: true
normalization_class: legacy_render_code
notes: Legacy shape class code used during transition and audits.
- field_name_jp: 表示用番号
field_name_std: display_code
field_group: source_legacy
keep_in_delivery: true
keep_in_engineering: true
normalization_class: legacy_render_code
notes: Legacy display code retained until all rendering migrates to chart_* fields.
- field_name_jp: 灯色
field_name_std: light_color_raw_code
field_group: light
keep_in_delivery: true
keep_in_engineering: true
normalization_class: field_value_normalization
notes: Legacy raw color code maps into light_color_code.
- field_name_jp: 灯略記
field_name_std: light_character_remark
field_group: light
keep_in_delivery: true
keep_in_engineering: true
normalization_class: content_text
notes: User-visible light remark should remain reversible.
- field_name_jp: 明弧/分孤
field_name_std: light_sector_remark
field_group: light
keep_in_delivery: true
keep_in_engineering: true
normalization_class: field_value_normalization
notes: Legacy light sector remark maps into light_sector_mode and trace fields.
- field_name_jp: 表示位置
field_name_std: label_position_code_legacy
field_group: labels
keep_in_delivery: true
keep_in_engineering: true
normalization_class: field_value_normalization
notes: Legacy label position code maps into chart_label_position_code.
- field_name_jp: 名称
field_name_std: name_ja
field_group: labels
keep_in_delivery: true
keep_in_engineering: true
normalization_class: content_text
notes: Primary Japanese name content must remain available.
- field_name_jp: 名称補助
field_name_std: name_subtext_ja
field_group: labels
keep_in_delivery: true
keep_in_engineering: true
normalization_class: content_text
notes: Secondary Japanese name content must remain available.
- field_name_jp: 日本語地名
field_name_std: place_name_ja
field_group: labels
keep_in_delivery: true
keep_in_engineering: true
normalization_class: content_text
notes: Japanese place name content must remain available.
- field_name_jp: 英文字地名
field_name_std: place_name_en
field_group: labels
keep_in_delivery: true
keep_in_engineering: true
normalization_class: content_text
notes: English place name content remains available for fallback labels.
- field_name_jp: 水深値(m)
field_name_std: depth_value_m_legacy
field_group: normalized_numeric
keep_in_delivery: true
keep_in_engineering: true
normalization_class: numeric_normalization
notes: Legacy depth string is normalized into depth_value_m.
- field_name_jp: 高さ(m)
field_name_std: clearance_height_m_legacy
field_group: normalized_numeric
keep_in_delivery: true
keep_in_engineering: true
normalization_class: numeric_normalization
notes: Legacy height string is normalized into clearance_height_m.
- field_name_jp: 高さ/深度(m)
field_name_std: height_or_depth_m_legacy
field_group: normalized_numeric
keep_in_delivery: true
keep_in_engineering: true
normalization_class: numeric_normalization
notes: Mixed height/depth legacy string maps into least_depth_m or clearance semantics.
- field_name_jp: 角度
field_name_std: bearing_deg_legacy
field_group: normalized_numeric
keep_in_delivery: true
keep_in_engineering: true
normalization_class: numeric_normalization
notes: Legacy angle string is normalized into bearing_deg.

View File

@@ -0,0 +1,148 @@
ruleset: navsea_field_value_rules_v1
bundle_id: navsea-core
version: v1-draft
rules:
- rule_id: FVAL-LIGHT-001
rule_revision: 1
field_name_jp: 灯色
legacy_value: "1"
standardized_field: light_color_code
standardized_value: green
notes: Legacy light color code 1 maps to green in current data.
- rule_id: FVAL-LIGHT-002
rule_revision: 1
field_name_jp: 灯色
legacy_value: "2"
standardized_field: light_color_code
standardized_value: red
notes: Legacy light color code 2 maps to red.
- rule_id: FVAL-LIGHT-003
rule_revision: 1
field_name_jp: 灯色
legacy_value: "3"
standardized_field: light_color_code
standardized_value: yellow
notes: Legacy light color code 3 maps to yellow.
- rule_id: FVAL-LIGHT-004
rule_revision: 1
field_name_jp: 灯色
legacy_value: "4"
standardized_field: light_color_code
standardized_value: white
notes: Legacy light color code 4 maps to white.
- rule_id: FVAL-LIGHT-005
rule_revision: 1
field_name_jp: 灯色
legacy_value: "5"
standardized_field: light_color_code
standardized_value: blue
notes: Legacy light color code 5 maps to blue.
- rule_id: FVAL-LIGHT-006
rule_revision: 1
field_name_jp: 灯色
legacy_value: "6"
standardized_field: light_color_code
standardized_value: violet
notes: Legacy light color code 6 maps to violet.
- rule_id: FVAL-LIGHT-007
rule_revision: 1
field_name_jp: 灯色
legacy_value: "7"
standardized_field: light_color_code
standardized_value: orange
notes: Legacy light color code 7 maps to orange.
- rule_id: FVAL-LIGHT-008
rule_revision: 1
field_name_jp: 灯色
legacy_value: "8"
standardized_field: light_color_code
standardized_value: amber
notes: Legacy light color code 8 maps to amber.
- rule_id: FVAL-LIGHT-009
rule_revision: 1
field_name_jp: 灯色
legacy_value: "9"
standardized_field: light_color_code
standardized_value: mixed
notes: Legacy light color code 9 maps to mixed.
- rule_id: FVAL-LABELPOS-001
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "0"
standardized_field: chart_label_position_code
standardized_value: tl
notes: Legacy label position 0 maps to top-left.
- rule_id: FVAL-LABELPOS-002
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "1"
standardized_field: chart_label_position_code
standardized_value: t
notes: Legacy label position 1 maps to top.
- rule_id: FVAL-LABELPOS-003
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "2"
standardized_field: chart_label_position_code
standardized_value: tr
notes: Legacy label position 2 maps to top-right.
- rule_id: FVAL-LABELPOS-004
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "4"
standardized_field: chart_label_position_code
standardized_value: l
notes: Legacy label position 4 maps to left.
- rule_id: FVAL-LABELPOS-005
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "5"
standardized_field: chart_label_position_code
standardized_value: c
notes: Legacy label position 5 maps to center.
- rule_id: FVAL-LABELPOS-006
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "6"
standardized_field: chart_label_position_code
standardized_value: r
notes: Legacy label position 6 maps to right.
- rule_id: FVAL-LABELPOS-007
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "8"
standardized_field: chart_label_position_code
standardized_value: bl
notes: Legacy label position 8 maps to bottom-left.
- rule_id: FVAL-LABELPOS-008
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "9"
standardized_field: chart_label_position_code
standardized_value: b
notes: Legacy label position 9 maps to bottom.
- rule_id: FVAL-LABELPOS-009
rule_revision: 1
field_name_jp: 表示位置
legacy_value: "10"
standardized_field: chart_label_position_code
standardized_value: br
notes: Legacy label position 10 maps to bottom-right.
- rule_id: FVAL-CLASS-001
rule_revision: 1
field_name_jp: 分類番号
legacy_value: "428"
standardized_field: chart_symbol_code
standardized_value: fish_reef
geom_scope: Point
canonical_object_scope: 魚礁
notes: Legacy class 428 point object renders as fish reef symbol.
- rule_id: FVAL-CLASS-002
rule_revision: 1
field_name_jp: 分類番号
legacy_value: "428"
standardized_field: chart_fill_style
standardized_value: fish_reef_area
geom_scope: Polygon,MultiPolygon
canonical_object_scope: 魚礁
notes: Legacy class 428 area object renders as fish reef area pattern.

View File

@@ -0,0 +1,171 @@
ruleset: navsea_render_rules_v1
bundle_id: navsea-core
version: v1-draft
rules:
- rule_id: REN-NAV-001
rule_revision: 1
priority: 100
enabled: true
match_expr:
all:
- field: canonical_object_type
op: eq
value: 港湾灯台
- field: geom_type
op: eq
value: Point
output:
chart_render_type: symbol
chart_symbol_family: navigation_light
chart_symbol_code: lighthouse
chart_priority: 900
chart_visibility_min: 7
chart_visibility_max: 24
reason: 港湾灯台应以高优先级灯标符号渲染。
- rule_id: REN-HAZ-001
rule_revision: 1
priority: 120
enabled: true
match_expr:
all:
- field: canonical_object_type
op: eq
value: 魚礁
- field: geom_type
op: eq
value: Point
output:
chart_render_type: symbol
chart_symbol_family: hazard
chart_symbol_code: fish_reef
chart_priority: 860
area_usage_class: fishery
hazard_class: fish_reef
hazard_severity: major
reason: 点状鱼礁以鱼礁专用危险物符号表达。
- rule_id: REN-HAZ-002
rule_revision: 1
priority: 121
enabled: true
match_expr:
all:
- field: canonical_object_type
op: eq
value: 魚礁
- field: geom_type
op: in
value: [Polygon, MultiPolygon]
output:
chart_render_type: fill
chart_symbol_family: hazard
chart_fill_style: fish_reef_area
chart_priority: 850
area_usage_class: fishery
hazard_class: fish_reef
hazard_severity: major
reason: 面状鱼礁区以鱼礁专用危险区填充表达,同时保留 fishery 用途语义。
- rule_id: REN-DEPTH-001
rule_revision: 1
priority: 200
enabled: true
match_expr:
all:
- field: canonical_object_type
op: eq
value: 等深线
output:
chart_render_type: line
chart_symbol_family: contour
chart_line_style: contour_minor
chart_priority: 640
chart_visibility_min: 8
chart_visibility_max: 24
reason: 等深线统一归入 contour line 体系。
- rule_id: REN-SEABED-001
rule_revision: 1
priority: 210
enabled: true
match_expr:
all:
- field: canonical_object_type
op: eq
value: 底質
output:
chart_render_type: label
chart_symbol_family: seabed
chart_text_style: seabed_text
chart_priority: 500
chart_visibility_min: 11
chart_visibility_max: 24
reason: 底质对象以海底属性文字渲染。
- rule_id: REN-PLACE-001
rule_revision: 1
priority: 220
enabled: true
match_expr:
all:
- field: canonical_object_type
op: eq
value: 海上地名
output:
chart_render_type: label
chart_symbol_family: place
chart_text_style: place_name_sea
chart_priority: 450
chart_visibility_min: 7
chart_visibility_max: 24
reason: 海上地名使用海上地名字体体系渲染。
- rule_id: REN-PLACE-002
rule_revision: 1
priority: 221
enabled: true
match_expr:
all:
- field: canonical_object_type
op: eq
value: 陆上地名
output:
chart_render_type: label
chart_symbol_family: place
chart_text_style: place_name_land
chart_priority: 440
chart_visibility_min: 7
chart_visibility_max: 24
reason: 陆上地名使用陆地地名字体体系渲染。
- rule_id: REN-USAGE-001
rule_revision: 1
priority: 230
enabled: true
match_expr:
all:
- field: canonical_object_type
op: eq
value: 錨泊地
- field: geom_type
op: in
value: [Polygon, MultiPolygon]
output:
chart_render_type: fill
chart_symbol_family: usage_area
chart_fill_style: anchorage_area
chart_priority: 750
area_usage_class: anchorage
reason: 锚泊地区域以 anchorage_area 语义填充表达。
- rule_id: REN-FALLBACK-001
rule_revision: 1
priority: 9999
enabled: true
match_expr:
all: []
output:
chart_render_type: none
chart_priority: 0
reason: 未命中渲染规则的对象默认不进入正式语义渲染,待补录。

View File

@@ -0,0 +1,12 @@
bundle_id: navsea-core
bundle_version: v1-draft
status: draft
effective_date: 2026-03-14
taxonomy_ruleset: navsea_taxonomy_rules_v1
render_ruleset: navsea_render_rules_v1
source_layer_ruleset: navsea_source_layer_rules_v1
field_name_ruleset: navsea_field_name_rules_v1
field_value_ruleset: navsea_field_value_rules_v1
notes: >
Draft rule bundle for traceable NavSea taxonomy and render mapping.
File is intended as source-of-truth metadata and should be imported into SQL.

View File

@@ -0,0 +1,151 @@
ruleset: navsea_source_layer_rules_v1
bundle_id: navsea-core
version: v1-draft
rules:
- source_layer_jp: L700
source_layer_std: depth_zone_700
notes: Legacy coded depth zone layer kept as stable standardized code.
- source_layer_jp: L702
source_layer_std: depth_zone_702
notes: Legacy coded depth zone layer kept as stable standardized code.
- source_layer_jp: L725
source_layer_std: depth_zone_725
notes: Legacy coded depth zone layer kept as stable standardized code.
- source_layer_jp: L739
source_layer_std: depth_zone_739
notes: Legacy coded depth zone layer kept as stable standardized code.
- source_layer_jp: L740
source_layer_std: depth_zone_740
notes: Legacy coded depth zone layer kept as stable standardized code.
- source_layer_jp: L741
source_layer_std: depth_zone_741
notes: Legacy coded depth zone layer kept as stable standardized code.
- source_layer_jp: L748
source_layer_std: depth_zone_748
notes: Legacy coded depth zone layer kept as stable standardized code.
- source_layer_jp: L749
source_layer_std: depth_zone_749
notes: Legacy coded depth zone layer kept as stable standardized code.
- source_layer_jp: L危険界
source_layer_std: hazard_boundary_line
notes: Standardized line identity for hazard boundary linework.
- source_layer_jp: L基本線
source_layer_std: baseline_line
notes: Standardized line identity for baseline linework.
- source_layer_jp: L概略等深線
source_layer_std: depth_contour_overview
notes: Overview contour line layer.
- source_layer_jp: L海底地形
source_layer_std: bathymetry_line
notes: Bathymetry support line layer.
- source_layer_jp: L海底線
source_layer_std: seabed_line
notes: Seabed line feature container.
- source_layer_jp: L等深線
source_layer_std: depth_contour
notes: Standard contour line layer.
- source_layer_jp: L航路
source_layer_std: route_axis_line
notes: Route axis or route line layer.
- source_layer_jp: L陸上構造物陸
source_layer_std: onshore_structure_line
notes: Onshore structure line layer.
- source_layer_jp: L高さ制限
source_layer_std: clearance_limit_line
notes: Clearance restriction line layer.
- source_layer_jp: P721ククリ
source_layer_std: clip_outline_721
notes: Stable outline layer preserved by numeric legacy code.
- source_layer_jp: P730ククリ
source_layer_std: clip_outline_730
notes: Stable outline layer preserved by numeric legacy code.
- source_layer_jp: P754ククリ
source_layer_std: clip_outline_754
notes: Stable outline layer preserved by numeric legacy code.
- source_layer_jp: pパイロットステーション
source_layer_std: pilot_station_point
notes: Pilot station point layer.
- source_layer_jp: P危険界ククリ
source_layer_std: hazard_boundary_outline
notes: Hazard boundary outline layer.
- source_layer_jp: p地名
source_layer_std: place_label_sea
notes: Marine place label point layer.
- source_layer_jp: p地名陸
source_layer_std: place_label_land
notes: Land place label point layer.
- source_layer_jp: P基本線
source_layer_std: baseline_area
notes: Baseline area or container layer.
- source_layer_jp: P基本線ククリ
source_layer_std: baseline_outline
notes: Baseline outline layer.
- source_layer_jp: p底質
source_layer_std: seabed_text_point
notes: Seabed label point layer.
- source_layer_jp: p投錨注意障害物
source_layer_std: anchor_caution_hazard_point
notes: Point hazards relevant to anchoring caution.
- source_layer_jp: P投錨注意障害物ククリ
source_layer_std: anchor_caution_hazard_outline
notes: Outline of anchoring caution hazard area.
- source_layer_jp: P施設・境界線等
source_layer_std: facility_boundary_area
notes: Facility and boundary area container.
- source_layer_jp: P施設・境界線等ククリ
source_layer_std: facility_boundary_outline
notes: Facility and boundary outline layer.
- source_layer_jp: P施設・境界線等透明
source_layer_std: facility_boundary_area_transparent
notes: Transparent facility and boundary area layer.
- source_layer_jp: P橋りょう等構造物
source_layer_std: bridge_structure
notes: Bridge and related structure layer.
- source_layer_jp: P漁具定置箇所
source_layer_std: fixed_fishing_gear_area
notes: Fixed fishing gear area layer.
- source_layer_jp: P潜堤
source_layer_std: submerged_reef_area
notes: Submerged reef area layer.
- source_layer_jp: P穴
source_layer_std: hole_area
notes: Hole or depression area layer.
- source_layer_jp: p航行危険障害物
source_layer_std: navigation_hazard_point
notes: Navigation hazard point layer.
- source_layer_jp: P航行危険障害物ククリ
source_layer_std: navigation_hazard_outline
notes: Navigation hazard outline layer.
- source_layer_jp: P航路
source_layer_std: route_area
notes: Route area layer.
- source_layer_jp: P航路ククリ
source_layer_std: route_outline
notes: Route outline layer.
- source_layer_jp: p航路境界等
source_layer_std: route_boundary_point
notes: Route boundary point annotation layer.
- source_layer_jp: p航路標識群
source_layer_std: navigation_marks
notes: Navigation marks point layer.
- source_layer_jp: P誘導線ククリ
source_layer_std: leading_line_outline
notes: Leading line outline layer.
- source_layer_jp: p錨泊地等
source_layer_std: anchorage_point
notes: Anchorage point symbol layer.
- source_layer_jp: P錨泊地等ククリ
source_layer_std: anchorage_outline
notes: Anchorage outline layer.
- source_layer_jp: p陸上構造物
source_layer_std: onshore_structure_point
notes: Onshore structure point layer.
- source_layer_jp: P陸上構造物陸
source_layer_std: onshore_structure_area
notes: Onshore structure area layer.
- source_layer_jp: P陸域
source_layer_std: land_area
notes: Land area polygon layer.
- source_layer_jp: p高さ制限
source_layer_std: clearance_limit_point
notes: Clearance restriction point layer.

View File

@@ -0,0 +1,134 @@
ruleset: navsea_taxonomy_rules_v1
bundle_id: navsea-core
version: v1-draft
rules:
- rule_id: TAX-NAV-001
rule_revision: 1
priority: 100
enabled: true
match_scope: feature
match_expr:
all:
- field: class_name
op: contains_any
value: [港湾灯台, 灯台]
- field: geom_type
op: eq
value: Point
output:
canonical_family: navigation_aid
canonical_object_type: 港湾灯台
detection_key_template: symbol:港湾灯台
reason: 港湾灯台属于典型点状助航对象。
- rule_id: TAX-DEPTH-001
rule_revision: 1
priority: 140
enabled: true
match_scope: layer
match_expr:
all:
- field: source_layer
op: eq
value: L等深線
output:
canonical_family: depth
canonical_object_type: 等深线
detection_key_template: line:等深线
reason: 等深线来源层具有稳定的深度线语义。
- rule_id: TAX-SEABED-001
rule_revision: 1
priority: 150
enabled: true
match_scope: layer
match_expr:
all:
- field: source_layer
op: eq
value: p底質
output:
canonical_family: seabed
canonical_object_type: 底質
detection_key_template: label:底質
reason: 底质标签层具有稳定的海底属性语义。
- rule_id: TAX-PLACE-001
rule_revision: 1
priority: 160
enabled: true
match_scope: layer
match_expr:
all:
- field: source_layer
op: eq
value: p地名
output:
canonical_family: place
canonical_object_type: 海上地名
detection_key_template: label:海上地名
reason: 海上地名点层具有稳定的地名语义。
- rule_id: TAX-PLACE-002
rule_revision: 1
priority: 161
enabled: true
match_scope: layer
match_expr:
all:
- field: source_layer
op: eq
value: p地名陸
output:
canonical_family: place
canonical_object_type: 陆上地名
detection_key_template: label:陆上地名
reason: 陆上地名点层具有稳定的地名语义。
- rule_id: TAX-USAGE-001
rule_revision: 1
priority: 180
enabled: true
match_scope: feature
match_expr:
all:
- field: class_name
op: contains_any
value: [錨泊, 錨地]
output:
canonical_family: usage_area
canonical_object_type: 錨泊地
detection_key_template: mixed:錨泊地
reason: 锚泊类对象统一归入 usage_area 体系。
- rule_id: TAX-HAZ-001
rule_revision: 1
priority: 120
enabled: true
match_scope: feature
match_expr:
all:
- field: class_name
op: contains
value: 魚礁
- field: geom_type
op: in
value: [Point, Polygon, MultiPolygon]
output:
canonical_family: hazard
canonical_object_type: 魚礁
detection_key_template: mixed:魚礁
reason: 魚礁在当前业务目标下优先视为危险对象,并允许后续叠加用途语义。
- rule_id: TAX-FALLBACK-001
rule_revision: 1
priority: 9999
enabled: true
match_scope: feature
match_expr:
all: []
output:
canonical_family: unknown
canonical_object_type: 未分类对象
detection_key_template: unknown:{source_layer}
reason: 所有未命中 taxonomy 规则的对象统一回退到待补录分类。

114
tasks/pipline.md Normal file
View File

@@ -0,0 +1,114 @@
# NavSea Weather Server
Task: WeatherServer_Pipeline
Architecture: NavSea V11
Codex: codex6
Status: TODO
---
# 1 任务目标
创建 Weather Pipeline。
Pipeline 负责自动执行整个天气数据生产流程:
Downloader
→ Grid Builder
→ Vector Tile Generator
输入:
NOAA GFS
输出:
/weather/{time}/{z}/{x}/{y}.pbf
用于 NavSea 客户端加载天气图层。
---
# 2 Pipeline 结构
weather_server/
downloader/
grid/
tiles/
pipeline/
创建文件:
weather_server/pipeline/weather_pipeline.py
---
# 3 Pipeline 执行流程
step1 下载 GRIB
step2 生成 Weather Grid
step3 生成 Vector Tiles
---
# 4 创建 Pipeline 文件
weather_server/pipeline/weather_pipeline.py
---
# 5 实现代码
```python
import os
import subprocess
import time
DOWNLOADER = "weather_server/downloader/gfs_downloader.py"
GRID_BUILDER = "weather_server/grid/grid_builder_v2.py"
TILE_GENERATOR = "weather_server/tiles/vector_tile_generator.py"
def run_step(name, script):
print("\n==========================")
print("Running:", name)
print("==========================\n")
start = time.time()
result = subprocess.run(
["python", script],
capture_output=True,
text=True
)
print(result.stdout)
if result.returncode != 0:
print("ERROR:", result.stderr)
raise RuntimeError(name + " failed")
end = time.time()
print("\nFinished:", name)
print("Time:", round(end-start,2),"seconds")
def main():
print("\nNavSea Weather Pipeline\n")
run_step("Downloader", DOWNLOADER)
run_step("Grid Builder", GRID_BUILDER)
run_step("Vector Tile Generator", TILE_GENERATOR)
print("\nWeather pipeline completed.\n")
if __name__ == "__main__":
main()

83
tasks/test2.md Normal file
View File

@@ -0,0 +1,83 @@
# NavSea Weather Server
Step-2 测试GFS Downloader
创建文件:
gfs_downloader.py
------------------------------------------------
import os
import requests
from datetime import datetime
BASE_URL = "https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod"
FORECAST_HOURS = [
0,3,6,9,12,15,18,21,24,
27,30,33,36,39,42,45,
48,51,54,57,60,63,66,
69,72
]
OUTPUT_DIR = "data/grib"
os.makedirs(OUTPUT_DIR, exist_ok=True)
def get_cycle():
now = datetime.utcnow()
hour = (now.hour // 6) * 6
cycle = f"{hour:02d}"
date = now.strftime("%Y%m%d")
return date, cycle
def download_file(url, path):
if os.path.exists(path):
print("skip", path)
return
print("downloading", url)
r = requests.get(url, stream=True)
if r.status_code != 200:
print("failed", url)
return
with open(path, "wb") as f:
for chunk in r.iter_content(1024*1024):
f.write(chunk)
def main():
date, cycle = get_cycle()
print("cycle:", date, cycle)
for fh in FORECAST_HOURS:
fh_str = f"{fh:03d}"
filename = f"gfs.t{cycle}z.pgrb2.0p25.f{fh_str}"
url = f"{BASE_URL}/gfs.{date}/{cycle}/atmos/{filename}"
output = os.path.join(
OUTPUT_DIR,
f"{date}_{cycle}_f{fh_str}.grib2"
)
download_file(url, output)
if __name__ == "__main__":
main()

264
tasks/updatedownload.md Normal file
View File

@@ -0,0 +1,264 @@
# NavSea Weather Server
Task: WeatherServer_GFS_Subset_Downloader
Architecture: V11
Codex: codex6
Status: TODO
---
# 任务目标
升级现有 gfs_downloader.py
当前问题:
直接下载完整 GFS 文件:
gfs.t00z.pgrb2.0p25.f000
文件大小:
≈ 500MB
下载 72 小时预测需要:
≈ 12GB
这是不可接受的。
解决方案:
使用 NOAA 提供的 GRIB Subset API
filter_gfs_0p25.pl
只下载:
1 指定区域
2 指定变量
3 指定高度层
目标:
将单个 GRIB 文件缩小到:
2MB 10MB
---
# 下载区域
NavSea 天气服务器只需要日本附近区域:
leftlon = 120
rightlon = 150
toplat = 50
bottomlat = 20
覆盖:
日本海
东海
太平洋日本海域
---
# 下载变量
Weather System V1 需要以下变量:
UGRD
VGRD
APCP
PRMSL
TMP
HTSGW
DIRPW
PERPW
说明:
UGRD VGRD → 风
APCP → 降水
PRMSL → 气压
TMP → 温度
HTSGW → 浪高
DIRPW → 浪方向
PERPW → 浪周期
变量参数来自 NOAA GFS 参数列表。 :contentReference[oaicite:0]{index=0}
---
# 下载高度层
需要以下层:
10 m above ground
surface
mean sea level
参数:
lev_10_m_above_ground
lev_surface
lev_mean_sea_level
---
# URL 构造规则
基础地址:
https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl
示例:
https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl?
file=gfs.t00z.pgrb2.0p25.f003
&lev_10_m_above_ground=on
&lev_surface=on
&lev_mean_sea_level=on
&var_UGRD=on
&var_VGRD=on
&var_APCP=on
&var_PRMSL=on
&var_TMP=on
&var_HTSGW=on
&var_DIRPW=on
&var_PERPW=on
&leftlon=120
&rightlon=150
&toplat=50
&bottomlat=20
&dir=%2Fgfs.20260312%2F00%2Fatmos
---
# 修改文件
weather_server/downloader/gfs_downloader.py
---
# 新代码
```python
import os
import requests
from datetime import datetime
BASE_URL = "https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl"
OUTPUT_DIR = "data/grib"
FORECAST_HOURS = [
0,3,6,9,12,15,18,21,24,
27,30,33,36,39,42,45,
48,51,54,57,60,63,66,
69,72
]
REGION = {
"leftlon":120,
"rightlon":150,
"toplat":50,
"bottomlat":20
}
VARIABLES = [
"UGRD",
"VGRD",
"APCP",
"PRMSL",
"TMP",
"HTSGW",
"DIRPW",
"PERPW"
]
LEVELS = [
"lev_10_m_above_ground",
"lev_surface",
"lev_mean_sea_level"
]
os.makedirs(OUTPUT_DIR, exist_ok=True)
def get_cycle():
now = datetime.utcnow()
hour = (now.hour // 6) * 6
cycle = f"{hour:02d}"
date = now.strftime("%Y%m%d")
return date, cycle
def build_url(date, cycle, fh):
filename = f"gfs.t{cycle}z.pgrb2.0p25.f{fh}"
params = {
"file": filename,
"leftlon": REGION["leftlon"],
"rightlon": REGION["rightlon"],
"toplat": REGION["toplat"],
"bottomlat": REGION["bottomlat"],
"dir": f"/gfs.{date}/{cycle}/atmos"
}
for v in VARIABLES:
params[f"var_{v}"] = "on"
for l in LEVELS:
params[l] = "on"
return BASE_URL, params
def download_file(url, params, path):
if os.path.exists(path):
print("skip", path)
return
print("downloading", path)
r = requests.get(url, params=params, stream=True)
if r.status_code != 200:
print("failed", r.status_code)
return
with open(path, "wb") as f:
for chunk in r.iter_content(1024*1024):
f.write(chunk)
def main():
date, cycle = get_cycle()
print("cycle:", date, cycle)
for fh in FORECAST_HOURS:
fh_str = f"{fh:03d}"
url, params = build_url(date, cycle, fh_str)
output = os.path.join(
OUTPUT_DIR,
f"{date}_{cycle}_f{fh_str}.grib2"
)
download_file(url, params, output)
if __name__ == "__main__":
main()