"""问题一算例:官方示例目录 ``examples/q1`` + 随机交会算例。""" from __future__ import annotations import json import math import random from project.common import ROOT EXAMPLE_DIR = ROOT / "examples" / "q1" EXAMPLE_IDS = ("normal", "triangle", "poor", "segment", "empty") def load_examples() -> list[dict]: """读取固定算例;缺文件时跳过,保证离线可跑。""" cases = [] for key in EXAMPLE_IDS: path = EXAMPLE_DIR / f"{key}.json" if not path.exists(): continue raw = json.loads(path.read_text(encoding="utf-8-sig")) cases.append({ "id": raw.get("id", key), "name": raw.get("name", key), "source": "examples/q1", "measurements": [ {"x": float(row["x"]), "y": float(row["y"]), "bearing_deg": float(row["bearing_deg"]), "half_angle_deg": float(row.get("half_angle_deg", 1.0))} for row in raw["measurements"] ], }) return cases def random_case(seed: int) -> dict: """随机三点/四点交会:目标在 Ω 内,测站分布在不同象限。 仅生成"区域有界且非退化"的良态算例,避免参考网格因细长区域失效; 生成后由 ``compare`` 再用最优实现复核状态。 """ rng = random.Random(seed) target = (rng.uniform(-900, 900), rng.uniform(-900, 900)) count = rng.choice((3, 3, 4, 5)) stations = [] base_angle = rng.uniform(0, 360) for index in range(count): angle = base_angle + 360 * index / count + rng.uniform(-25, 25) radius = rng.uniform(500, 1100) stations.append((target[0] + radius * math.cos(math.radians(angle)), target[1] + radius * math.sin(math.radians(angle)))) measurements = [] for (sx, sy) in stations: true_bearing = math.degrees(math.atan2(target[1] - sy, target[0] - sx)) % 360.0 # 观测误差固定在同一地点、落在 ±1° 内;读数保留两位小数 error = rng.uniform(-0.9, 0.9) measurements.append({"x": round(sx, 2), "y": round(sy, 2), "bearing_deg": round((true_bearing + error) % 360.0, 2), "half_angle_deg": 1.0}) return {"id": f"rand-{seed}", "name": "随机交会", "source": "synthetic", "target": [round(target[0], 2), round(target[1], 2)], "measurements": measurements} def random_cases(count: int, base_seed: int = 7000) -> list[dict]: return [random_case(base_seed + index) for index in range(count)]