diff --git a/Lisp/ssg_stueckliste.lsp b/Lisp/ssg_stueckliste.lsp new file mode 100644 index 0000000..2e191d1 --- /dev/null +++ b/Lisp/ssg_stueckliste.lsp @@ -0,0 +1,281 @@ +;; ============================================================ +;; SSG_STUECKLISTE.LSP - Positionsfaehnchen + Stuecklistentabelle +;; +;; Befehl: +;; SSG_FAEHNCHEN_STUECKLISTE Setzt an jedem gewaehlten ILS-/Omniflo-/ +;; Geruest-Element ein Positions-Faehnchen und +;; zeichnet die zugehoerige Stuecklistentabelle +;; auf die Zeichnung. +;; +;; Alles entsteht AUS DER ZEICHNUNG - es wird keine Datei eingelesen. +;; Zum Vergleich der frueheren Walz-Loesung (MENU/POSITION.LSP): dort vergab +;; ein externes Clipper-Warenwirtschaftssystem die Positionsnummern und +;; lieferte spaltenfixe .pos-/.zei-Dateien zurueck, die AutoCAD nur noch +;; abgezeichnet hat. Dieser Umweg ist hier bewusst nicht nachgebaut: die +;; Positionsnummern und Mengen entstehen in dieser Funktion, die +;; Stuecklisten-AUSGABE fuer Sivas/CSV liefern EXPORTSIVAS/EXPORTCSV aus +;; denselben Block-Attributen. +;; +;; Setzt ssg_core.lsp, ssg_lang.lsp und ssg_input.lsp voraus, dazu +;; csv:get-bbox/csv:get-attrib aus export.lsp und ssg-bt-effname aus +;; ssg_blocktools.lsp - MUSS daher nach beiden geladen werden (siehe +;; ssg-ensure-Reihenfolge in SSG_LIB.mnl und ssg_load.lsp). +;; ============================================================ + +(vl-load-com) + +;; ------------------------------------------------------------ +;; POSITIONSFAEHNCHEN +;; ------------------------------------------------------------ + +;; Ein Faehnchen bei pt0 mit Positionsnummer posnr zeichnen (Layer muss +;; bereits aktiv sein). umrand = "1" rechteckig, "2" Kreis, "3" Automation. +;; Geometrie und Masse aus der Walz-Vorlage (posfahne) uebernommen. +(defun ssg-sl-faehnchen (pt0 posnr faktor umrand / pt1 pt2 pt3 pt4 pt5 pt6 x y z) + (setq x (car pt0) y (cadr pt0) z (caddr pt0)) + (cond + ((= umrand "2") + (setq pt1 (list (+ x (* faktor 100)) (+ y (* faktor 150)) z)) + (setq pt5 (list (+ x (* faktor 125)) (+ y (* faktor 175)) z)) + (setq pt6 (list (+ (car pt1) (* faktor 125)) (+ (cadr pt1) (* faktor 68)) z)) + (command "_line" pt0 pt1 "") + (command "_circle" pt6 (* faktor 153)) + (command "_text" pt5 (rtos (* faktor 75)) "0" (itoa posnr)) + ) + ((= umrand "3") + (setq x (- x 15) y (- y 15)) + (setq pt0 (list x y z)) + (setq pt1 (list (- x (* faktor 250)) y z)) + (setq pt2 (list (car pt1) (+ (cadr pt1) (* faktor 150)) z)) + (setq pt3 (list x (+ y (* faktor 150)) z)) + (setq pt5 (list (- x (* faktor 225)) (+ y (* faktor 25)) z)) + (command "_pline" pt0 "_w" "0" "0" pt1 pt2 pt3 pt0 "") + (command "_text" pt5 (rtos (* faktor 75)) "0" (itoa posnr)) + ) + (t + (setq pt1 (list (+ x (* faktor 100)) (+ y (* faktor 150)) z)) + (setq pt2 (list (+ (car pt1) (* faktor 250)) (cadr pt1) (caddr pt1))) + (setq pt3 (list (car pt2) (+ (cadr pt2) (* faktor 125)) (caddr pt1))) + (setq pt4 (list (car pt1) (cadr pt3) (caddr pt1))) + (setq pt5 (list (+ x (* faktor 125)) (+ y (* faktor 175)) z)) + (command "_pline" pt0 "_w" "0" "0" pt1 "") + (command "_pline" pt1 pt2 pt3 pt4 pt1 "") + (command "_text" pt5 (rtos (* faktor 75)) "0" (itoa posnr)) + ) + ) +) + +;; ------------------------------------------------------------ +;; STUECKLISTENTABELLE +;; ------------------------------------------------------------ + +;; Stuecklistentabelle (Kopf + Rahmen + Zeilen) ab p1 (obere linke Ecke der +;; ersten Zeile) zeichnen. zeilen = Liste von (POS MENGE LAENGE ARTNR BEZ), +;; alle Felder als String. Layer muss bereits aktiv sein. Rueckgabe: Anzahl +;; gezeichneter Zeilen. Spaltenraster aus der Walz-Vorlage (stcklimp). +(defun ssg-sl-tabelle-zeichnen (p1 zeilen / p11 p12 p91 p92 p93 p94 p95 + tsize lspace daten n) + (setq tsize 100.0 + lspace 200.0) + (setq p11 (list (- (car p1) 100.0) (+ (cadr p1) 250.0))) + (setq p12 (list (+ (car p1) 9000.0) (+ (cadr p1) 250.0))) + (command "_line" p11 p12 + (list (car p12) (+ (cadr p12) 350.0)) + (list (car p11) (+ (cadr p11) 350.0)) p11 "") + (setq p91 (list (+ (car p11) 400.0) (+ (cadr p11) 100.0))) + (setq p92 (list (+ (car p11) 800.0) (+ (cadr p11) 100.0))) + (setq p93 (list (+ (car p11) 1450.0) (+ (cadr p11) 100.0))) + (setq p94 (list (+ (car p11) 2050.0) (+ (cadr p11) 100.0))) + (setq p95 (list (+ (car p11) 3250.0) (+ (cadr p11) 100.0))) + (command "_text" p91 tsize "0" (ssg-text "sl-stkl-kopf-pos")) + (command "_text" p92 tsize "0" (ssg-text "sl-stkl-kopf-menge")) + (command "_text" p93 tsize "0" (ssg-text "sl-stkl-kopf-laenge")) + (command "_text" p94 tsize "0" (ssg-text "sl-stkl-kopf-artikel")) + (command "_text" p95 tsize "0" (ssg-text "sl-stkl-kopf-bezeichnung")) + (setq n 0) + (foreach daten zeilen + (command "_text" p1 tsize "0" (nth 0 daten)) + (command "_text" (list (+ (car p1) 400.0) (cadr p1)) tsize "0" (nth 1 daten)) + (command "_text" (list (+ (car p1) 1000.0) (cadr p1)) tsize "0" (nth 2 daten)) + (command "_text" (list (+ (car p1) 1900.0) (cadr p1)) tsize "0" (nth 3 daten)) + (command "_text" (list (+ (car p1) 3000.0) (cadr p1)) tsize "0" (nth 4 daten)) + (command "_line" (list (- (car p1) 100.0) (- (cadr p1) 50.0)) + (list (+ (car p1) 9000.0) (- (cadr p1) 50.0)) "") + (setq p1 (list (car p1) (- (cadr p1) lspace))) + (setq n (1+ n)) + ) + (command "_line" p11 p12 + (list (+ (car p1) 9000.0) (- (cadr p1) 50.0)) + (list (- (car p1) 100.0) (- (cadr p1) 50.0)) p11 "") + n +) + +;; ------------------------------------------------------------ +;; ELEMENTE AUS DER ZEICHNUNG ERKENNEN UND GRUPPIEREN +;; ------------------------------------------------------------ +;; +;; Erfasst dieselben Elementarten wie der alte Walz-c:stueckl, aber aus der +;; Zeichnung statt aus Linienlaengen auf Spezial-Layern: ILS Kreisel/Eckrad +;; (KREISEL_*/ECKRAD_*), ILS Streckengruppen (VF_*/GF_*), Rohrgeruest (GR_*) +;; und Omniflo-Geraden (AP60*/AP110*/AP_110*/APG110*). +;; +;; Gruppierung bewusst GROB je Elementklasse (keine Sivas-Artikelaufloesung +;; wie export_sivas.py) - eine Tabellenzeile pro Klasse mit Anzahl und, +;; soweit vorhanden, Laengensumme aus dem LAENGE-Attribut. Jedes einzelne +;; erkannte Element bekommt ein Positions-Faehnchen an seiner Bounding-Box- +;; Ecke mit der Positionsnummer seiner Tabellenzeile; mehrere gleichartige +;; Elemente tragen daher dieselbe Nummer. + +;; Elementklasse eines Blocknamens oder nil, wenn nicht erkannt. +;; Rueckgabe: (schluessel . bezeichnung) oder nil. +(defun ssg-sl-klasse (bname / b) + (setq b (strcase bname)) + (cond + ((or (wcmatch b "KREISEL_*") (wcmatch b "ECKRAD_*")) + (cons "ils_kreisel" (ssg-text "sl-erk-kreisel"))) + ((or (wcmatch b "VF_*") (wcmatch b "GF_*")) + (cons "ils_strecke" (ssg-text "sl-erk-strecke"))) + ((wcmatch b "GR_*") + (cons "geruest" (ssg-text "sl-erk-geruest"))) + ((wcmatch b "AP60*") + (cons "ap60" (ssg-text "sl-erk-ap60"))) + ((wcmatch b "APG110*") + (cons "apg110" (ssg-text "sl-erk-apg110"))) + ((or (wcmatch b "AP110*") (wcmatch b "AP_110*")) + (cons "ap110" (ssg-text "sl-erk-ap110"))) + (t nil) + ) +) + +;; Aus einem Auswahlsatz die Elemente heraussuchen, die ssg-sl-klasse erkennt. +;; Nicht erkannte Objekte (fremde Bloecke, Linien, Texte) fallen still weg - +;; der Benutzer darf also grosszuegig ein Fenster aufziehen. +;; Rueckgabe: Liste von (ENAME . KLASSE), KLASSE = (schluessel . bez). +(defun ssg-sl-elemente-aus-ss (ss / i ename bname klasse res) + (if ss + (progn + (setq i 0) + (while (setq ename (ssname ss i)) + (setq bname (ssg-bt-effname ename)) + (if (setq klasse (ssg-sl-klasse bname)) + (setq res (cons (cons ename klasse) res)) + ) + (setq i (1+ i)) + ) + ) + ) + (reverse res) +) + +;; Elemente fuer Faehnchen/Stueckliste bestimmen: zuerst wird eine Auswahl +;; erfragt; Enter ohne Auswahl nimmt alle erkannten Elemente des aktuellen +;; Layouts. Rueckgabe wie ssg-sl-elemente-aus-ss. +(defun ssg-sl-erkannte-elemente ( / ss) + (prompt (ssg-text "sl-erk-auswahl")) + (setq ss (ssget '((0 . "INSERT")))) + (if (null ss) + (setq ss (ssget "_X" (list '(0 . "INSERT") (cons 410 (getvar "CTAB")))))) + (ssg-sl-elemente-aus-ss ss) +) + +;; Laenge eines Elements aus dem LAENGE-Attribut (mm) oder 0.0, falls keines. +(defun ssg-sl-elem-laenge (ename / wert) + (setq wert (csv:get-attrib ename "LAENGE")) + (if wert (atof wert) 0.0) +) + +;; Erkannte Elemente nach Klassenschluessel gruppieren. elemente = Liste von +;; (ENAME . (SCHLUESSEL . BEZ)), wie ssg-sl-erkannte-elemente liefert. Die +;; LAENGE je Element wird HIER per ssg-sl-elem-laenge aus der Zeichnung +;; gelesen - daher nicht ohne Zeichnung testbar; siehe +;; ssg-sl-gruppieren-werte fuer den file-freien Kern. +;; Rueckgabe: Liste von (schluessel bezeichnung anzahl laenge-mm) in der +;; Reihenfolge des ersten Auftretens. +(defun ssg-sl-gruppieren (elemente / werte) + (setq werte + (mapcar '(lambda (e) (list (car (cdr e)) (cdr (cdr e)) (ssg-sl-elem-laenge (car e)))) + elemente)) + (ssg-sl-gruppieren-werte werte) +) + +;; Reiner Kern von ssg-sl-gruppieren, ohne Zeichnungszugriff: werte = Liste +;; von (schluessel bezeichnung laenge-mm) je Element. Rueckgabe wie dort. +(defun ssg-sl-gruppieren-werte (werte / gruppen eintrag schluessel bez laenge) + (foreach w werte + (setq schluessel (nth 0 w) + bez (nth 1 w) + laenge (nth 2 w)) + (setq eintrag (assoc schluessel gruppen)) + (if eintrag + (setq gruppen (subst + (list schluessel bez (1+ (nth 2 eintrag)) (+ (nth 3 eintrag) laenge)) + eintrag gruppen)) + (setq gruppen (append gruppen (list (list schluessel bez 1 laenge)))) + ) + ) + gruppen +) + +;; ------------------------------------------------------------ +;; BEFEHL +;; ------------------------------------------------------------ + +(defun c:SSG_FAEHNCHEN_STUECKLISTE ( / layer faktor umrand elemente gruppen + posnr-map pos g bbox min-pt zeilen n p1) + (ssg-start (ssg-text "sl-erk-titel") nil) + (setq elemente (ssg-sl-erkannte-elemente)) + (if (null elemente) + (prompt (ssg-text "sl-erk-keine")) + (progn + (setq gruppen (ssg-sl-gruppieren elemente)) + (setq layer (ssg-in-string (ssg-text "sl-pos-layer") "ZZ_Position") + faktor (ssg-in-real (ssg-text "sl-pos-faktor") 1.0) + umrand (ssg-in-keyword (ssg-text "sl-pos-umrand") "Rechteck Kreis Automation" "Rechteck")) + (setq umrand (cond ((= umrand "Kreis") "2") ((= umrand "Automation") "3") (t "1"))) + (ssg-make-layer layer "7" T) + + ;; Positionsnummer je Gruppenschluessel (1-basiert, Reihenfolge der + ;; Gruppenliste). + (setq posnr-map nil pos 0) + (foreach g gruppen + (setq pos (1+ pos)) + (setq posnr-map (cons (cons (car g) pos) posnr-map)) + ) + + ;; Faehnchen je einzelnem Element an der unteren linken Ecke seiner + ;; Bounding-Box. csv:get-bbox liefert (cx cy cz dx dy dz) - Zentrum + + ;; Abmessungen, keine Eckpunkte - die Ecke wird daraus berechnet. + (foreach e elemente + (setq bbox (csv:get-bbox (car e))) + (if bbox + (progn + (setq min-pt (list (- (nth 0 bbox) (/ (nth 3 bbox) 2.0)) + (- (nth 1 bbox) (/ (nth 4 bbox) 2.0)) + (- (nth 2 bbox) (/ (nth 5 bbox) 2.0)))) + (setq pos (cdr (assoc (car (cdr e)) posnr-map))) + (ssg-sl-faehnchen min-pt pos faktor umrand) + ) + ) + ) + + ;; Stuecklistentabelle: eine Zeile je Gruppe. + (setq zeilen nil) + (foreach g gruppen + (setq pos (cdr (assoc (car g) posnr-map))) + (setq zeilen (cons + (list (itoa pos) (itoa (nth 2 g)) + (if (> (nth 3 g) 0.0) (rtos (nth 3 g) 2 0) "") + "" (nth 1 g)) + zeilen)) + ) + (setq zeilen (reverse zeilen)) + (setq p1 (getpoint (ssg-text "sl-stkl-einfuegepunkt"))) + (setq n (ssg-sl-tabelle-zeichnen p1 zeilen)) + (prompt (ssg-textf "sl-erk-ergebnis" (list (length elemente) n))) + ) + ) + (ssg-end) + (princ) +) + +(princ) diff --git a/doc/images/gf-linienzug3.png b/doc/images/gf-linienzug3.png index b5e6af2..3d4abf8 100644 Binary files a/doc/images/gf-linienzug3.png and b/doc/images/gf-linienzug3.png differ diff --git a/lib/export_csv.py b/lib/export_csv.py index 295f88a..8d1bb90 100644 --- a/lib/export_csv.py +++ b/lib/export_csv.py @@ -1126,7 +1126,7 @@ def process_blocks(blocks, lookup, dbg=None): cnt_einzel += 1 continue - # Omniflo Gerade (AP110) + # Omniflo Gerade (AP110/AP60) if matches_any(bname, BLOCKPATTERNS.get("pattern_gerade", [])): elem_nr += 1 gerade_count += 1 @@ -1140,7 +1140,10 @@ def process_blocks(blocks, lookup, dbg=None): "merkmale": build_gerade_merkmale(block), **bbox_columns(block), }) - len_ap110_mm += get_laenge_mm(block) + if bname.upper().startswith("AP60"): + len_ap60_mm += get_laenge_mm(block) + else: + len_ap110_mm += get_laenge_mm(block) continue # VarioFoerderer Compound-Block (VF_N)