Fix des Redefines im Lisp. Erzeugte lange schleifen. Jeder Block nur einmal laden

This commit is contained in:
2026-07-28 16:11:31 +02:00
parent efec00d4c6
commit 98f1c64c3d
4 changed files with 141 additions and 51 deletions
+18
View File
@@ -89,6 +89,24 @@ Grundfunktionen für Umgebungssicherung, Benutzerinteraktion, Layer, Blöcke, At
| `ssg-insert-block layer farbe pfad pt xs ys rot` | Layer anlegen und Block einfügen |
| `ssg-make-block pt rotation ss` | Auswahlsatz als Block definieren und gleich einfügen |
**ILS-Blockdateien laden (2D/3D):**
| Funktion | Beschreibung |
| --- | --- |
| `ssg-ils-dim-aktuell` | Gültige Dimension: `*ssg-ils-dim*``DXFM_DIM``"3D"` |
| `ssg-ils-blockname[-dim] roh [dim]` | Effektiver Blockname mit Suffix `_2D`/`_3D` |
| `ssg-ils-block-datei[-dim] roh [dim]` | Pfad zu `data/ils/<blockname>.dwg` (3D-Fallback) |
| `ssg-ils-block-laden[-dim] roh [dim]` | Blockdefinition sicherstellen; Rückgabe = effektiver Name |
| `ssg-block-refresh-reset roh` | Redefine-Sperre lösen (`nil` = alle Blöcke) → DWG wird neu gelesen |
Jede Block-DWG wird **einmal pro Zeichnung** aus der Datei neu definiert (Redefine);
danach greift eine Sperre (`*ssg-block-refreshed*`, siehe `ssg-block-refreshed-p`/
`-set`). Ohne sie las jede einzelne Element-Einfügung die DWG erneut von der Platte
und regenerierte alle bereits platzierten Referenzen bei den großen 3D-Blöcken
(`AS_Element_90_links_3D` ~52 MB) waren Tests wie `TEST_MUBEA` dadurch minutenlang
beschäftigt. Wurde eine Block-DWG während der laufenden Sitzung geändert, hebt
`ssg-block-refresh-reset` die Sperre auf.
**Attribut-Operationen:**
| Funktion | Beschreibung |
+78 -41
View File
@@ -370,13 +370,58 @@
(defun ssg-ils-block-datei (blockname / )
(ssg-ils-block-datei-dim blockname (ssg-ils-dim-aktuell)))
;; ------------------------------------------------------------
;; REDEFINE-SPERRE (eine DWG-Lesung pro Block und Zeichnung)
;; ------------------------------------------------------------
;; Merkliste der in DIESER Zeichnung schon einmal aus der DWG-Datei neu
;; definierten (redefinierten) Blocknamen. Grundlage der Sperre in
;; ssg-ils-block-laden-dim. Namen werden in Grossschreibung gehalten, weil
;; Blocknamen in CAD case-insensitiv sind. LISP-Variablen sind pro Dokument
;; eigenstaendig, die Liste gilt also automatisch je Zeichnung.
(if (not (boundp '*ssg-block-refreshed*)) (setq *ssg-block-refreshed* nil))
(defun ssg-block-refreshed-p (eff / )
(and (boundp '*ssg-block-refreshed*)
(member (strcase eff) *ssg-block-refreshed*)
t))
(defun ssg-block-refreshed-set (eff / )
(if (not (ssg-block-refreshed-p eff))
(setq *ssg-block-refreshed* (cons (strcase eff) *ssg-block-refreshed*)))
eff)
;; Sperre aufheben - erzwingt beim naechsten ssg-ils-block-laden(-dim) ein
;; erneutes Einlesen der DWG. Argument nil: ALLE Bloecke; ROH- oder effektiver
;; Blockname: nur dieser (beide Dimensionen). Noetig, wenn eine Block-DWG
;; waehrend der laufenden Sitzung geaendert wurde.
(defun ssg-block-refresh-reset (blockname / rest n2 n3 nroh)
(if (null blockname)
(setq *ssg-block-refreshed* nil)
(progn
(setq nroh (strcase blockname)
n2 (strcase (ssg-ils-blockname-dim blockname "2D"))
n3 (strcase (ssg-ils-blockname-dim blockname "3D"))
rest '())
(foreach n *ssg-block-refreshed*
(if (not (or (= n nroh) (= n n2) (= n n3)))
(setq rest (cons n rest))))
(setq *ssg-block-refreshed* rest)))
(princ))
;; Stellt sicher, dass die Block-DEFINITION zum ROH-Namen 'blockname' in einer
;; EXPLIZITEN Dimension geladen ist. Blocknamen tragen das Suffix _2D/_3D
;; (siehe ssg-ils-blockname-dim), daher koennen 2D und 3D gleichzeitig existieren.
;; WICHTIG: Ein bereits vorhandener gleichnamiger Block wird IMMER neu aus der
;; Datei definiert (Redefine), damit sein Inhalt zur aktuellen Datei passt. Sonst
;; bliebe eine veraltete Definition (z.B. mit falschem 2D/3D-Inhalt aus einer
;; frueheren Sitzung) bestehen und wuerde wiederverwendet.
;; Ein bereits vorhandener gleichnamiger Block wird EINMAL PRO ZEICHNUNG neu aus
;; der Datei definiert (Redefine), damit eine veraltete Definition aus einer
;; frueheren Sitzung (z.B. mit falschem 2D/3D-Inhalt) nicht wiederverwendet wird.
;; Jeder WEITERE Aufruf fuer denselben effektiven Blocknamen ueberspringt das
;; Neu-Definieren (siehe *ssg-block-refreshed*): Ohne diese Sperre las jede
;; einzelne Element-Einfuegung die DWG erneut von der Platte - bei den grossen
;; 3D-Bloecken (AS_Element_90_links_3D ~52 MB, ES_Element_90_links_3D ~9 MB)
;; und zusaetzlich einer Regeneration aller bereits platzierten Referenzen
;; dieses Blocks. Bei Tests mit vielen Strecken (TEST_MUBEA, Gefaellestrecke-
;; und Foerderer-Tests) fuehrte das zu minutenlangen Laufzeiten.
;; Zum erzwungenen Neu-Einlesen: ssg-block-refresh-reset.
;; Rueckgabe: effektiver (suffigierter) Blockname oder nil (Datei nicht gefunden).
(defun ssg-ils-block-laden-dim (blockname dim / eff datei base temp-obj osm areq adia)
(setq eff (ssg-ils-blockname-dim blockname dim))
@@ -385,12 +430,6 @@
nil
(progn
(setq base (vl-filename-base datei))
;; --- TEMP-DIAGNOSE (nach Klaerung wieder entfernen) ---
(princ (strcat "\n[SSG-DBG] roh=" blockname " dim=" dim
" eff=" eff
" existiert-vorher=" (if (tblsearch "BLOCK" eff) "JA" "NEIN")
" datei=" datei))
;; --- ENDE TEMP-DIAGNOSE ---
;; Sichtbar machen, wenn die Datei der gewuenschten Dimension fehlt und der
;; 3D-Fallback greift (dann traegt der Block den gewuenschten Namen, aber
;; den Inhalt der anderen Dimension = potenziell falsche Referenz). Jeder
@@ -399,38 +438,36 @@
(princ (strcat "\n[SSG] WARNUNG: Blockdatei '" eff
".dwg' fehlt - Fallback auf '" base
".dwg' (Inhalt evtl. andere Dimension).")))
(if (and (not (tblsearch "BLOCK" eff)) (= (strcase base) (strcase eff)))
;; Neu UND Dateiname == Blockname -> COM-Weg (kein Prompt).
;; In dieser Zeichnung bereits aus der Datei aktualisiert UND noch in der
;; Blocktabelle vorhanden -> nichts zu tun, die Definition ist aktuell.
;; Die tblsearch-Pruefung faengt ab, dass der Block zwischenzeitlich
;; entfernt wurde (z.B. per PURGE) und neu geladen werden muss.
(if (and (ssg-block-refreshed-p eff) (tblsearch "BLOCK" eff))
eff
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0)) datei 1.0 1.0 1.0 0))
(vla-Delete temp-obj))
;; Sonst (Block existiert bereits ODER Dateiname != Blockname wg.
;; 3D-Fallback) -> aus Datei (neu) definieren. "_Y" beantwortet die
;; Redefine-Abfrage, falls der Block bereits vorhanden ist; danach die
;; laufende Einfuegung sofort abbrechen (Definition ist bereits wirksam).
(progn
(setq areq (getvar "ATTREQ") adia (getvar "ATTDIA") osm (getvar "OSMODE"))
(setvar "ATTREQ" 0)(setvar "ATTDIA" 0)(setvar "OSMODE" 0)
(if (tblsearch "BLOCK" eff)
(command "_.-INSERT" (strcat eff "=" datei) "_Y") ; Redefine bestehender Block
(command "_.-INSERT" (strcat eff "=" datei))) ; neu (kein Redefine-Prompt)
(if (> (getvar "CMDACTIVE") 0) (command))
(if (> (getvar "CMDACTIVE") 0) (command))
(setvar "OSMODE" osm)(setvar "ATTREQ" areq)(setvar "ATTDIA" adia)))
;; --- TEMP-DIAGNOSE: verschachtelte Blocknamen in eff auflisten ---
(if (tblsearch "BLOCK" eff)
(progn
(princ (strcat "\n[SSG-DBG] nested in " eff ":"))
(vl-catch-all-apply
(function (lambda ()
(vlax-for e (vla-Item
(vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object)))
eff)
(if (= (vla-get-ObjectName e) "AcDbBlockReference")
(princ (strcat " [" (vla-get-Name e) "]")))))))))
;; --- ENDE TEMP-DIAGNOSE ---
eff)))
(if (and (not (tblsearch "BLOCK" eff)) (= (strcase base) (strcase eff)))
;; Neu UND Dateiname == Blockname -> COM-Weg (kein Prompt).
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0)) datei 1.0 1.0 1.0 0))
(vla-Delete temp-obj))
;; Sonst (Block existiert bereits ODER Dateiname != Blockname wg.
;; 3D-Fallback) -> aus Datei (neu) definieren. "_Y" beantwortet die
;; Redefine-Abfrage, falls der Block bereits vorhanden ist; danach die
;; laufende Einfuegung sofort abbrechen (Definition ist bereits wirksam).
(progn
(setq areq (getvar "ATTREQ") adia (getvar "ATTDIA") osm (getvar "OSMODE"))
(setvar "ATTREQ" 0)(setvar "ATTDIA" 0)(setvar "OSMODE" 0)
(if (tblsearch "BLOCK" eff)
(command "_.-INSERT" (strcat eff "=" datei) "_Y") ; Redefine bestehender Block
(command "_.-INSERT" (strcat eff "=" datei))) ; neu (kein Redefine-Prompt)
(if (> (getvar "CMDACTIVE") 0) (command))
(if (> (getvar "CMDACTIVE") 0) (command))
(setvar "OSMODE" osm)(setvar "ATTREQ" areq)(setvar "ATTDIA" adia)))
;; Nur merken, wenn die Definition danach wirklich vorhanden ist -
;; sonst wuerde ein fehlgeschlagener Ladeversuch dauerhaft gesperrt.
(if (tblsearch "BLOCK" eff) (ssg-block-refreshed-set eff))
eff)))))
;; Wie ssg-ils-block-laden-dim, aber fuer die AKTUELLE Dimension.
(defun ssg-ils-block-laden (blockname / )