Sepliste-XDATA fuer Separator/AS/ES-Reihenfolge + Unit-Tests, makunbound-Fix
Sammelt beim Bau von VF_n/GF_n-Ketten die Baureihenfolge der Separator-/ AS-/ES-Sub-Bloecke vor dem Block-Sweep und schreibt sie als XDATA auf den fertigen Wrapper (ssg_ks_insert.lsp); export.lsp liest sie fuer das neue "sepliste"-Feld im CSV-Export, export_neighbors.py nutzt es als Fallback zur BBox-Kollisionspruefung. Dazu Unit-Tests fuer die reinen Serialisierungs- funktionen (Chunking, Roundtrip) in test_unit.lsp. Ausserdem: makunbound (existiert nicht in BricsCAD-AutoLISP) aus test_run_all.lsp entfernt - verursachte Laufzeitfehler bei SSG_RUN_ALL_TESTS_EXPORT/_OFFEN. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -354,4 +354,148 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; SEPLISTE: Separator-/AS-/ES-Reihenfolge als XDATA am fertigen Wrapper
|
||||
;; ------------------------------------------------------------
|
||||
;; Sammelt beim Bau einer VF_n/GF_n-Kette die Weltposition + Baureihenfolge
|
||||
;; aller "Staustrecke_Separator_SP_300_mm"/"AS_Element_*"/"ES_Element_*"-
|
||||
;; Sub-Bloecke, BEVOR der abschliessende _.-BLOCK-Sweep (ssg-block-wrap-welt)
|
||||
;; sie in die Wrapper-Blockdefinition einsaugt und ihre Modellraum-Existenz
|
||||
;; damit beendet. Genutzt von vf-block-erstellen (vf_core.lsp),
|
||||
;; vfl-block-erstellen (vf_linienzug.lsp) und gf-block-erstellen
|
||||
;; (Gefaellestrecke.lsp) - an allen drei Stellen identisch aufgerufen, daher
|
||||
;; hier zentral (vgl. Projektregel "Wiederverwendung vor Neuschaffung").
|
||||
;;
|
||||
;; Traegt bewusst KEINE ssg-id-generate-ID (kein ID-ATTDEF an diesen
|
||||
;; Bloecken, Sinn/Zweck rein interne Geometrie-Traeger) - jeder Eintrag
|
||||
;; bekommt nur eine laufende Nummer innerhalb der Liste. Der Export bildet
|
||||
;; daraus bei Bedarf eigene, global fortlaufende TeileIds.
|
||||
|
||||
;; Einfaches Chunking eines Strings in Stuecke <= n Zeichen (DXF-Limit einer
|
||||
;; 1000-Gruppe ist 255 Byte) - eigenstaendige Kopie statt vfl-chunk-string
|
||||
;; (vf_linienzug.lsp), da diese Datei laut Lademechanismus VOR vf_linienzug
|
||||
;; geladen wird und dessen Funktionen hier noch nicht existieren.
|
||||
(defun ssg-sepliste-chunk-string (s n / out len)
|
||||
(setq out '())
|
||||
(while (> (setq len (strlen s)) n)
|
||||
(setq out (cons (substr s 1 n) out))
|
||||
(setq s (substr s (1+ n))))
|
||||
(if (> (strlen s) 0) (setq out (cons s out)))
|
||||
(reverse out))
|
||||
|
||||
;; Sammelt alle seit lastEnt neu erzeugten Separator-/AS-/ES-Entities in
|
||||
;; Baureihenfolge (identische entnext-Wanderung wie die Auswahlsatz-Sammlung
|
||||
;; der Aufrufer, nur mit wcmatch-Filter). Rueckgabe: Liste von
|
||||
;; (typ lfdnr x y), typ = "SEP"/"AS"/"ES", lfdnr 1-basiert in Baureihenfolge.
|
||||
(defun ssg-sepliste-sammeln (lastEnt / ent bname typ lfdnr pt liste)
|
||||
(setq liste '() lfdnr 0)
|
||||
(setq ent (if lastEnt (entnext lastEnt) (entnext)))
|
||||
(while ent
|
||||
(if (= (cdr (assoc 0 (entget ent))) "INSERT")
|
||||
(progn
|
||||
(setq bname (cdr (assoc 2 (entget ent))))
|
||||
(setq typ (cond
|
||||
((wcmatch bname "Staustrecke_Separator_SP_300_mm*") "SEP")
|
||||
((wcmatch bname "AS_Element_*") "AS")
|
||||
((wcmatch bname "ES_Element_*") "ES")
|
||||
(t nil)))
|
||||
(if typ
|
||||
(progn
|
||||
(setq lfdnr (1+ lfdnr))
|
||||
(setq pt (cdr (assoc 10 (entget ent))))
|
||||
(setq liste (cons (list typ lfdnr (car pt) (cadr pt)) liste))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(setq ent (entnext ent))
|
||||
)
|
||||
(reverse liste)
|
||||
)
|
||||
|
||||
;; Serialisiert die Sepliste zu "TYP:LFDNR:X:Y,TYP:LFDNR:X:Y,...".
|
||||
(defun ssg-sepliste->string (liste / eintrag out first)
|
||||
(setq out "" first t)
|
||||
(foreach eintrag liste
|
||||
(setq eintrag
|
||||
(strcat (nth 0 eintrag) ":" (itoa (nth 1 eintrag)) ":"
|
||||
(rtos (nth 2 eintrag) 2 2) ":" (rtos (nth 3 eintrag) 2 2)))
|
||||
(if first (progn (setq out eintrag) (setq first nil))
|
||||
(setq out (strcat out "," eintrag)))
|
||||
)
|
||||
out
|
||||
)
|
||||
|
||||
;; Gegenstueck zu ssg-sepliste->string - Rueckgabe Liste von (typ lfdnr x y).
|
||||
(defun ssg-sepliste-string->liste (s / out teile eintraege feld)
|
||||
(setq out '())
|
||||
(if (> (strlen s) 0)
|
||||
(progn
|
||||
(setq eintraege '() teile "")
|
||||
(foreach c (ssg-sepliste-explode-chars s)
|
||||
(if (= c ",")
|
||||
(progn (setq eintraege (cons teile eintraege)) (setq teile ""))
|
||||
(setq teile (strcat teile c))
|
||||
)
|
||||
)
|
||||
(setq eintraege (reverse (cons teile eintraege)))
|
||||
(foreach eintrag eintraege
|
||||
(setq feld (ssg-sepliste-split-feld eintrag ":"))
|
||||
(if (= (length feld) 4)
|
||||
(setq out (cons (list (nth 0 feld) (atoi (nth 1 feld))
|
||||
(atof (nth 2 feld)) (atof (nth 3 feld))) out))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(reverse out)
|
||||
)
|
||||
(defun ssg-sepliste-explode-chars (s / i n out)
|
||||
(setq out '() i 1 n (strlen s))
|
||||
(while (<= i n) (setq out (cons (substr s i 1) out)) (setq i (1+ i)))
|
||||
(reverse out)
|
||||
)
|
||||
(defun ssg-sepliste-split-feld (s sep / pos out)
|
||||
(setq out '())
|
||||
(while (setq pos (vl-string-search sep s))
|
||||
(setq out (cons (substr s 1 pos) out))
|
||||
(setq s (substr s (+ pos 1 (strlen sep)))))
|
||||
(reverse (cons s out))
|
||||
)
|
||||
|
||||
;; Schreibt die Sepliste als XDATA (App app-name, z.B. "SSG_VF_SEP"/
|
||||
;; "SSG_GF_SEP") auf den fertigen Wrapper-Block ent. Layout der 1000-Gruppen:
|
||||
;; [0]="sepliste" (Marker), [1..]=serialisierte Liste in 250-Byte-Chunks
|
||||
;; (DXF-Limit 255 Byte je 1000-Gruppe) - identisches Muster wie
|
||||
;; vfl-journal-xdata-schreiben (vf_linienzug.lsp).
|
||||
(defun ssg-sepliste-xdata-schreiben (ent app-name liste / chunks appentry)
|
||||
(if (and ent liste)
|
||||
(progn
|
||||
(regapp app-name)
|
||||
(setq chunks (ssg-sepliste-chunk-string (ssg-sepliste->string liste) 250))
|
||||
(setq appentry
|
||||
(cons app-name
|
||||
(cons (cons 1000 "sepliste")
|
||||
(mapcar (function (lambda (c) (cons 1000 c))) chunks))))
|
||||
(entmod (append (entget ent) (list (list -3 appentry))))
|
||||
)
|
||||
)
|
||||
ent
|
||||
)
|
||||
|
||||
;; 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)
|
||||
(setq xd (entget ent (list app-name)))
|
||||
(setq app-data (cdr (assoc -3 xd)))
|
||||
(if app-data
|
||||
(progn
|
||||
(setq werte (mapcar 'cdr (cdr (car app-data))))
|
||||
(if (and werte (= (car werte) "sepliste"))
|
||||
(ssg-sepliste-string->liste (apply 'strcat (cdr werte)))
|
||||
nil))
|
||||
nil
|
||||
)
|
||||
)
|
||||
|
||||
(princ)
|
||||
|
||||
Reference in New Issue
Block a user