| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- """场景位置:data/scene_positions.csv 的读写(含初始种子)。
- 坐标存“参考系”(Z 不含随模型变化的 dz),前端应用时再叠加 dz。
- """
- import csv
- import os
- from typing import Any
- from config import DATA_DIR, SCENE_CSV
- FIELDS = [
- "id", "name",
- "camera_x", "camera_y", "camera_z",
- "target_x", "target_y", "target_z",
- ]
- # 初始种子:俯视 / 角度A(参考系坐标,与前端 VIEW_PRESETS 一致)。
- SEED: list[tuple[int, str, list[float], list[float]]] = [
- (1, "俯视", [2.0, 22.0, -3.2], [2.0, 0.0, -22.0]),
- (2, "角度A", [5.4, 16.7, -6.3], [9.4, 0.0, -22.5]),
- ]
- def _ensure_file() -> None:
- if SCENE_CSV.exists():
- return
- DATA_DIR.mkdir(parents=True, exist_ok=True)
- with SCENE_CSV.open("w", encoding="utf-8", newline="") as handle:
- writer = csv.writer(handle)
- writer.writerow(FIELDS)
- for scene_id, name, camera, target in SEED:
- writer.writerow([scene_id, name, *camera, *target])
- def _to_scene(row: dict[str, str]) -> dict[str, Any]:
- return {
- "id": int(row["id"]),
- "name": row["name"],
- "camera": [float(row["camera_x"]), float(row["camera_y"]), float(row["camera_z"])],
- "target": [float(row["target_x"]), float(row["target_y"]), float(row["target_z"])],
- }
- def _read() -> list[dict[str, Any]]:
- _ensure_file()
- with SCENE_CSV.open("r", encoding="utf-8", newline="") as handle:
- return [_to_scene(row) for row in csv.DictReader(handle)]
- def _write(scenes: list[dict[str, Any]]) -> None:
- DATA_DIR.mkdir(parents=True, exist_ok=True)
- tmp = SCENE_CSV.parent / (SCENE_CSV.name + ".tmp")
- with tmp.open("w", encoding="utf-8", newline="") as handle:
- writer = csv.writer(handle)
- writer.writerow(FIELDS)
- for scene in scenes:
- writer.writerow([scene["id"], scene["name"], *scene["camera"], *scene["target"]])
- os.replace(tmp, SCENE_CSV)
- def list_scenes() -> list[dict[str, Any]]:
- return _read()
- def add_scene(name: str, camera: list[float], target: list[float]) -> dict[str, Any]:
- scenes = _read()
- scene = {
- "id": max((s["id"] for s in scenes), default=0) + 1,
- "name": name,
- "camera": [float(v) for v in camera],
- "target": [float(v) for v in target],
- }
- scenes.append(scene)
- _write(scenes)
- return scene
- def rename_scene(scene_id: int, name: str) -> dict[str, Any] | None:
- scenes = _read()
- for scene in scenes:
- if scene["id"] == scene_id:
- scene["name"] = name
- _write(scenes)
- return scene
- return None
- def delete_scene(scene_id: int) -> bool:
- scenes = _read()
- remaining = [scene for scene in scenes if scene["id"] != scene_id]
- if len(remaining) == len(scenes):
- return False
- _write(remaining)
- return True
|