Initial import

This commit is contained in:
OpenAI Codex
2026-03-17 19:52:51 +08:00
commit c957fef15b
39 changed files with 7108 additions and 0 deletions

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()