[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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user