[FIX] Eindeutige IDs und korrekte ZUORDNUNG der verpackten Separatoren
Beim CSV-Export von Mubea trugen Gefaellestrecke/VF/Kreisel und die aus ihnen erzeugten Separator-Kopien dieselbe ID (26 Dubletten 0001-0026), und die ZUORDNUNG der Separatoren zeigte auf den falschen Carrier. ssg-id-check-all: neue Phase 0 ermittelt das globale Maximum der bereits vergebenen IDs, BEVOR die erste neue ID vergeben wird (ausgelagert nach ssg-id-max-in-ss, das auch ssg-id-max nutzt). Bisher wurde max-id erst waehrend Phase 1 mitgezogen (Start 0); da (ssget "X" ...) in BricsCAD die zuletzt erzeugten Entities zuerst liefert, standen die noch ID-losen Separator-Kopien ganz vorne und bekamen 0001, 0002, ... - genau die IDs der weiter hinten liegenden Wrapper-Bloecke. Phase 2 konnte das nicht heilen, weil frisch vergebene IDs nicht in id-map landen. ssg-collect-nested-inserts: fuehrt Position, Z-Drehung und Skalierung jetzt ueber alle Verschachtelungsebenen mit (Records statt nackter Entity-Namen). Vorher gab die Rekursion Entities tieferer Ebenen mit ihrer ROH-Position aus der Zwischen-Blockdefinition zurueck - zwei Separatoren an derselben lokalen Stelle in zwei verschieden platzierten Zwischenbloecken landeten dadurch auf exakt derselben Weltposition. csv:sep-proxies-erzeugen: die Kopie steht jetzt exakt auf Position/Drehung/ Skalierung ihres verpackten Vorbilds; der kosmetische Versatz von 500 mm ist weg (er kippte Separatoren am Kettenende in die Boundingbox des Nachbar- Carriers). Der vla-InsertBlock-Aufruf ist gekapselt, damit ein Sonderfall nur diese eine Kopie ausfallen laesst statt den ganzen Export abzubrechen. csv:sep-proxies-zuordnung-setzen (neu, laeuft NACH ssg-id-check-all, da ein frisch gebauter Wrapper vorher keine ID hat): fuer einen VERPACKTEN Separator ist der Carrier bekannt - es ist der Wrapper, in dem er steckt. ZUORDNUNG wird daher auf die Wrapper-ID gesetzt (Separator in VF 0010 -> ZUORDNUNG 0010) und ueber *cs-sep-fix-by-handle* festgenagelt: cs-zuordnung-lauf uebernimmt sie unveraendert statt sie geometrisch neu zu raten, und csv:block-to-json reicht sie als "zuordnung_fix" an export_csv.py durch. Ohne das ueberschrieb compute_sensor_zuordnung (Prioritaet GF > Foerderer > Kreiselhaelfte) den bekannten Wert - in der Mubea-Zeichnung landeten 26 in VF/GF verpackte Separatoren so bei einer Kreiselhaelfte. export_csv.py: respektiert "zuordnung_fix" und ersetzt eine vorhandene ZUORDNUNG nicht mehr durch "nicht zugeordnet" - nur ein echter Treffer ueberschreibt, wie im Docstring von compute_sensor_zuordnung beschrieben. tests/test_export_ids.py (neu): prueft je tests/output/*_export.csv, dass jede TeileId hoechstens einmal vorkommt und jede Sensor-Zuordnung auf eine existierende TeileId zeigt. Gegen die fehlerhafte Mubea-CSV schlaegt der Test mit allen 26 Dubletten an. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+40
-8
@@ -62,13 +62,17 @@
|
||||
)
|
||||
|
||||
|
||||
;; --- Hoechste ID in der Zeichnung ermitteln ---
|
||||
;; Durchsucht alle exportierbaren Bloecke nach dem Attribut "ID".
|
||||
;; --- Hoechste bereits vergebene ID in einem Auswahlsatz ermitteln ---
|
||||
;; ss = Auswahlsatz (i.d.R. aus ssg-id-collect-blocks) oder nil.
|
||||
;; Rueckgabe: Integer (hoechste ID) oder 0 wenn keine gefunden.
|
||||
(defun ssg-id-max ( / ss i ename attribs id-val id-num max-id)
|
||||
(dbgf "ssg-id-max")
|
||||
;;
|
||||
;; Bewusst als eigene Funktion: ssg-id-check-all MUSS diesen Wert ueber den
|
||||
;; GESAMTEN Auswahlsatz kennen, BEVOR es die erste neue ID vergibt (siehe
|
||||
;; Phase 0 dort) - sonst haengt die Neuvergabe von der (beliebigen)
|
||||
;; ssget-Reihenfolge ab und vergibt IDs, die weiter hinten im Auswahlsatz
|
||||
;; schon belegt sind.
|
||||
(defun ssg-id-max-in-ss (ss / i ename attribs id-val id-num max-id)
|
||||
(setq max-id 0)
|
||||
(setq ss (ssg-id-collect-blocks))
|
||||
(if ss
|
||||
(progn
|
||||
(setq i 0)
|
||||
@@ -87,6 +91,16 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
max-id
|
||||
)
|
||||
|
||||
|
||||
;; --- Hoechste ID in der Zeichnung ermitteln ---
|
||||
;; Durchsucht alle exportierbaren Bloecke nach dem Attribut "ID".
|
||||
;; Rueckgabe: Integer (hoechste ID) oder 0 wenn keine gefunden.
|
||||
(defun ssg-id-max ( / max-id)
|
||||
(dbgf "ssg-id-max")
|
||||
(setq max-id (ssg-id-max-in-ss (ssg-id-collect-blocks)))
|
||||
(dbgreturn max-id)
|
||||
)
|
||||
|
||||
@@ -156,10 +170,26 @@
|
||||
0
|
||||
)
|
||||
(progn
|
||||
;; Phase 1: Alle IDs sammeln und hoechste ID ermitteln
|
||||
;; Phase 0: Hoechste BEREITS vergebene ID ueber den GESAMTEN Auswahlsatz
|
||||
;; ermitteln - zwingend VOR der ersten Neuvergabe in Phase 1.
|
||||
;;
|
||||
;; Frueher wurde max-id erst waehrend Phase 1 mitgefuehrt (Start 0) und
|
||||
;; eine fehlende ID sofort mit max-id+1 belegt. Die Reihenfolge von
|
||||
;; (ssget "X" ...) ist aber beliebig - in BricsCAD kommen die zuletzt
|
||||
;; erzeugten Entities zuerst. Genau das trifft die temporaeren
|
||||
;; Separator-Kopien aus csv:sep-proxies-erzeugen (export.lsp): sie haben
|
||||
;; noch keine ID, stehen ganz vorne und bekamen daher 0001, 0002, ... -
|
||||
;; also exakt die IDs, die die weiter hinten liegenden Kreisel/VF_n/GF_n
|
||||
;; laengst tragen. Phase 2 konnte das nicht heilen, weil die frisch
|
||||
;; vergebenen IDs nicht in id-map landen (und auch nicht muessen: sie
|
||||
;; liegen jetzt garantiert oberhalb jeder vorhandenen ID).
|
||||
(dbgp "=== Phase 0: hoechste vorhandene ID ermitteln ===")
|
||||
(setq max-id (ssg-id-max-in-ss ss))
|
||||
(dbgp (strcat "Phase 0: hoechste vorhandene ID = " (itoa max-id)))
|
||||
|
||||
;; Phase 1: Alle IDs sammeln, Bloecke ohne ID neu nummerieren
|
||||
(dbgp "=== Phase 1: IDs sammeln ===")
|
||||
(setq id-map nil)
|
||||
(setq max-id 0)
|
||||
(setq i 0)
|
||||
(while (setq ename (ssname ss i))
|
||||
(setq attribs (ssg-attrib-read ename))
|
||||
@@ -171,7 +201,9 @@
|
||||
(if (and id-val (> (strlen id-val) 0))
|
||||
(progn
|
||||
(setq id-num (atoi id-val))
|
||||
(if (> id-num max-id) (setq max-id id-num))
|
||||
;; max-id NICHT mehr hier nachziehen - es steht seit Phase 0 auf
|
||||
;; dem globalen Maximum und dient ab jetzt nur noch als Zaehler
|
||||
;; fuer die Neuvergabe.
|
||||
;; In Map eintragen: (id-num . (ename1 ename2 ...))
|
||||
(setq entry (assoc id-num id-map))
|
||||
(if entry
|
||||
|
||||
Reference in New Issue
Block a user