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-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 | | `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:** **Attribut-Operationen:**
| Funktion | Beschreibung | | Funktion | Beschreibung |
+78 -41
View File
@@ -370,13 +370,58 @@
(defun ssg-ils-block-datei (blockname / ) (defun ssg-ils-block-datei (blockname / )
(ssg-ils-block-datei-dim blockname (ssg-ils-dim-aktuell))) (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 ;; Stellt sicher, dass die Block-DEFINITION zum ROH-Namen 'blockname' in einer
;; EXPLIZITEN Dimension geladen ist. Blocknamen tragen das Suffix _2D/_3D ;; EXPLIZITEN Dimension geladen ist. Blocknamen tragen das Suffix _2D/_3D
;; (siehe ssg-ils-blockname-dim), daher koennen 2D und 3D gleichzeitig existieren. ;; (siehe ssg-ils-blockname-dim), daher koennen 2D und 3D gleichzeitig existieren.
;; WICHTIG: Ein bereits vorhandener gleichnamiger Block wird IMMER neu aus der ;; Ein bereits vorhandener gleichnamiger Block wird EINMAL PRO ZEICHNUNG neu aus
;; Datei definiert (Redefine), damit sein Inhalt zur aktuellen Datei passt. Sonst ;; der Datei definiert (Redefine), damit eine veraltete Definition aus einer
;; bliebe eine veraltete Definition (z.B. mit falschem 2D/3D-Inhalt aus einer ;; frueheren Sitzung (z.B. mit falschem 2D/3D-Inhalt) nicht wiederverwendet wird.
;; frueheren Sitzung) bestehen und wuerde wiederverwendet. ;; 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). ;; 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) (defun ssg-ils-block-laden-dim (blockname dim / eff datei base temp-obj osm areq adia)
(setq eff (ssg-ils-blockname-dim blockname dim)) (setq eff (ssg-ils-blockname-dim blockname dim))
@@ -385,12 +430,6 @@
nil nil
(progn (progn
(setq base (vl-filename-base datei)) (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 ;; Sichtbar machen, wenn die Datei der gewuenschten Dimension fehlt und der
;; 3D-Fallback greift (dann traegt der Block den gewuenschten Namen, aber ;; 3D-Fallback greift (dann traegt der Block den gewuenschten Namen, aber
;; den Inhalt der anderen Dimension = potenziell falsche Referenz). Jeder ;; den Inhalt der anderen Dimension = potenziell falsche Referenz). Jeder
@@ -399,38 +438,36 @@
(princ (strcat "\n[SSG] WARNUNG: Blockdatei '" eff (princ (strcat "\n[SSG] WARNUNG: Blockdatei '" eff
".dwg' fehlt - Fallback auf '" base ".dwg' fehlt - Fallback auf '" base
".dwg' (Inhalt evtl. andere Dimension)."))) ".dwg' (Inhalt evtl. andere Dimension).")))
(if (and (not (tblsearch "BLOCK" eff)) (= (strcase base) (strcase eff))) ;; In dieser Zeichnung bereits aus der Datei aktualisiert UND noch in der
;; Neu UND Dateiname == Blockname -> COM-Weg (kein Prompt). ;; 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 (progn
(setq temp-obj (vla-InsertBlock modelspace (if (and (not (tblsearch "BLOCK" eff)) (= (strcase base) (strcase eff)))
(vlax-3D-point '(0 0 0)) datei 1.0 1.0 1.0 0)) ;; Neu UND Dateiname == Blockname -> COM-Weg (kein Prompt).
(vla-Delete temp-obj)) (progn
;; Sonst (Block existiert bereits ODER Dateiname != Blockname wg. (setq temp-obj (vla-InsertBlock modelspace
;; 3D-Fallback) -> aus Datei (neu) definieren. "_Y" beantwortet die (vlax-3D-point '(0 0 0)) datei 1.0 1.0 1.0 0))
;; Redefine-Abfrage, falls der Block bereits vorhanden ist; danach die (vla-Delete temp-obj))
;; laufende Einfuegung sofort abbrechen (Definition ist bereits wirksam). ;; Sonst (Block existiert bereits ODER Dateiname != Blockname wg.
(progn ;; 3D-Fallback) -> aus Datei (neu) definieren. "_Y" beantwortet die
(setq areq (getvar "ATTREQ") adia (getvar "ATTDIA") osm (getvar "OSMODE")) ;; Redefine-Abfrage, falls der Block bereits vorhanden ist; danach die
(setvar "ATTREQ" 0)(setvar "ATTDIA" 0)(setvar "OSMODE" 0) ;; laufende Einfuegung sofort abbrechen (Definition ist bereits wirksam).
(if (tblsearch "BLOCK" eff) (progn
(command "_.-INSERT" (strcat eff "=" datei) "_Y") ; Redefine bestehender Block (setq areq (getvar "ATTREQ") adia (getvar "ATTDIA") osm (getvar "OSMODE"))
(command "_.-INSERT" (strcat eff "=" datei))) ; neu (kein Redefine-Prompt) (setvar "ATTREQ" 0)(setvar "ATTDIA" 0)(setvar "OSMODE" 0)
(if (> (getvar "CMDACTIVE") 0) (command)) (if (tblsearch "BLOCK" eff)
(if (> (getvar "CMDACTIVE") 0) (command)) (command "_.-INSERT" (strcat eff "=" datei) "_Y") ; Redefine bestehender Block
(setvar "OSMODE" osm)(setvar "ATTREQ" areq)(setvar "ATTDIA" adia))) (command "_.-INSERT" (strcat eff "=" datei))) ; neu (kein Redefine-Prompt)
;; --- TEMP-DIAGNOSE: verschachtelte Blocknamen in eff auflisten --- (if (> (getvar "CMDACTIVE") 0) (command))
(if (tblsearch "BLOCK" eff) (if (> (getvar "CMDACTIVE") 0) (command))
(progn (setvar "OSMODE" osm)(setvar "ATTREQ" areq)(setvar "ATTDIA" adia)))
(princ (strcat "\n[SSG-DBG] nested in " eff ":")) ;; Nur merken, wenn die Definition danach wirklich vorhanden ist -
(vl-catch-all-apply ;; sonst wuerde ein fehlgeschlagener Ladeversuch dauerhaft gesperrt.
(function (lambda () (if (tblsearch "BLOCK" eff) (ssg-block-refreshed-set eff))
(vlax-for e (vla-Item eff)))))
(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)))
;; Wie ssg-ils-block-laden-dim, aber fuer die AKTUELLE Dimension. ;; Wie ssg-ils-block-laden-dim, aber fuer die AKTUELLE Dimension.
(defun ssg-ils-block-laden (blockname / ) (defun ssg-ils-block-laden (blockname / )
+24 -4
View File
@@ -113,7 +113,7 @@
;; L_GF2 (Nachlauf) ist der Rest (L_GF_gesamt - L_GF1). ;; L_GF2 (Nachlauf) ist der Rest (L_GF_gesamt - L_GF1).
(defun mubea:build-vario-one (tid richtung deltaL deltaH winkel-soll gf1-ziel seite hz (defun mubea:build-vario-one (tid richtung deltaL deltaH winkel-soll gf1-ziel seite hz
startpunkt / ergebnis winkel-treffer best-winkel L_GF L_VF startpunkt / ergebnis winkel-treffer best-winkel L_GF L_VF
gf1 gf2 hoehe-bis lastEnt ent) gf1 gf2 hoehe-bis lastEnt ent vf-nummer)
(if (or (null seite) (= seite "")) (setq seite "links")) (if (or (null seite) (= seite "")) (setq seite "links"))
(if (null hz) (setq hz 0.0) (setq hz (float hz))) (if (null hz) (setq hz 0.0) (setq hz (float hz)))
(princ (strcat "\n [VARIO] " tid " -> deltaL=" (rtos deltaL 2 0) (princ (strcat "\n [VARIO] " tid " -> deltaL=" (rtos deltaL 2 0)
@@ -147,7 +147,14 @@
(setq hoehe-bis (if (= richtung "Auf") deltaH (- deltaH))) (setq hoehe-bis (if (= richtung "Auf") deltaH (- deltaH)))
(setq lastEnt (vf-lastent-ohne-attribute)) (setq lastEnt (vf-lastent-ohne-attribute))
(variofoerderer-einfuegen deltaL deltaH richtung best-winkel gf1 gf2 L_VF startpunkt seite hz) (variofoerderer-einfuegen deltaL deltaH richtung best-winkel gf1 gf2 L_VF startpunkt seite hz)
(setq ent (vf-block-erstellen "standard" seite 1 0 0 hoehe-bis ;; Blocknummer wie in der Produktion ueber vf-next-number holen (NICHT fest
;; auf 1): vf-next-number ueberspringt bereits belegte VF_n-Nummern. Mit
;; einer festen 1 traf das _.-BLOCK des ZWEITEN Foerderers auf den schon
;; vorhandenen Namen "VF_1" -> BricsCAD fragt "Neu definieren?", verschluckt
;; damit Basispunkt/Auswahlsatz der festen Antwortfolge, meldet "Eintrag
;; kann nicht erkannt werden" und der Befehl bleibt offen (Haenger).
(setq vf-nummer (vf-next-number))
(setq ent (vf-block-erstellen "standard" seite vf-nummer 0 0 hoehe-bis
deltaH deltaL L_VF gf1 gf2 richtung best-winkel deltaH deltaL L_VF gf1 gf2 richtung best-winkel
startpunkt lastEnt hz "0" "Schoenenberger Geruest")) startpunkt lastEnt hz "0" "Schoenenberger Geruest"))
(if (or (null ent) (/= (type ent) 'ENAME)) (if (or (null ent) (/= (type ent) 'ENAME))
@@ -327,7 +334,7 @@
;; > 0) - dieselbe Absicherung wie in ssg-ils-block-laden-dim (Zeilen 418f.) und ;; > 0) - dieselbe Absicherung wie in ssg-ils-block-laden-dim (Zeilen 418f.) und
;; omni:insert-dxf (Zeile 980): nach dem INSERT verbleibende Prompts mit Leer- ;; omni:insert-dxf (Zeile 980): nach dem INSERT verbleibende Prompts mit Leer-
;; Antworten (Enter) abfangen, bis der Befehl sauber beendet ist. ;; Antworten (Enter) abfangen, bis der Befehl sauber beendet ist.
(defun mubea:build-separator-one (tid blockname pt rot / eff) (defun mubea:build-separator-one (tid blockname pt rot / eff n)
(princ (strcat "\n [SEP] " tid " '" (if blockname blockname "?") (princ (strcat "\n [SEP] " tid " '" (if blockname blockname "?")
"' -> (" (rtos (car pt) 2 0) "," (rtos (cadr pt) 2 0) "," (rtos (caddr pt) 2 0) "' -> (" (rtos (car pt) 2 0) "," (rtos (cadr pt) 2 0) "," (rtos (caddr pt) 2 0)
") R=" (rtos rot 2 0))) ") R=" (rtos rot 2 0)))
@@ -342,7 +349,20 @@
(if eff (if eff
(progn (progn
(command "_.INSERT" eff pt "" "" rot) (command "_.INSERT" eff pt "" "" rot)
(while (> (getvar "CMDACTIVE") 0) (command "")) ;; Verbleibende Prompts mit Enter abfangen - aber GEZAEHLT. Ein Prompt, der
;; eine Leer-Antwort ablehnt ("Eintrag kann nicht erkannt werden. Bitte
;; versuchen Sie es erneut."), haelt CMDACTIVE dauerhaft > 0: eine
;; ungebremste (while (> CMDACTIVE 0) (command "")) Schleife laeuft dort
;; endlos und BricsCAD haengt. Danach hart abbrechen und melden.
(setq n 0)
(while (and (> (getvar "CMDACTIVE") 0) (< n 5))
(command "")
(setq n (1+ n)))
(if (> (getvar "CMDACTIVE") 0)
(progn
(command)
(princ (strcat "\n WARNUNG: INSERT von '" eff
"' nicht sauber beendet - abgebrochen."))))
(mubea:ent-json tid "separator" (entlast))) (mubea:ent-json tid "separator" (entlast)))
(progn (progn
;; Kein Block gefunden -> sichtbaren Platzhalter zeichnen ;; Kein Block gefunden -> sichtbaren Platzhalter zeichnen
+21 -6
View File
@@ -42,7 +42,7 @@
"function": "insert", "function": "insert",
"block": "S-LP", "block": "S-LP",
"x": 400, "x": 400,
"y": -4700, "y": -3815,
"z": 1467, "z": 1467,
"rotation": 90, "rotation": 90,
"assigned_to": "Kreisel_links" "assigned_to": "Kreisel_links"
@@ -52,7 +52,7 @@
"function": "insert", "function": "insert",
"block": "Scanner", "block": "Scanner",
"x": 400, "x": 400,
"y": -4823, "y": -3925,
"z": 1467, "z": 1467,
"rotation": 0, "rotation": 0,
"assigned_to": "Kreisel_links" "assigned_to": "Kreisel_links"
@@ -94,7 +94,22 @@
"x": 400, "x": 400,
"y": 14120, "y": 14120,
"z": 1467, "z": 1467,
"comment": "deltaL=9110 wie die Gefaellestrecken (GF_Mubea deltaL_mm) - deltaL ist die GESAMTLAENGE des VF (Vorlauf L_GF1 + Foerderer L_VF + Nachlauf L_GF2), analog foerderer_tests.json/object_data.md 3.1; winkel=21 wird erzwungen (naechster verfuegbarer Bogenwinkel); L_GF (gesamt) und L_VF werden von berechne-alle-winkel aus deltaL/deltaH/winkel geloest, L_GF1=500 (Vorlauf-Ziel) fix, L_GF2 = L_GF_gesamt - L_GF1 (Nachlauf, Rest)" "comment": "oberer Förderer für die Leertrolleys"
},
{
"test_id": "VF_Schnitt_E",
"richtung": "Auf",
"deltaL": 9110,
"deltaH": 474,
"winkel": 21,
"gf_verteilung": "manuell",
"L_GF1": 2298,
"seite": "links",
"hz": 0.0,
"x": 400,
"y": -4133,
"z": 1467,
"comment": "unterer Förderer für die Teile"
}, },
{ {
"comment": "Separator Förderer oben", "comment": "Separator Förderer oben",
@@ -170,7 +185,7 @@
"block": "S-LP", "block": "S-LP",
"x": 10310, "x": 10310,
"y": -500, "y": -500,
"z": 1467, "z": 1941,
"rotation": 90, "rotation": 90,
"assigned_to": "Kreisel_rechts" "assigned_to": "Kreisel_rechts"
}, },
@@ -180,7 +195,7 @@
"block": "S-LP", "block": "S-LP",
"x": 10310, "x": 10310,
"y": 100, "y": 100,
"z": 1467, "z": 1941,
"rotation": 90, "rotation": 90,
"assigned_to": "Kreisel_rechts" "assigned_to": "Kreisel_rechts"
}, },
@@ -190,7 +205,7 @@
"block": "S-LP", "block": "S-LP",
"x": 9510, "x": 9510,
"y": -4823, "y": -4823,
"z": 1467, "z": 1941,
"rotation": 270, "rotation": 270,
"assigned_to": "GF_Mubea_20" "assigned_to": "GF_Mubea_20"
} }