[FIX] CSV-Export K1/K2 = Eingang/Ausgang; GF-Richtung ueber die Hoehe

K1 ist jetzt IMMER der Eingang eines Elements, K2 IMMER der Ausgang
(AS = Eingangs-Element mit KS_EIN, ES = Ausgangs-Element mit KS_AUS).

- VarioFoerderer/Strecke (VF_*): Richtung liegt ueber die Elementrolle fest
  -> K1 = AS-Ende (KS_EIN), K2 = ES-Ende (KS_AUS). Verhalten unveraendert.
- Gefaellestrecke (GF_*): Foerderrichtung ist bergab, also durch die HOEHE
  bestimmt (HOEHE_VON_mm > HOEHE_BIS_mm, siehe check_hoehen.lsp). Der Eingang
  ist das HOEHERE Ende, der Ausgang das TIEFERE - unabhaengig davon, welches
  physische Element das AS bzw. ES ist. csv:vfgf-k-kos-strings sortiert bei
  GF darum nach Z (hoeheres Z -> K1, tieferes Z -> K2); Fallback auf die
  Rolle, wenn nur ein Ende gefunden wird.

Verifiziert: vario-VF K1 bei VF-x=0 (AS), K2 bei VF-x=15000 (ES);
mubea-GF 0016 AS_z=1852 >= ES_z=1537 -> K1=Eingang(hoch), K2=Ausgang(tief).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-04 21:41:43 +02:00
parent 7eff324056
commit 842e93c571
+43 -26
View File
@@ -425,7 +425,7 @@
)
)
;; --- K1 (AS/KS_EIN) / K2 (ES/KS_AUS) eines VF_n/GF_n-Wrappers ableiten ---
;; --- K1 (Eingang) / K2 (Ausgang) eines VF_n/GF_n-Wrappers ableiten ---
;; ename = Entity-Name des platzierten VF_n/GF_n-INSERT.
;; pt/rot-rad = Welt-Einfuegepunkt/-Rotation (radiant) des Wrappers (siehe
;; csv:block-to-json).
@@ -437,36 +437,52 @@
;; Elemente tragen beide KS-Typen). Der so ermittelte Punkt (Wrapper-Frame)
;; wird ueber die Wrapper-Weltlage (reine Z-Drehung) in Weltkoordinaten
;; gedreht und wie K1-K4 als reiner Positions-String (csv:trans-encode)
;; exportiert. Damit hat auch eine Strecke K1 (AS) und K2 (ES) fuer die
;; exportiert. Damit hat auch eine Strecke K1 und K2 fuer die
;; Python-Kollisionspruefung (export_neighbors.py: Schleuselemente +
;; Kreisel-Kollision ueber die AS/ES-Position mit fester BBox statt der
;; ganzen Wrapper-Box).
;;
;; RICHTUNG: K1 ist IMMER der Eingang eines Elements, K2 IMMER der Ausgang.
;; AS = Eingangs-Element (traegt KS_EIN), ES = Ausgangs-Element (traegt KS_AUS).
;; - VarioFoerderer/Strecke (VF_*): Richtung liegt ueber die Elementrolle
;; fest -> K1 = AS-Ende (KS_EIN), K2 = ES-Ende (KS_AUS).
;; - Gefaellestrecke (GF_*): Foerderrichtung ist bergAB, also durch die HOEHE
;; bestimmt (siehe HOEHE_VON_mm > HOEHE_BIS_mm, check_hoehen.lsp). Der
;; Eingang ist das HOEHERE Ende, der Ausgang das TIEFERE - unabhaengig
;; davon, welches der beiden physischen Elemente das AS bzw. ES ist. Darum
;; wird bei GF nach Z sortiert (hoeheres Z -> K1, tieferes Z -> K2).
;; Rueckgabe wie csv:get-k-kos-strings: (("K1" . str) ("K2" . str)) - nur die
;; tatsaechlich gefundenen Enden.
(defun csv:vfgf-k-kos-strings (ename pt rot-rad / ed bname loc world result)
(defun csv:vfgf-k-kos-strings (ename pt rot-rad / ed bname as-loc es-loc
as-world es-world ein-world aus-world result)
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
(setq result nil)
;; K1 = KS_EIN aus dem AS_Element, K2 = KS_AUS aus dem ES_Element. Die
;; Element-Zuordnung ist zwingend (jedes Element traegt beide KS-Typen,
;; siehe csv:vfgf-ks-loc). Ergebnis-Frame -> Weltlage ueber die reine
;; Z-Drehung des Wrappers (csv:local-to-world).
(setq loc (csv:vfgf-ks-loc bname "AS_ELEMENT*" "KS_EIN,KSYS_EIN"))
(if loc
(progn
(setq world (csv:local-to-world pt rot-rad loc))
(setq result (cons (cons "K1"
(csv:trans-encode (car world) (cadr world) (caddr world))) result))
)
)
(setq loc (csv:vfgf-ks-loc bname "ES_ELEMENT*" "KS_AUS,KSYS_AUS"))
(if loc
(progn
(setq world (csv:local-to-world pt rot-rad loc))
(setq result (cons (cons "K2"
(csv:trans-encode (car world) (cadr world) (caddr world))) result))
)
;; Beide Enden im Wrapper-Frame holen und in Weltkoordinaten (reine
;; Z-Drehung) umrechnen. AS traegt das KS_EIN, ES das KS_AUS - jeweils aus
;; dem RICHTIGEN Element (csv:vfgf-ks-loc; beide Elemente fuehren beide
;; KS-Typen).
(setq as-loc (csv:vfgf-ks-loc bname "AS_ELEMENT*" "KS_EIN,KSYS_EIN"))
(setq es-loc (csv:vfgf-ks-loc bname "ES_ELEMENT*" "KS_AUS,KSYS_AUS"))
(if as-loc (setq as-world (csv:local-to-world pt rot-rad as-loc)))
(if es-loc (setq es-world (csv:local-to-world pt rot-rad es-loc)))
;; Eingang/Ausgang festlegen (siehe Richtung im Kopfkommentar).
(cond
;; GF: Richtung ueber die Hoehe - hoeheres Z = Eingang, tieferes Z = Ausgang.
;; Nur wenn BEIDE Enden vorhanden sind; sonst faellt es auf die Rolle zurueck.
((and (wcmatch (strcase bname) "GF_*") as-world es-world)
(if (>= (caddr as-world) (caddr es-world))
(setq ein-world as-world aus-world es-world)
(setq ein-world es-world aus-world as-world)))
;; VF/Strecke (und GF mit nur einem Ende): AS = Eingang, ES = Ausgang.
(t (setq ein-world as-world aus-world es-world))
)
(if ein-world
(setq result (cons (cons "K1"
(csv:trans-encode (car ein-world) (cadr ein-world) (caddr ein-world))) result)))
(if aus-world
(setq result (cons (cons "K2"
(csv:trans-encode (car aus-world) (cadr aus-world) (caddr aus-world))) result)))
(reverse result)
)
@@ -576,10 +592,11 @@
(export:pattern "pattern_gerade" "AP110*,AP_110*")))
(setq k-list (csv:gerade-k-kos-strings ename pt rotation))
)
;; VF_n/GF_n-Wrapper: K1 (AS/KS_EIN) und K2 (ES/KS_AUS) eine Ebene tiefer
;; aus AS_Element/ES_Element ableiten (siehe csv:vfgf-k-kos-strings). Damit
;; die Python-Kollisionspruefung Kreisel<->Strecke ueber die AS/ES-Position
;; mit fester BBox statt der ganzen Wrapper-Box arbeiten kann.
;; VF_n/GF_n-Wrapper: K1 (Eingang) und K2 (Ausgang) eine Ebene tiefer aus
;; AS_Element/ES_Element ableiten (siehe csv:vfgf-k-kos-strings; VF ueber die
;; Elementrolle, GF ueber die Hoehe). Damit die Python-Kollisionspruefung
;; Kreisel<->Strecke ueber die AS/ES-Position mit fester BBox statt der
;; ganzen Wrapper-Box arbeiten kann.
(if (and (null k-list)
(wcmatch (strcase blk-name) "VF_*,GF_*"))
(setq k-list (csv:vfgf-k-kos-strings ename pt rotation))