chore(tools): AD-vejnet-værktøjer (45°-kurver, parkering, reparationer) brugt på savegame2 30/9

This commit is contained in:
2026-09-30 15:32:21 +02:00
parent 68eb26d71d
commit a3d234a3a2
7 changed files with 798 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
"""Savegame2 30/9: reparationer af AD-vejnettet fundet ved gennemgangen.
1. Punkt 19564 (spor til 'P Forage Wagon') lå 5,6 km væk -> midt mellem naboerne.
2. Biogas Drop 1/2/4/5 var blindgyder (kun vej ind) -> sidste kant gøres tovejs som Drop 3.
3. Chicken Wait 5: 81° knæk ved 12808 (AD tillader 80°) -> privat spor 12808..12815 lagt om i en blød kurve.
4. 'Food And More' lå på en afbrudt stump oven på vejen -> markøren flyttes til vejpunkt 8416.
Brug: netfix.py <ind.xml> <ud.xml>
"""
import math, re, sys, os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from adsmooth import read, write, link, dist
src, dst = sys.argv[1], sys.argv[2]
doc = read(src); N = doc["N"]
mk = {m.group(2): int(float(m.group(1))) for m in re.finditer(r"<mm\d+>\s*<id>([\d.]+)</id>\s*<name>([^<]*)</name>", doc["s"])}
# 1
a, b = N[19563], N[19565]
assert dist(N[19564], a) > 1000, "19564 ser allerede rigtig ud"
for ax in "xyz":
N[19564][ax] = (a[ax] + b[ax]) / 2
print("19564 ->", round(N[19564]["x"], 2), round(N[19564]["z"], 2))
# 2
for name in ("Biogas Drop 1", "Biogas Drop 2", "Biogas Drop 4", "Biogas Drop 5"):
w = mk[name]; assert not N[w]["out"], name
for p in list(N[w]["inc"]):
link(N, w, p)
print(name, "tovejs mod", N[w]["out"])
# 3 kurve fra 12802 (retning fra 12801) til 12697 (retning mod 12698)
chain = [12808, 12809, 12810, 12811, 12812, 12813, 12814, 12815]
for i in chain:
assert len(N[i]["inc"]) == 1 and len(N[i]["out"]) == 1, i
P0, P3 = N[12802], N[12697]
def unit(u, v):
L = dist(u, v); return ((v["x"] - u["x"]) / L, (v["z"] - u["z"]) / L)
t0, t3 = unit(N[12801], P0), unit(P3, N[12698])
seq = [12801, 12802] + chain + [12697, 12698]
def ang(p, b, c):
v1 = (N[b]["x"] - N[p]["x"], N[b]["z"] - N[p]["z"]); v2 = (N[c]["x"] - N[b]["x"], N[c]["z"] - N[b]["z"])
return math.degrees(math.acos(max(-1, min(1, (v1[0] * v2[0] + v1[1] * v2[1]) / (math.hypot(*v1) * math.hypot(*v2))))))
def shape(k0, k3, g):
P1 = {"x": P0["x"] + t0[0] * k0, "z": P0["z"] + t0[1] * k0}
P2 = {"x": P3["x"] - t3[0] * k3, "z": P3["z"] - t3[1] * k3}
n = len(chain) + 1
for j, i in enumerate(chain, 1):
t = (j / n) ** g # g skubber punkterne mod den skarpe ende
for ax in "xz":
N[i][ax] = (1 - t) ** 3 * P0[ax] + 3 * (1 - t) ** 2 * t * P1[ax] + 3 * (1 - t) * t * t * P2[ax] + t ** 3 * P3[ax]
N[i]["y"] = P0["y"] + (P3["y"] - P0["y"]) * t
return max(ang(*seq[i:i + 3]) for i in range(len(seq) - 2))
D = dist(P0, P3)
best = min(((shape(a * D, b * D, g), a, b, g) for a in (0.2, 0.35, 0.5, 0.7, 0.9, 1.2) for b in (0.2, 0.35, 0.5, 0.7, 0.9, 1.2) for g in (0.7, 0.85, 1.0, 1.2)))
worst = shape(best[1] * D, best[2] * D, best[3])
print("Chicken Wait 5-kurve: største knæk %.1f°" % worst)
assert worst <= 45
write(doc, dst)
# 4 markør
s = open(dst, encoding="utf-8-sig").read()
s, cnt = re.subn(r"(<id>)8481\.000000(</id>\s*<name>Food And More</name>)", r"\g<1>8416.000000\g<2>", s)
assert cnt == 1
open(dst, "wb").write(b"\xef\xbb\xbf" + s.encode("utf-8"))
print("Food And More -> 8416")