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 / )
+24 -4
View File
@@ -113,7 +113,7 @@
;; 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
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 (null hz) (setq hz 0.0) (setq hz (float hz)))
(princ (strcat "\n [VARIO] " tid " -> deltaL=" (rtos deltaL 2 0)
@@ -147,7 +147,14 @@
(setq hoehe-bis (if (= richtung "Auf") deltaH (- deltaH)))
(setq lastEnt (vf-lastent-ohne-attribute))
(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
startpunkt lastEnt hz "0" "Schoenenberger Geruest"))
(if (or (null ent) (/= (type ent) 'ENAME))
@@ -327,7 +334,7 @@
;; > 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-
;; 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 "?")
"' -> (" (rtos (car pt) 2 0) "," (rtos (cadr pt) 2 0) "," (rtos (caddr pt) 2 0)
") R=" (rtos rot 2 0)))
@@ -342,7 +349,20 @@
(if eff
(progn
(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)))
(progn
;; Kein Block gefunden -> sichtbaren Platzhalter zeichnen
+21 -6
View File
@@ -42,7 +42,7 @@
"function": "insert",
"block": "S-LP",
"x": 400,
"y": -4700,
"y": -3815,
"z": 1467,
"rotation": 90,
"assigned_to": "Kreisel_links"
@@ -52,7 +52,7 @@
"function": "insert",
"block": "Scanner",
"x": 400,
"y": -4823,
"y": -3925,
"z": 1467,
"rotation": 0,
"assigned_to": "Kreisel_links"
@@ -94,7 +94,22 @@
"x": 400,
"y": 14120,
"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",
@@ -170,7 +185,7 @@
"block": "S-LP",
"x": 10310,
"y": -500,
"z": 1467,
"z": 1941,
"rotation": 90,
"assigned_to": "Kreisel_rechts"
},
@@ -180,7 +195,7 @@
"block": "S-LP",
"x": 10310,
"y": 100,
"z": 1467,
"z": 1941,
"rotation": 90,
"assigned_to": "Kreisel_rechts"
},
@@ -190,7 +205,7 @@
"block": "S-LP",
"x": 9510,
"y": -4823,
"z": 1467,
"z": 1941,
"rotation": 270,
"assigned_to": "GF_Mubea_20"
}