[ADD] dxf_scan_components.py: Separatoren/Scanner auf einer Kreisel-Kette uebernehmen dessen Anwender-Hoehe (sensor_hoehen_von_kreiseln, bei --kreisel-hoehe) + Tests; [FIX] GF-Winkel aus Kreisel-Hoehen (dematic_arvato:gf-winkel): Modus 1 haelt die horizontale Laenge fest - Abfall = (deltaL - aus-dx - ein-dx) * tan(w) statt asin-Naeherung von gf-winkel-berechnen, ES-Abfall beim aktuellen Winkel gemessen und iteriert (steile GF wie Showroom ~37 Grad endeten sonst weit unter dem Kreisel); [CHANGE] Showroom ILS: Testdaten und Treiber aktualisiert

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 15:23:39 +02:00
parent d403c23e5b
commit 8885b5c96a
5 changed files with 267 additions and 153 deletions
+53
View File
@@ -1973,6 +1973,53 @@ def hoehen_entfernen(eintraege):
return n
# Querabstand (mm) zur Kreisel-Kette, bis zu dem ein Einzelteil (Separator,
# Scanner) als "auf dem Kreisel" gilt und dessen Anwender-Hoehe bekommt.
SENSOR_KETTE_MAX_QUER = 350.0
def sensor_hoehen_von_kreiseln(eintraege, durchmesser=800.0):
"""Einzelteile auf einer Kreisel-Kette bekommen dessen Anwender-Hoehe.
Im flachen 2D-Plan (--ohne-hoehen) stehen Separatoren/Scanner sonst auf
Z=0, waehrend der Kreisel per --kreisel-hoehe auf seiner Hoehe sitzt.
Kette = Achse (Einfuegepunkt + Radius entlang rotation, Laenge abstand)
im Abstand r beidseits, plus die Halbkreise an den Enden. Nur Kreisel mit
hoehe_quelle "Anwender"; bei mehreren gewinnt der naechste.
Rueckgabe: Anzahl gesetzter Hoehen.
"""
r = durchmesser / 2.0
kreisel = []
for e in eintraege:
if "abstand" in e and e.get("hoehe_quelle") == "Anwender":
w = math.radians(e.get("rotation", 0.0))
u = (math.cos(w), math.sin(w))
a = (e["x"] + r * u[0], e["y"] + r * u[1])
kreisel.append((e, a, u, float(e["abstand"])))
gesetzt = 0
for e in eintraege:
if e.get("function") != "insert" or "block" not in e:
continue
beste = None
for k, a, u, laenge in kreisel:
vx, vy = e["x"] - a[0], e["y"] - a[1]
t = max(0.0, min(laenge, vx * u[0] + vy * u[1]))
# Abstand zur Achse (Strecke), davon r abgezogen = Abstand zur Kette
d = abs(math.hypot(vx - t * u[0], vy - t * u[1]) - r)
if d <= SENSOR_KETTE_MAX_QUER and (beste is None or d < beste[0]):
beste = (d, k)
if beste:
k = beste[1]
e["z"] = float(k["z"])
e["hoehe_quelle"] = "Anwender"
e.pop("hoehe_unbekannt", None)
e["comment"] += " Hoehe %.1f von %s (liegt auf dessen Kette)." % (
k["z"], k["id"])
gesetzt += 1
return gesetzt
def arrays_einzeilig(text):
"""Zahlen-Arrays im JSON-Text auf eine Zeile ziehen.
@@ -2133,6 +2180,12 @@ def main():
if args.ohne_hoehen:
print("%s --ohne-hoehen: Hoehe in %d Eintraegen auf 0 gesetzt"
% (PREFIX, hoehen_entfernen(eintraege)))
if args.kreisel_hoehe:
print("%s Einzelteile auf Kreisel-Ketten: Hoehe in %d Eintraegen vom "
"Kreisel uebernommen"
% (PREFIX, sensor_hoehen_von_kreiseln(
eintraege,
defaults.get("kreisel", {}).get("durchmesser", 800.0))))
if fenster:
vorher = len(eintraege)