Files
dxfmakros/Lisp/ssg_id.lsp
T

202 lines
6.3 KiB
Common Lisp

;; ============================================================
;; SSG_ID - Eindeutige ID-Verwaltung fuer SSG_LIB Bloecke
;;
;; Jedes eingefuegte Element erhaelt ein Attribut "ID" mit
;; einer eindeutigen, vierstelligen Nummer (z.B. "0001").
;;
;; Befehle:
;; IDGENERATE - Weist dem zuletzt eingefuegten Block eine neue ID zu
;; IDSCHECK - Prueft alle Bloecke auf doppelte IDs und korrigiert sie
;;
;; Funktionen:
;; (ssg-id-max) - Hoechste ID in der Zeichnung ermitteln
;; (ssg-id-generate ent) - Neue ID erzeugen und auf Block setzen
;; (ssg-id-check-all) - Doubletten pruefen und korrigieren
;; (ssg-id-format n) - Zahl als 4-stelligen String formatieren
;; ============================================================
;; --- ID als 4-stelligen String formatieren ---
;; n = Integer (z.B. 1 -> "0001", 42 -> "0042")
(defun ssg-id-format (n / s)
(setq s (itoa n))
(while (< (strlen s) 4)
(setq s (strcat "0" s))
)
s
)
;; --- Alle exportierbaren INSERT-Entities sammeln ---
;; Gleiche Filterlogik wie csv:collect-export-blocks
(defun ssg-id-collect-blocks ( / ss-all ss-out i ename ed bname)
(setq ss-all (ssget "X" (list (cons 0 "INSERT"))))
(if (null ss-all)
nil
(progn
(setq ss-out (ssadd))
(setq i 0)
(while (setq ename (ssname ss-all i))
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
(if (or
(wcmatch bname "KR_*,KREISEL_*,ECKRAD_*")
(wcmatch (strcase bname) "AP110*,AP_110*,AP60*,AP_60*,APG110*")
(wcmatch bname "Vario*,Staustrecke*,AUS_Element*,EIN_Element*")
(wcmatch bname "#*")
)
(ssadd ename ss-out)
)
(setq i (1+ i))
)
(if (= (sslength ss-out) 0) nil ss-out)
)
)
)
;; --- 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 ( / 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)
(while (setq ename (ssname ss i))
(setq attribs (ssg-attrib-read ename))
(setq id-val (cdr (assoc "ID" attribs)))
(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)
)
)
)
(setq i (1+ i))
)
)
)
max-id
)
;; --- Neue ID erzeugen und auf einen Block setzen ---
;; ent = Entity-Name eines INSERT-Blocks mit ID-Attribut
;; Rueckgabe: Die zugewiesene ID als String oder nil bei Fehler
(defun ssg-id-generate (ent / max-id new-id new-id-str)
(if (and ent (= (cdr (assoc 0 (entget ent))) "INSERT"))
(progn
(setq max-id (ssg-id-max))
(setq new-id (1+ max-id))
(setq new-id-str (ssg-id-format new-id))
(ssg-attrib-set-on ent (list (cons "ID" new-id-str)))
(princ (strcat "\n[ID] Neue ID zugewiesen: " new-id-str))
new-id-str
)
(progn
(princ "\n[ID] FEHLER: Kein gueltiger INSERT-Block!")
nil
)
)
)
;; --- Alle Bloecke auf doppelte IDs pruefen und korrigieren ---
;; Findet Bloecke mit gleicher ID. Behaelt die erste Instanz,
;; weist Duplikaten neue IDs zu.
;; Rueckgabe: Anzahl korrigierter IDs
(defun ssg-id-check-all ( / ss i ename attribs id-val id-num
id-map entry max-id fixed-count new-id-str)
(setq ss (ssg-id-collect-blocks))
(if (null ss)
(progn
(princ "\n[IDSCHECK] Keine relevanten Bloecke gefunden.")
0
)
(progn
;; Phase 1: Alle IDs sammeln und hoechste ID ermitteln
(setq id-map nil)
(setq max-id 0)
(setq i 0)
(while (setq ename (ssname ss i))
(setq attribs (ssg-attrib-read ename))
(setq id-val (cdr (assoc "ID" attribs)))
(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))
;; In Map eintragen: (id-num . (ename1 ename2 ...))
(setq entry (assoc id-num id-map))
(if entry
(setq id-map (subst (cons id-num (append (cdr entry) (list ename)))
entry id-map))
(setq id-map (cons (cons id-num (list ename)) id-map))
)
)
;; Block ohne ID -> neue ID zuweisen
(progn
(setq max-id (1+ max-id))
(setq new-id-str (ssg-id-format max-id))
(ssg-attrib-set-on ename (list (cons "ID" new-id-str)))
(princ (strcat "\n[IDSCHECK] Fehlende ID gesetzt: " new-id-str
" (Block " (cdr (assoc 2 (entget ename))) ")"))
)
)
(setq i (1+ i))
)
;; Phase 2: Duplikate korrigieren
(setq fixed-count 0)
(foreach entry id-map
(if (> (length (cdr entry)) 1)
(progn
;; Erste Instanz behalten, Duplikate neu nummerieren
(foreach ename (cdr (cdr entry))
(setq max-id (1+ max-id))
(setq new-id-str (ssg-id-format max-id))
(ssg-attrib-set-on ename (list (cons "ID" new-id-str)))
(princ (strcat "\n[IDSCHECK] Duplikat ID " (ssg-id-format (car entry))
" -> neue ID " new-id-str
" (Block " (cdr (assoc 2 (entget ename))) ")"))
(setq fixed-count (1+ fixed-count))
)
)
)
)
(princ (strcat "\n[IDSCHECK] Fertig. " (itoa fixed-count) " Duplikate korrigiert."))
fixed-count
)
)
)
;; --- Befehl: IDSCHECK ---
;; Prueft alle Bloecke auf doppelte IDs und korrigiert sie.
(defun c:IDSCHECK ( / count)
(ssg-start "IDSCHECK" nil)
(setq count (ssg-id-check-all))
(princ (strcat "\n[IDSCHECK] " (itoa count) " IDs korrigiert."))
(ssg-end)
(princ)
)
;; --- Befehl: IDGENERATE ---
;; Fordert den Benutzer auf, einen Block zu waehlen und weist eine neue ID zu.
(defun c:IDGENERATE ( / ent ed)
(ssg-start "IDGENERATE" nil)
(setq ent (car (entsel "\nBlock waehlen: ")))
(if (and ent (= (cdr (assoc 0 (entget ent))) "INSERT"))
(ssg-id-generate ent)
(princ "\n[IDGENERATE] Kein gueltiger Block gewaehlt.")
)
(ssg-end)
(princ)
)
(princ "\n[SSG_ID] Geladen.")
(princ)