68 lines
2.6 KiB
Python
68 lines
2.6 KiB
Python
"""问题一算例:官方示例目录 ``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)]
|