fix: KF_EDIT loeste den Block auf - Blocknummer jetzt ueber die Blocktabelle

KF_EDIT loescht beim Neuaufbau den alten Foerderer. kf-naechste-nummer zaehlte
nur die Referenzen im Modell und vergab dadurch dieselbe Nummer erneut, obwohl
die Block-Definition KF_<n> weiter in der Blocktabelle steht. _.-BLOCK traf auf
den vorhandenen Namen, die "Neu definieren?"-Abfrage verschluckte die
Folge-Eingaben, der Block entstand nicht und die Einzelteile blieben lose im
Modell liegen. GF_n und VF_n pruefen aus demselben Grund die Blocktabelle.

- kf-freie-nummer ueberspringt jede Nummer mit vorhandener Block-Definition
- kf-nummer-aus-name liest nur rein numerische Namen (KF_2D, KF_UM_26 und
  KF_LAENGE tragen dasselbe Praefix, atoi("2D") waere 2)
- KF_EDIT nutzt zuerst die vorgewaehlte Auswahl (Doppelklick), entsel nur als
  Rueckfall, und akzeptiert nur echte KF_<n>
- Unit-Tests fuer Namens-Parser und Nummernvergabe
- KF_2D.dwg: ueberarbeitete Draufsicht

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-30 12:17:06 +01:00
parent 989ee398ce
commit 61372e9104
4 changed files with 80 additions and 9 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+50 -8
View File
@@ -632,18 +632,51 @@
kf-insert) kf-insert)
;; Naechste freie KF-Nummer in der Zeichnung. ;; Naechste freie KF-Nummer in der Zeichnung.
(defun kf-naechste-nummer ( / n ss i nm num) ;; Nummer aus einem Blocknamen "KF_<n>" (rein numerisch), sonst nil. Die
;; Bausteine der Kette heissen ebenfalls "KF_...": "KF_2D" (Draufsicht),
;; "KF_UM_26", "KF_LAENGE" duerfen NICHT als Nummer gelesen werden - atoi
;; liefert fuer "2D" naemlich 2 und fuer "UM_26" 0. Reiner Rechenkern.
(defun kf-nummer-aus-name (nm / rest i ok)
(setq nm (strcase nm))
(if (and (> (strlen nm) 3) (= (substr nm 1 3) "KF_"))
(progn
(setq rest (substr nm 4) i 1 ok T)
(while (and ok (<= i (strlen rest)))
(if (not (wcmatch (substr rest i 1) "#")) (setq ok nil))
(setq i (1+ i)))
(if ok (atoi rest) nil))
nil))
;; Erste freie Nummer ab start: ueberspringt jede Nummer, fuer die belegt-p
;; (Symbol einer Ein-Argument-Funktion) T liefert. Reiner Rechenkern, das
;; Praedikat macht die Zeichnungsabfrage austauschbar und damit testbar.
(defun kf-freie-nummer (start belegt-p / n)
(setq n start)
(while (apply belegt-p (list n)) (setq n (1+ n)))
n)
;; Ist die Block-DEFINITION KF_<n> in der Zeichnung vorhanden?
(defun kf-nummer-belegt-p (n)
(not (null (tblsearch "BLOCK" (strcat "KF_" (itoa n))))))
;; Naechste freie KF-Nummer. Bewusst NICHT nur ueber die Referenzen im Modell:
;; loescht man einen Foerderer (oder baut KF_EDIT ihn neu auf), lebt seine
;; Block-DEFINITION in der Blocktabelle weiter. Wird deren Nummer erneut
;; vergeben, trifft das spaetere _.-BLOCK auf einen vorhandenen Namen - die
;; "Neu definieren?"-Abfrage verschluckt die Folge-Eingaben, der Block entsteht
;; nicht, und die Einzelteile bleiben LOSE im Modell liegen (Fehlerbild "Block
;; aufgeloest"). GF_n und VF_n pruefen aus demselben Grund die Blocktabelle.
(defun kf-naechste-nummer ( / n ss i num)
(setq n 0) (setq n 0)
(setq ss (ssget "X" '((0 . "INSERT") (2 . "KF_*")))) (setq ss (ssget "X" '((0 . "INSERT") (2 . "KF_*"))))
(if ss (if ss
(progn (progn
(setq i 0) (setq i 0)
(while (< i (sslength ss)) (while (< i (sslength ss))
(setq nm (cdr (assoc 2 (entget (ssname ss i))))) (setq num (kf-nummer-aus-name (cdr (assoc 2 (entget (ssname ss i))))))
(setq num (atoi (substr nm 4))) (if (and num (> num n)) (setq n num))
(if (> num n) (setq n num))
(setq i (1+ i))))) (setq i (1+ i)))))
(1+ n)) (kf-freie-nummer (1+ n) 'kf-nummer-belegt-p))
;; ============================================================ ;; ============================================================
;; DIALOG ;; DIALOG
@@ -1082,17 +1115,26 @@
(setq i (1+ i))) (setq i (1+ i)))
(cond (treffer) (0))) (cond (treffer) (0)))
(defun c:KF_EDIT ( / ent ed bname attribs daten eingabe variante hoehe (defun c:KF_EDIT ( / ss ent ed bname attribs daten eingabe variante hoehe
verbindung farbe antriebsmotor movimot steuerung verbindung farbe antriebsmotor movimot steuerung
geo erg laenge skala lmin lmax startpunkt drehung geo erg laenge skala lmin lmax startpunkt drehung
last-ent kf-nummer endpunkt) last-ent kf-nummer endpunkt)
(setq ent (car (entsel (ssg-text "kf-edit-waehlen")))) ;; Erst die VORGEWAEHLTE Auswahl (Doppelklick setzt sie), nur ohne sie per
;; Klick nachfragen - wie GEFAELLESTRECKE_EDIT/KreiselEdit. Vorher fragte
;; KF_EDIT auch nach einem Doppelklick noch einmal nach einer Auswahl.
(setq ss (ssget "I"))
(setq ent (if (and ss (= (sslength ss) 1))
(ssname ss 0)
(car (entsel (ssg-text "kf-edit-waehlen")))))
(if (null ent) (if (null ent)
(princ (ssg-text "kf-abgebrochen")) (princ (ssg-text "kf-abgebrochen"))
(progn (progn
(setq ed (entget ent)) (setq ed (entget ent))
(setq bname (cdr (assoc 2 ed))) (setq bname (cdr (assoc 2 ed)))
(if (or (/= (cdr (assoc 0 ed)) "INSERT") (not (wcmatch bname "KF_*"))) ;; Nur echte Foerderer "KF_<n>": die Bausteine (KF_UM_26, KF_2D, ...)
;; tragen ebenfalls das Praefix KF_, haben aber keine Attribute - ein
;; Neuaufbau aus ihnen waere sinnlos und wuerde sie loeschen.
(if (or (/= (cdr (assoc 0 ed)) "INSERT") (null (kf-nummer-aus-name bname)))
(alert (ssg-text "kf-edit-kein-kf")) (alert (ssg-text "kf-edit-kein-kf"))
(progn (progn
(setq daten (kf-daten)) (setq daten (kf-daten))
Binary file not shown.
+29
View File
@@ -2863,6 +2863,35 @@
(tu-nil "kf-antriebsart/kein-komma" (tu-nil "kf-antriebsart/kein-komma"
(vl-string-search "," (kf-antriebsart '(("titel" . "x"))))) (vl-string-search "," (kf-antriebsart '(("titel" . "x")))))
;; --- kf-nummer-aus-name: nur rein numerische Namen zaehlen ---
;; Die Bausteine heissen ebenfalls KF_...; atoi("2D") waere 2 und wuerde
;; die Nummernvergabe verschieben, sobald lose Teile in der Zeichnung liegen.
(tu-eq "kf-nummer/KF_1" 1 (kf-nummer-aus-name "KF_1"))
(tu-eq "kf-nummer/KF_12" 12 (kf-nummer-aus-name "KF_12"))
(tu-eq "kf-nummer/klein" 7 (kf-nummer-aus-name "kf_7"))
(tu-nil "kf-nummer/KF_2D" (kf-nummer-aus-name "KF_2D"))
(tu-nil "kf-nummer/KF_UM_26" (kf-nummer-aus-name "KF_UM_26"))
(tu-nil "kf-nummer/KF_LAENGE" (kf-nummer-aus-name "KF_LAENGE"))
(tu-nil "kf-nummer/nur-Praefix" (kf-nummer-aus-name "KF_"))
(tu-nil "kf-nummer/fremdes-Praefix" (kf-nummer-aus-name "GR_5"))
;; --- kf-freie-nummer: Nummern mit vorhandener Block-DEFINITION ueberspringen ---
;; Regression "Block aufgeloest": KF_EDIT loescht den alten KF_1, die
;; Referenzen im Modell sind weg (Start = 1), die Definition KF_1 lebt aber
;; weiter. Wurde 1 erneut vergeben, traf _.-BLOCK auf einen vorhandenen
;; Namen, die "Neu definieren?"-Abfrage verschluckte die Folge-Eingaben,
;; und die Einzelteile blieben lose im Modell liegen.
(tu-eq "kf-frei/nichts-belegt" 1
(kf-freie-nummer 1 '(lambda (n) nil)))
(tu-eq "kf-frei/Edit-Szenario" 2
(kf-freie-nummer 1 '(lambda (n) (member n '(1)))))
(tu-eq "kf-frei/mehrere-belegt" 4
(kf-freie-nummer 1 '(lambda (n) (member n '(1 2 3)))))
(tu-eq "kf-frei/Luecke-bleibt" 3
(kf-freie-nummer 1 '(lambda (n) (member n '(1 2 4)))))
(tu-eq "kf-frei/Start-mitten" 5
(kf-freie-nummer 3 '(lambda (n) (member n '(3 4)))))
;; --- kf-drehung-gesamt: Drehwinkel fuer KF_EDIT --- ;; --- kf-drehung-gesamt: Drehwinkel fuer KF_EDIT ---
;; Regression: der Drehwinkel wird beim Bau in die Geometrie eingerechnet, ;; Regression: der Drehwinkel wird beim Bau in die Geometrie eingerechnet,
;; die Blockreferenz selbst hat IMMER Drehung 0 (ssg-block-wrap-welt). ;; die Blockreferenz selbst hat IMMER Drehung 0 (ssg-block-wrap-welt).