From 2f56729308108afd4fce93ec334e0bd7a13c4f22 Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Wed, 23 Sep 2026 17:28:31 +0200 Subject: [PATCH] export_csv: Separator-TYP (VF/GF) bauzeitig je Separator statt vom Wrapper-Blocknamen ableiten csv:wrapper-strecke-typ (voriger Ansatz) las den Streckentyp aus dem VF_n/GF_n-Wrapper-Blocknamen - falsch, weil ein einzelner Wrapper intern mehrfach zwischen Foerderer- und Gefaellestrecke-Abschnitten wechseln kann (HundM05 VF_1: 4 Separatoren, 2x VF, 2x GF). Jede Separator-Einfuegestelle in vf_linienzug.lsp/Gefaellestrecke.lsp/vf_standard.lsp/vf_etage.lsp markiert das frisch eingefuegte Staustrecke_Separator_SP_300_mm-Insert jetzt direkt per XDATA (ssg-sep-typ-xdata-schreiben/-lesen, ssg_ks_insert.lsp). Der Export liest den Marker am verpackten Original (nested-ent), nicht mehr am Wrapper. Co-Authored-By: Claude Sonnet 5 --- Lisp/Gefaellestrecke.lsp | 3 +++ Lisp/export.lsp | 55 +++++++++++++++++++++++++++++++++------- Lisp/ssg_ks_insert.lsp | 32 +++++++++++++++++++++++ Lisp/vf_etage.lsp | 2 ++ Lisp/vf_linienzug.lsp | 9 +++++++ Lisp/vf_standard.lsp | 2 ++ lib/export_csv.py | 9 ++++++- 7 files changed, 102 insertions(+), 10 deletions(-) diff --git a/Lisp/Gefaellestrecke.lsp b/Lisp/Gefaellestrecke.lsp index f4507e4..de7fc1b 100644 --- a/Lisp/Gefaellestrecke.lsp +++ b/Lisp/Gefaellestrecke.lsp @@ -665,6 +665,7 @@ (setq endpunkt (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car aktuell-frame) hz grade 300 0)) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") (setq aktuell-frame (make-frame-from-dir endpunkt xu-incl)) ) ) @@ -996,6 +997,7 @@ (setq sep-endpunkt (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car aktuell-frame) exit-hz grade 300 0)) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") ;; Ausgangsrahmen nach Separator fuer ES-Element (setq rad-h-es (* (float exit-hz) (/ pi 180.0))) (setq rad-v-es (* (float grade) (/ pi 180.0))) @@ -1377,6 +1379,7 @@ (setq sep-endpunkt (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car aktuell-frame) hz winkel 300 0)) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") (setq sep-frame (make-frame-from-dir sep-endpunkt xu-incl)) ;; 4/4: EIN-Element (KS-zu-KS) diff --git a/Lisp/export.lsp b/Lisp/export.lsp index c96eae2..c42cee3 100644 --- a/Lisp/export.lsp +++ b/Lisp/export.lsp @@ -652,7 +652,9 @@ (defun csv:block-to-json (ename include-bbox / ed blk-name layer pt rotation extrusion R-world handle attribs bbox bbox-json insert-quat insert-kos k-list warnung-json warnung-eintrag - zuordnung-fix-json zuordnung-fix-eintrag sepliste-json sepliste-app sepliste + zuordnung-fix-json zuordnung-fix-eintrag + strecke-typ-json strecke-typ-eintrag + sepliste-json sepliste-app sepliste sepliste-teile sepliste-first sepliste-ids sep-id) (setq ed (entget ename)) (setq blk-name (cdr (assoc 2 ed))) @@ -747,6 +749,18 @@ (setq zuordnung-fix-json (strcat ",\"zuordnung_fix\":\"" (csv:json-escape (cdr zuordnung-fix-eintrag)) "\"")) ) + ;; Streckentyp (VF/GF) DIESES EINZELNEN Separators, bauzeitig gesetzt + ;; (ssg-sep-typ-xdata-schreiben, siehe csv:sep-proxies-erzeugen/ + ;; -zuordnung-setzen) - NICHT vom Wrapper-Blocknamen ableitbar, da ein + ;; VF_n/GF_n-Wrapper intern zwischen VF-/GF-Abschnitten wechseln kann. + ;; export_csv.py schreibt diesen Wert in die Merkmale der Proxy-Zeile + ;; (Feld "Typ"). + (setq strecke-typ-json "") + (setq strecke-typ-eintrag (assoc handle *cs-sep-typ-by-handle*)) + (if strecke-typ-eintrag + (setq strecke-typ-json + (strcat ",\"strecke_typ\":\"" (csv:json-escape (cdr strecke-typ-eintrag)) "\"")) + ) ;; VF_n/GF_n-Wrapper: Separator-/AS-/ES-Reihenfolge aus der beim Bau ;; geschriebenen XDATA lesen (siehe ssg-sepliste-xdata-lesen, ;; ssg_ks_insert.lsp) und als "sepliste"-Array einbetten. Nur gesetzt, wenn @@ -808,6 +822,7 @@ bbox-json warnung-json zuordnung-fix-json + strecke-typ-json sepliste-json "}" ) @@ -1026,6 +1041,15 @@ ;; jeden Fund eine ECHTE Kopie DESSELBEN Blocks an derselben Weltlage. ;; Die AS-/ES-Kettenenden laufen NICHT mehr hierueber - fuer sie setzt ;; csv:asmark-aktualisieren einen dauerhaften Marker (siehe dort). +;; +;; proxy-liste-Eintrag: (proxy-ename wrapper-ename typ (x y z) strecke-typ). +;; strecke-typ = "VF"/"GF"/nil, gelesen von ssg-sep-typ-xdata-lesen AM +;; VERPACKTEN ORIGINAL (nested-ent, nth 1 rec) - NICHT vom Wrapper-Blocknamen +;; abgeleitet (fruehere Fehlannahme, siehe lib/dump_vf_kette_inhalt.py): ein +;; einzelner VF_n/GF_n-Wrapper kann intern mehrfach zwischen Foerderer- und +;; Gefaellestrecke-Abschnitten wechseln, der Marker sitzt daher direkt am +;; Separator-Insert (gesetzt bauzeitig in vf_linienzug.lsp/Gefaellestrecke.lsp/ +;; vf_standard.lsp/vf_etage.lsp, direkt nach dessen Einfuegung). (defun csv:sep-proxies-erzeugen ( / ms recs rec proxy proxy-liste) (setq recs (csv:nested-welt-records (csv:pattern-nested-separator))) (if recs @@ -1037,7 +1061,8 @@ (cdr (assoc 2 (entget (nth 0 rec)))))) (if proxy (setq proxy-liste - (cons (list proxy (nth 0 rec) (csv:proxy-typ (nth 2 rec)) (nth 3 rec)) + (cons (list proxy (nth 0 rec) (csv:proxy-typ (nth 2 rec)) (nth 3 rec) + (ssg-sep-typ-xdata-lesen (nth 1 rec))) proxy-liste))) ) ) @@ -1060,20 +1085,32 @@ ;; Zuordnung ueber *cs-sep-fix-by-handle* (Key = Entity-Handle der Kopie) ;; festgenagelt; cs-zuordnung-lauf uebernimmt sie unveraendert und zaehlt den ;; Separator beim richtigen Carrier. -;; proxy-liste = Records (proxy-ename wrapper-ename typ (x y z)), siehe -;; csv:nested-proxies-erzeugen. Rueckgabe: Anzahl festgenagelter Kopien. +;; +;; Gleich nebenbei wird der bauzeitig ermittelte Streckentyp (VF/GF) dieses +;; EINZELNEN Separators (nth 4 rec, siehe csv:sep-proxies-erzeugen) ueber +;; *cs-sep-typ-by-handle* festgehalten. csv:block-to-json schreibt den Wert +;; als "strecke_typ" mit in die Proxy-Zeile. NICHT vom Wrapper-Blocknamen +;; ableiten (fruehere Fehlannahme) - ein einzelner VF_n/GF_n-Wrapper kann +;; intern mehrfach zwischen VF- und GF-Abschnitten wechseln. +;; proxy-liste = Records (proxy-ename wrapper-ename typ (x y z) strecke-typ), +;; siehe csv:sep-proxies-erzeugen. Rueckgabe: Anzahl festgenagelter Kopien. (defun csv:sep-proxies-zuordnung-setzen (proxy-liste / rec proxy wrapper wrapper-id - handle gesetzt ohne-id) + handle gesetzt ohne-id strecke-typ) (setq gesetzt 0 ohne-id 0) (setq *cs-sep-fix-by-handle* nil) + (setq *cs-sep-typ-by-handle* nil) (foreach rec proxy-liste (setq proxy (nth 0 rec)) (setq wrapper (nth 1 rec)) + (setq handle (cdr (assoc 5 (entget proxy)))) + (setq strecke-typ (nth 4 rec)) + (if strecke-typ + (setq *cs-sep-typ-by-handle* + (cons (cons handle strecke-typ) *cs-sep-typ-by-handle*))) (setq wrapper-id (cdr (assoc "ID" (ssg-attrib-read wrapper)))) (if (and wrapper-id (> (strlen wrapper-id) 0)) (progn (ssg-attrib-set-on proxy (list (cons "ZUORDNUNG" wrapper-id))) - (setq handle (cdr (assoc 5 (entget proxy)))) (setq *cs-sep-fix-by-handle* (cons (cons handle wrapper-id) *cs-sep-fix-by-handle*)) (setq gesetzt (1+ gesetzt)) @@ -1192,9 +1229,8 @@ ) ;; --- Nach der ID-Vergabe: ID jeder Kopie an ihren sepliste-Eintrag haengen --- -;; proxy-liste = Records (proxy-ename wrapper-ename typ (x y z)) aus -;; csv:sep-proxies-erzeugen UND csv:schleus-proxies-erzeugen - beide Listen -;; zusammen uebergeben, AS/ES und SEP stehen in DERSELBEN sepliste. +;; proxy-liste = Records (proxy-ename wrapper-ename typ (x y z) strecke-typ) +;; aus csv:sep-proxies-erzeugen (das 5. Feld wird hier nicht gebraucht). ;; MUSS nach ssg-id-check-all laufen: vorher hat eine frisch erzeugte Kopie ;; noch keine ID. ;; @@ -1590,6 +1626,7 @@ (foreach rec proxy-liste (entdel (car rec))) ) (setq *cs-sep-fix-by-handle* nil) + (setq *cs-sep-typ-by-handle* nil) (setq *csv-sepliste-id-by-handle* nil) (princ) ) diff --git a/Lisp/ssg_ks_insert.lsp b/Lisp/ssg_ks_insert.lsp index 35e21e4..985691e 100644 --- a/Lisp/ssg_ks_insert.lsp +++ b/Lisp/ssg_ks_insert.lsp @@ -610,6 +610,38 @@ ent ) +;; --- Streckentyp (VF/GF) EINES Separator-Inserts als XDATA vermerken --- +;; App "SSG_SEP_TYP", einzelne 1000-Gruppe = "VF"/"GF". Anders als die +;; Sepliste (EIN Eintrag je Wrapper, alle Separatoren zusammengefasst) sitzt +;; dieser Marker DIREKT am einzelnen Staustrecke_Separator_SP_300_mm-Insert - +;; noetig, weil ein einzelner VF_n/GF_n-Wrapper intern mehrfach zwischen +;; Foerderer- und Gefaellestrecke-Abschnitten wechseln kann (siehe +;; lib/dump_vf_kette_inhalt.py: HundM05 VF_1 hat 4 Separatoren, 2x VF, 2x GF). +;; Der Wrapper-Blockname (VF_n/GF_n) sagt darueber nichts aus und darf dafuer +;; NICHT herangezogen werden (fruehere Fehlannahme). Aufrufer: die +;; Separator-Einfuegestellen in vf_linienzug.lsp/Gefaellestrecke.lsp/ +;; vf_standard.lsp/vf_etage.lsp, direkt nach gf-insert-hz-with-ks (ueber +;; entlast - zwischen Insert und Tag darf nichts anderes erzeugt werden). +;; Gelesen von csv:sep-proxies-erzeugen (export.lsp) am NESTED-Original +;; (nested-ent), bevor die temporaere Kopie entsteht. +(defun ssg-sep-typ-xdata-schreiben (ent typ) + (if (and ent typ) + (progn + (regapp "SSG_SEP_TYP") + (entmod (append (entget ent) (list (list -3 (list "SSG_SEP_TYP" (cons 1000 typ)))))) + ) + ) + ent +) + +;; Liest den Streckentyp-Marker zurueck. Rueckgabe: "VF"/"GF" oder nil (kein +;; Marker - z.B. Altbestand ohne den neuen Bauzeit-Tag). +(defun ssg-sep-typ-xdata-lesen (ent / xd app-data) + (setq xd (entget ent (list "SSG_SEP_TYP"))) + (setq app-data (cdr (assoc -3 xd))) + (if app-data (cdr (cadr (car app-data))) nil) +) + ;; Liest die Sepliste-XDATA. Rueckgabe: Liste von (typ lfdnr x y), oder nil ;; (kein/unbekanntes Sepliste-XDATA am Entity). (defun ssg-sepliste-xdata-lesen (ent app-name / xd app-data werte) diff --git a/Lisp/vf_etage.lsp b/Lisp/vf_etage.lsp index 8147fd4..40423b1 100644 --- a/Lisp/vf_etage.lsp +++ b/Lisp/vf_etage.lsp @@ -534,6 +534,7 @@ (setq aktueller-punkt (insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt as-hz *vfk-gefaelle-winkel* *vfk-separator-laenge* 0)) + (ssg-sep-typ-xdata-schreiben (entlast) "VF") ;; Ab hier laufende Richtung cur-hz mitfuehren (frame-verkettet). Start = ;; KS_AUS-Richtung des AS (as-hz). Jeder Gefaellebogen dreht cur-hz um seinen @@ -686,6 +687,7 @@ (setq aktueller-punkt (insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt cur-hz *vfk-gefaelle-winkel* *vfk-separator-laenge* 0)) + (ssg-sep-typ-xdata-schreiben (entlast) "VF") ;; 15. ES_30 (verkettet: KS_EIN auf cur-hz; KS_AUS auf der Hauptlinie) (princ (ssg-textf "vfe-step15" (list es-block (rtos cur-hz 2 1)))) diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index 4d11e93..26a5707 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -3474,6 +3474,7 @@ (defun vfl-sep-hz (pt hz / ep) (princ (ssg-text "vfl-sep-horizontal-info")) (setq ep (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" pt hz 0 *vfk-separator-laenge* 0)) + (ssg-sep-typ-xdata-schreiben (entlast) "VF") (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)) ep) @@ -6204,6 +6205,7 @@ (setq w (ssg-cfg-or "vario" "gefaelle_winkel" 3)) (setq sep-endpunkt (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car frame) hz w *vfk-separator-laenge* 0)) + (ssg-sep-typ-xdata-schreiben (entlast) "VF") (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)) (make-frame-from-dir sep-endpunkt (hz-winkel->xu hz w)) ) @@ -6222,6 +6224,7 @@ (setq w-eff (if (= typ "GF") winkel (ssg-cfg-or "vario" "gefaelle_winkel" 3))) (setq sep-endpunkt (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car frame) hz w-eff *vfk-separator-laenge* 0)) + (ssg-sep-typ-xdata-schreiben (entlast) typ) (setq sep-frame (make-frame-from-dir sep-endpunkt (hz-winkel->xu hz w-eff))) (if (boundp '*vfl-acc-separator*) (setq *vfl-acc-separator* (1+ *vfl-acc-separator*))) ; Separator vor ES @@ -7249,6 +7252,7 @@ (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car frame) hz-neu winkel *vfk-separator-laenge* 0) (hz-winkel->xu hz-neu winkel))) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)) ) ) @@ -7272,6 +7276,7 @@ (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car frame) hz-neu winkel *vfk-separator-laenge* 0) (hz-winkel->xu hz-neu winkel))) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)) (setq letzter-typ "Separator") (setq p-aktuell (car frame)) @@ -9919,6 +9924,7 @@ (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car frame) hz winkel *vfk-separator-laenge* 0) (hz-winkel->xu hz winkel))) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)))) (setq frame (vfl-insert-gf-segment (car frame) hz deltaL winkel)) (vfl-acc-gf-seg (/ deltaL (cos (* winkel (/ pi 180.0)))) winkel) @@ -9929,6 +9935,7 @@ (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car frame) hz winkel *vfk-separator-laenge* 0) (hz-winkel->xu hz winkel))) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") (setq *vfl-acc-separator* (1+ *vfl-acc-separator*))))) ((= typ "Bogen") (setq bwinkel (nth 3 seg) bseite (nth 4 seg) klass (nth 5 seg)) @@ -10254,6 +10261,7 @@ (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car frame) hz winkel *vfk-separator-laenge* 0) (hz-winkel->xu hz winkel))) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)))) (setq frame (vfl-insert-gf-segment (car frame) hz deltaL winkel)) (vfl-acc-gf-seg (/ deltaL (cos (* winkel (/ pi 180.0)))) winkel) @@ -10264,6 +10272,7 @@ (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" (car frame) hz winkel *vfk-separator-laenge* 0) (hz-winkel->xu hz winkel))) + (ssg-sep-typ-xdata-schreiben (entlast) "GF") (setq *vfl-acc-separator* (1+ *vfl-acc-separator*))))) ((= typ "Bogen") (setq bwinkel (nth 3 seg) bseite (nth 4 seg) klass (nth 5 seg)) diff --git a/Lisp/vf_standard.lsp b/Lisp/vf_standard.lsp index 96825ab..8e09207 100644 --- a/Lisp/vf_standard.lsp +++ b/Lisp/vf_standard.lsp @@ -593,6 +593,7 @@ (ssg-cfg-or "vario" "gefaelle_winkel" 3) (ssg-cfg-or "vario" "separator_block_dx" 300) (ssg-cfg-or "vario" "separator_block_dz" 0) hz)) + (ssg-sep-typ-xdata-schreiben (entlast) "VF") ) ) ;; 3. Umlenkstation @@ -757,6 +758,7 @@ (ssg-cfg-or "vario" "gefaelle_winkel" 3) (ssg-cfg-or "vario" "separator_block_dx" 300) (ssg-cfg-or "vario" "separator_block_dz" 0) hz)) + (ssg-sep-typ-xdata-schreiben (entlast) "VF") ) ) aktueller-punkt diff --git a/lib/export_csv.py b/lib/export_csv.py index 0b83f1c..06701a5 100644 --- a/lib/export_csv.py +++ b/lib/export_csv.py @@ -237,13 +237,20 @@ def build_sensor_merkmale(block): "zuordnung_fix" (csv:block-to-json) hat Vorrang vor dem ZUORDNUNG-Attribut: es steht an den temporaeren Kopien der in VF_n/GF_n/KREISEL_n VERPACKTEN Separator_SP-Symbole und traegt die ID des Wrapper-Blocks, in dem das - Symbol steckt - eine bekannte, keine geratene Zuordnung.""" + Symbol steckt - eine bekannte, keine geratene Zuordnung. + + "strecke_typ" (csv:block-to-json/csv:wrapper-strecke-typ) traegt bei + denselben verpackten Kopien den Streckentyp (VF/GF) des Wrappers, in dem + der Separator steckt - eine Strecke wechselt sich zwingend Foerderer/ + Gefaellestrecke ab. Fehlt bei eigenstaendigen Separator_SP/Scanner- + Bloecken (keinem Wrapper zugeordnet) und bleibt dann leer.""" attribs = block.get("attribs", {}) return { "Zuordnung": block.get("zuordnung_fix") or attribs.get("ZUORDNUNG", ""), "ARTINR": attribs.get("ARTINR", ""), "Höhe": get_hoehe(block), "Drehung": get_drehung(block), + "Typ": block.get("strecke_typ", ""), }