[ADD] AS/ES-Koordinatensysteme als K1/K2 exportieren + Kollision/Schleuselemente daran ausrichten

Export (Lisp/export.lsp):
- Neue csv:vfgf-k-kos-strings leitet fuer VF_n/GF_n-Wrapper K1 (AS/KS_EIN) und
  K2 (ES/KS_AUS) aus den verschachtelten AS_Element/ES_Element ab (via
  ssg-collect-nested-inserts) und schreibt sie wie K1-K4 als Positions-String.
  Bisher waren die K-Spalten fuer Strecken leer.

Kollisionspruefung Kreisel<->GF/VF (lib/export_neighbors.py):
- compute_neighbor_ids testet Strecken (GF/VF UND "ILS 2.0 Strecke - Modul")
  nicht mehr ueber die grosse Wrapper-Box, sondern ueber je eine kleine feste
  Box an der AS- (K1) und ES-Position (K2). Fallback auf Wrapper-Box, wenn
  K1/K2 fehlen (Altbestand).

Schleuselement-Positionen (lib/export_neighbors.py):
- compute_strecke_kreisel_schleus setzt Aus-/Einschleuselement ans AS/ES-KOS,
  um eine halbe Box entlang der Foerderachse nach aussen versetzt (AS: davor,
  ES: dahinter) - realistischer als der bisherige Kreiselrand-Punkt.

Keine Magic Numbers (cfg/export.cfg [Boundingbox]):
- element_box_laenge/breite/hoehe_mm (250/100/30) ersetzen die WEICHE_BOX_*-
  Konstanten; gelesen von load_element_box_mm und an alle Rechenfunktionen
  durchgereicht (WEICHE_BOX_* nur noch dokumentierter Fallback).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-04 14:00:52 +02:00
parent 29b7bf1a10
commit c88be420be
4 changed files with 254 additions and 40 deletions
+54
View File
@@ -381,6 +381,52 @@
)
)
;; --- K1 (AS/KS_EIN) / K2 (ES/KS_AUS) 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).
;; VF/GF-Wrapper fuehren - anders als Omniflo-Boegen - KEINE direkten K1-K4-
;; oder KS-Sub-INSERTs; ihre Streckenenden stecken je EINE Ebene tiefer:
;; KS_EIN im AS_Element*, KS_AUS im ES_Element* (siehe check_hoehen.lsp,
;; extract-ks-from-block-raw). ssg-collect-nested-inserts findet diese
;; verschachtelten INSERTs mit ihrer Platzierung RELATIV zur Wrapper-
;; Blockdefinition (ename/(x y z)/... - der zweite Eintrag ist der Ursprung
;; des KS-INSERTs, also die AS-/ES-Position). Der lokale Punkt 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 Python-Kollisionspruefung
;; (export_neighbors.py: Schleuselemente + Kreisel-Kollision ueber die AS/ES-
;; Position mit fester BBox statt der ganzen Wrapper-Box).
;; 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 as-hits es-hits result
loc world)
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
(setq result nil)
;; KS-INSERTs (KS_EIN/KS_AUS bzw. KSYS_-Varianten) direkt im AS_Element/
;; ES_Element suchen. wcmatch ist Gross/Klein-unempfindlich fuer Blocknamen.
(setq as-hits (ssg-collect-nested-inserts bname "KS_EIN,KSYS_EIN"))
(setq es-hits (ssg-collect-nested-inserts bname "KS_AUS,KSYS_AUS"))
(if as-hits
(progn
(setq loc (cadr (car as-hits)))
(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))
)
)
(if es-hits
(progn
(setq loc (cadr (car es-hits)))
(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))
)
)
result
)
;; --- Mindesthoehe der Bounding-Box (Z-Ausdehnung), aus cfg/export.cfg ---
;; [Boundingbox] bb_minimum_height_mm, Default 1 (mm) falls nicht gesetzt.
@@ -487,6 +533,14 @@
(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.
(if (and (null k-list)
(wcmatch (strcase blk-name) "VF_*,GF_*"))
(setq k-list (csv:vfgf-k-kos-strings ename pt rotation))
)
(setq bbox-json "")
(if include-bbox
(progn