AutoLISP

VPLayer samopowtarzalny…

Praca z dużą ilością arkuszy na których występuje wiele rzutni, wymaga od użytkownika wielokrotnego powtarzania oddzielnie takich samych czynności służących do sterowania widocznością warstw, czy ustalania określanych widoków w każdym układzie. Przykładowo, pewne elementy rysunku (np. rzutnie w obszarze papieru) znajdują się na osobnej warstwie, którą przed wydrukiem należy ukryć. Z kolei inne obiekty (warstwy) muszą być wtedy widoczne, lub mogą mieć inne określone cechy (kolor, szerokość linii, poziom przezroczystości itp.). Oczywiście oczekujemy że takie działanie powinno mieć charakter wybiórczy – to powinno działać w określonej rzutni. W takich sytuacjach z pomocą przychodzi polecenie _VPLAYER

Standardowe polecenie _VPLAYER (RWARSTWA), umożliwia właśnie ustawianie rozmaitych trybów widoczności warstw w obrębie rzutni. Zachęcam do korzystania z szerokiego wachlarzu możliwości  tego polecenia, a jako przykład przedstawiam, krótkie makro ułatwiające tworzenie pewnego rodzaju ustawień dla każdej zakładki (układu / arkusza papieru), w pliku rysunkowym.  

Zdefiniowane jest polecenie ZPAP, które należy wywołać w obszarze modelu. Działanie makra polega na automatycznym „przejściu” po każdym układzie (Layout), ustawieniu blokowania trzech określonych warstw w aktualnej rzutni, oraz ustawieniu widoku całego arkusza. Lista blokowanych warstw zapisana jest w zmiennej globalnej o nazwie *jk-PaperSpaceLayer*. Kod krótkiego makra definiującego polecenie ZPAP wygląda tak:


; ===================================================================== ;
; C:ZPAP - blokuje w rzutni ukladu papieru warstwy z listy zmiennej     ;
;          globalnej *JK-PaperSpaceLayer* dla wszystkich ukladow.       ;
;          by kojacek - 2018                                            ;
; ===================================================================== ;
(setq *JK-PaperSpaceLayer* '("_VP1" "_VP2" "_VP3"))
; ===================================================================== ;
(defun C:ZPAP (/ l c -za)
  (defun -za ()
    (vla-ZoomAll (vla-get-Application (cd:ACX_ADoc)))
  )
  (if
    (= (getvar "CTAB") "Model")
    (progn
      (setq l (layoutlist)
            c (getvar "CMDECHO")
      )
      (setvar "CMDECHO" 0)
      (foreach % l
        (setvar "CTAB" %)
        (-za)
        (foreach %1 *JK-PaperSpaceLayer*
          (if
            (tblobjname "LAYER" %1)
            (command "_VPLAYER" "_F" %1 "" "")
          )
        )
        (vla-Regen (cd:ACX_ADoc) acActiveViewport)
      )
      (setvar "CTAB" "Model")
      (setvar "CMDECHO" c)
    )
    (princ "\nPolecenie niedozwolone w obszarze papieru. ")
  )
  (princ)
)
; ===================================================================== ;

Jak widać zastosowanie makra, znacząco poprawia wydajność pracy – wystarczy sobie wyobrazić ręczne działanie polegające na aktywowaniu każdego układu, sprawdzeniu stanu warstw i (ewentualną) ich zmianę, oraz na koniec ustawieniu widoku całego arkusza… dla 5… 10… 20 zakładek. Rzecz jasna na potrzeby wpisu, makro przedstawia tylko jedno działanie dla trzech warstw – ostatecznie każdy z czytelników może sobie ten zakres w dowolny sposób rozszerzyć. Celem (jak zwykle) jest pokazanie możliwości automatyzacji powtarzalnych, rutynowych czynności.   

Tradycyjnie już (przypomnę), do poprawnego działania konieczne jest załadowanie CADPL-Pack‚a. O LISP-owych zmiennych globalnych (i nie tylko) pisałem też TUTAJ.

(   . . .   )

Reklamy
AutoLISP

Biblioteki…

W idealnym CAD-owskim świecie, jedną z fundamentalnych zasad jest: nigdy nie rysuj czegokolwiek dwa razy… Jedną z dróg dążących do tego ideału jest wykorzystywanie własnych bibliotek elementów powtarzalnych. Tutaj zaś, istnieje kilka sposobów ich tworzenia i zarządzania. Zwykle są to bloki, parametryczne bloki dynamiczne, ale też elementy rysowane on-line, na podstawie danych charakterystycznych.

Poniżej przedstawiam w dużym uproszczeniu stosunkowo krótki program do dynamicznego tworzenia bloków, stalowych profili. Ze względu na miejsce prezentuję tylko jedną funkcję rysującą dwuteowniki równoległościenne typu Universal Beam i Universal Column (British Standard). Inne dowolne funkcje rysujące można sobie napisać samemu – tutaj zależy mi na pokazaniu mechanizmu działania. W skrócie zaś wygląda on tak. Po wywołaniu polecenia BS-STEEL, w linii poleceń można wybrać typ profilu, a następnie (w oknie dialogowym) jego wielkość. Po wskazaniu punktu wstawienia, w jego miejscu umieszczany jest blok wybranego profilu. Na poniższej animacji widać działanie programu:

Najważniejszą rzeczą (w moim przekonaniu) tego schematu działania, jest brak konieczności tworzenia dziesiątek czy setek bloków tych elementów, przechowywania ich na dysku, oraz istnienia mniej lub bardziej skomplikowanego systemu ich zarządzania… Tutaj bowiem bloki tworzone są w locie – w chwili potrzeby ich użycia. Wszystko zaś odbywa się za pomocą kilku nawiasów… 😉

Poniżej kod programu:


; ===================================================================== ;
; Steel profile (BS) by kojacek 2018                                    ;
; ===================================================================== ;
(defun C:BS-STEEL (/ i j k l r d a n u b s)
  (if (not *jk-BS-STEEL*)(setq *jk-BS-STEEL* "UB"))
  (setq l '( ("UB" . "Universal Beam")
             ("UC" . "Universal Column")
             ("EA" . "Equal Angles")
             ("UA" . "Unequal Angles")
             ("PFC". "Parallel Flange Channels")
             ("SHS" . "Square Hollow Section")
             ("RHS" . "Rectangular Hollow Section")
          )
        i (findfile "Steel_Profiles.ini")
        j 0
        k *jk-BS-STEEL*
  )
  (if
    (setq r
      (cd:USR_GetKeyWord "\nSelect steel profile"
        (append (mapcar 'car l) '("Exit"))
        k
      )
    )
    (if
      (= r "Exit")
      (princ "\nCancelled. ")
      (if
        (setq d (jk:LIB_Get-Steel i (setq s (cdr (assoc r l)))))
        (progn
          (setq *jk-BS-STEEL* r
                a (mapcar 'car d)
          )
          (if
            (numberp
              (setq n
                (cd:DCL_StdListDialog
                  a j s "Select profile:" 30 15 2 11
                  (list "&OK" "&Cancel")
                  nil T T nil
                )
              )
            )
            (progn
              (cd:SYS_UndoBegin)
              (setq u (nth n d)
                    b (if
                        (not (tblobjname "BLOCK" (car u)))
                        (cond
                          ( (= r "UB")(jk:LIB_2T-Profile u))
                          ( (= r "UC")(jk:LIB_2T-Profile u))
                          ;*  ( (= r "EA")(jk:LIB_L-Profile u))
                          ;*  ( (= r "UA")(jk:LIB_L-Profile u))
                          ;*  ( (= r "SHS")(jk:LIB_R-Profile u))
                          ;*  ( (= r "RHS")(jk:LIB_R-Profile u))
                          (t nil)
                        )
                        (car u)
                      )
              )
              (if b
                (if
                  (setq p
                    (getpoint
                      (strcat
                        "\nSelect point to insert "
                        (car u)
                        ": "
                      )
                    )
                  )
                  (cd:BLK_InsertBlock p b nil 0 T)
                  (princ "\nError - bad point.")
                )
                (princ "\nCancelled.")
              )
              (cd:SYS_UndoEnd)
            )
            (princ "\nCancelled.")
          )
        )
        (princ (strcat "\nCan not find [" s "] data. "))
      )
    )
    (princ "\nCancelled")
  )
  (princ)
)
; ===================================================================== ;
(defun jk:LIB_Get-Steel (File Group / f g)
  (if
    (and
      (setq f (findfile File))
      (setq g (acet-ini-get f Group))
    )
    (mapcar
      '(lambda (%)
         (cons % (cd:STR_Parse (acet-ini-get f Group %) "," t))
      ) g
    )
  )
)
; ===================================================================== ;
(defun jk:LIB_2T-Profile (Data / Pins Name D B W F R s hpi i o
                   p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12
                   p13 p14 p15 p16
                  )
  (setq Pins '(0 0 0)
        Name (car Data)
        D (read (cadr Data))
        B (read (caddr Data))
        W (read (cadddr Data))
        F (read (car (cddddr Data)))
        R (read (cadr (cddddr Data)))
  )
  (if
    (not (tblobjname "BLOCK" Name))
    (if
      (setq i
        (vla-Add (cd:ACX_Blocks)(vlax-3d-point Pins) Name)
      )
      (progn
        (setq s (* R (sqrt 2))
              hpi (* 0.5 pi)
              p1 (polar Pins (* 2 pi)(/ B 2.0))
              p2 (polar Pins pi (/ B 2.0))
              p3 (polar p2 hpi F)
              p4 (polar p3 0.0 (- (/ B 2.0)(+ (/ W 2.0) R)))
              p5 (polar p4 (* 0.25 pi) s)
              p6 (polar p5 hpi (- D (+ (* 2.0 R)(* 2.0 F))))
              p7 (polar p4 hpi (- D (* 2.0 F)))
              p8 (polar p3 hpi (- D (* 2.0 F)))
              p9 (polar p2 hpi D)
              p10 (polar p1 hpi D)
              p11 (polar p8 0.0 B)
              p12 (polar p7 0.0 (+ (* 2.0 R) W))
              p13 (polar p6 0.0 W)
              p14 (polar p5 0.0 W)
              p15 (polar p4 0.0 (+ (* 2.0 R) W))
              p16 (polar p1 hpi F)
        )
        (setq o
          (cd:ACX_AddLWPolyline i
            (list p1 p2 p3 p4 p5 p6 p7 p8 p9 p10
                  p11 p12 p13 p14 p15 p16) t
          )
        )
        (foreach % '(3 5 11 13) (vla-setbulge o % 0.414214))
        (cd:ACX_SetProp  o
          '(("LineType" . "ByBlock")("Color" . 0)("Layer" . "0")
            ("Lineweight" . -2)("PlotStyleName" . "ByBlock"))
        )
        (vla-put-BlockScaling i 1)
        (vla-put-Comments i Name)
        (vla-put-Units i 4)
        Name
      )
    )
  )
)
; ===================================================================== ;
(princ)

Do przechowywania danych wykorzystuję „zwyczajny” plik tekstowy o rozszerzeniu ini, oczywiście zgodny w formie zapisu ze standardem windowsowych plików inicjalizacyjnych. Poniżej fragment pliku wykorzystywanego przez opisany tu program:

 

Przypomnę że, o programowym tworzeniu bloków LISP-em, pisałem już TUTAJ. Wykorzystywanie plików tekstowych (typu ini) do przechowywania danych opisywałem TUTAJ. Omówiłem tam sposoby dostępu do danych za pomocą AutoLISP. Rzecz jasna w opisanym oprogramowaniu wykorzystuję również CADPL-Pack‚a.

Rzecz jasna istnieją setki, czy nawet tysiące różnorodnych aplikacji i bibliotek bloków zarówno darmowych i komercyjnych, z których możesz korzystać. Możesz też tak jak tutaj (w skrócie) pokazałem, pokusić się o napisanie programu do tworzenia własnych specyficznych elementów bibliotecznych. Jak widać powyżej, nie musi to być bardzo trudne…

< . . . >

AutoCAD, AutoLISP

Historia (brył)

Intensywne trójwymiarowe modelowanie w AutoCAD-zie, powoduje stopniowym powolnym „rozrostem” (brzydkie słowo (choć są i brzydsze)) wielkości pliku rysunku. Jest to proces nieunikniony, niemniej świadomy użytkownik, powinien (w miarę możliwości) nad nim panować. Jednym ze sposobów jest kontrolowanie trybu zapisu historii bryły. Pozwala ona na zachowywanie całego procesu tworzenia docelowej bryły. Składają się na nią wszystkie operacje wyciągania, wydłużania, ucinania, obrotu, podziału, różnicy, sum i innych działań tworzących model. W większości przypadków (jednak) te informacje nie są do niczego potrzebne. Pomimo domyślnych ustawień (brak zapisu),  zdarza się że AutoCAD, pozwala na zapis historii brył. W takich sytuacjach, często korzystam z narzędzia które napisałem w LISP-ie. Kod polecenia H3DS wygląda tak:

; ------------------------------------------------------------------ ;
; H3DS by kojacek 2018 - Wylacza historie dla istniejacych 3DSOLID   ;
; ------------------------------------------------------------------ ;
(defun C:H3DS (/ s l i j)
  (if
    (setq s (ssget "_x" '((0 . "3DSOLID"))))
    (progn
      (setq i (sslength s) j 0)
      (foreach % (cd:SSX_Convert s 0)
        (if
          (not (zerop (getpropertyvalue % "RecordHistory")))
          (progn
            (setpropertyvalue % "RecordHistory" 0)
            (setq j (1+ j))
          )
        )
      )
      (if
        (not (zerop j))
        (princ
          (strcat
            "\nDla obiektów " (itoa j) " wyłączono historię brył. "
          )
        )
        (princ "Bryły nie mają włączonego trybu zapisu historii. ")
      )
    )
    (princ "\nW rysunku nie ma brył. ")
  )
  (princ)
)
; ------------------------------------------------------------------ ;
(princ)
Wywołanie tego polecenia, powoduje wybranie wszystkich brył (obiekty 3DSOLID), a następnie zmianę ustawień zapisu historii bryły dla każdego obiektu:
W przypadku gdy bryły nie mają zapisanej historii wyświetlany jest komunikat:
Z historią obiektów 3D związane są dwie zmienne systemowe:
oraz:
Niewątpliwie w cyklu projektowania tworzenie trójwymiarowego modelu, jest często jedynym sposobem na unikanie błędów oraz generowanie bezbłędnej dokumentacji rysunkowej, niemniej (często) okupionym spadkiem wydajności, spowodowanej zbyt dużą wielkością pliku. Warto o tym pamiętać, i (przynajmniej), mieć świadomość, co na to wpływa. Na koniec. Choć powyżej była mowa o wyłączaniu historii, dotyczyła jednak ona tylko procesu tworzenia brył 3D w AutoCAD-zie. Na szczęście, (pomimo starań karłów wszelkiej maści), historii (jako takiej) nie da się zmanipulować…   ( . . . )
AutoLISP

ATTA – Edycja atrybutu dla wielu bloków

Ponieważ dotarły (różnymi drogami) do mnie (nieco) krytyczne głosy dotyczące zbyt małej ilości nawiasów prezentowanych ostatnio na blog-u… zatem czym prędzej staram się coś temu zaradzić… Krótki (ale użyteczny) kawałek kodu zaprezentowany poniżej, służy do edycji atrybutów w wielu blokach jednocześnie. Jakie ma to zastosowanie?   

Dobrze skonstruowany projekt zawiera definicję (dwu lub trójwymiarową)  dowolnego obiektu w obszarze modelu, na podstawie którego tworzona jest dokumentacja rysunkowa, składająca się z co najmniej jednego lub więcej arkuszy, tworzonych w obszarze papieru. Wykorzystuje się do tego tak zwane Layout-y, (układy) czy też w innej nomenklaturze znane jako zakładki. Zwykle tworzą one „obszar papieru” czyli pojedyncze arkusze (dwuwymiarowe rysunki) dokumentacji technicznej. Jedną z najważniejszych rzeczy opisujących  rysunek są (między innymi) tabliczki rysunkowe. Znów – w dobrze skonstruowanym projekcie, większość zawartych w nich informacji tworzona jest automatycznie na podstawie danych zgromadzonych w jednym miejscu, a wspólnych dla całości projektu.  

Dobrym zwyczajem jest stosowanie w tym przypadku pól danych (FIELD-ów), ze względu na możliwość ich automatycznej aktualizacji. Są to informacje wspólne dla całości projektu. Część danych (tutaj trzech atrybutów w bloku tabliczki rysunkowej), z różnych względów, musi być jednak edytowana ręcznie. Oczywiście nie wyklucza to też automatyzacji tego procesu. 

Poniżej prezentuję zapowiadany krótki kod umożliwiający edycję wartości jednego atrybutu dla wszystkich (występujących w pliku) wstawień tego samego bloku. Zdefiniowane jest polecenie ATTA, i wymaga ono tylko wskazania dowolnego edytowalnego atrybutu bloku. Zmiana wartości wybranego atrybutu dokonywana jest we wszystkich wstawieniach tego bloku.  


; ------------------------------------------------------------------ ;
; ATTA by kojacek 2018 - Multiple blocks edit attribute              ;
; ------------------------------------------------------------------ ;
(defun C:ATTA (/ e d b s l i a v r)
  (if
    (and
      (setq e (nentsel "\nSelect an attribute: "))
      (= 2 (length e))
      (= "ATTRIB" (cdr (assoc 0 (setq d (entget (car e))))))
    )
    (progn
      (setq b (cdr (assoc 2 (entget (cdr (assoc 330 d))))))
      (if
        (setq s (ssget "_x" (list (cons 0 "INSERT")(cons 2 b))))
        (progn
          (setq l (cd:SSX_Convert s 0)
                i (length l)
                a (cdr (assoc 2 d))
                v (cdr (assoc 1 d))
          )
          (if
            (setq r
              (cd:DCL_StdEditBoxDialog
                (list 0 0 v)
                (strcat "Edit Attribute (in " (itoa i) " blocks)")
                (strcat "Block: " (strcase b) " / Tag: " (strcase a))
                50 10 (list "&OK" "&Cancel") T 50)
            )
            (progn
              (cd:SYS_UndoBegin)
              (foreach % l
                (cd:BLK_SetAttValueVLA % a r)
              )
              (princ
                (strcat "\nUpdated " (itoa i) " blocks. ")
              )
              (cd:SYS_UndoEnd)
            )
            (princ "\nCanceled. ")
          )
        )
      )
    )
    (princ "\nInvalid object selected. ")
  )
  (princ)
)
; ------------------------------------------------------------------ ;
(princ)

Jak widać, zmiana wartości trzech atrybutów w dowolnej ilości bloków trwa zaledwie tylko chwilę. Tutaj (w prezentowanym przykładzie) jest ich 27. Wyobraźmy sobie zmianę tych wartości w kolejno występujących 27 tabliczkach w 27 layout-ach… 

Oczywiście do poprawnego działania konieczne jest wcześniejsze załadowanie CADPL-Pack‚a. 

( . . . )

AutoLISP

CenterMark w obszarze papieru

Modelowanie 3D to rzecz jasna wielkie ułatwienie w procesie projektowania. Pozwala ono (między innymi) w stosunkowo szybki sposób tworzyć bezbłędną trójwymiarową reprezentację dowolnej konstrukcji. Zanim jednak stanie się ona rzeczywistym bytem, prędzej czy później (w większości przypadków) trzeba ją odwzorować w dokumentacji dwuwymiarowej. Ta zaś musi spełniać wiele (unormowanych i sformalizowanych) wymogów dotyczących opisu geometrii przedmiotu. Jednym z nich jest wymiarowanie, a na te oprócz samych wymiarów, składają się także „nierzeczywiste” obiekty jakimi są osie symetrii i znaczniki środków. W AutoCAD-zie, (zwykle) tworzy się model (dwu lub trójwymiarowy) w przestrzeni modelu (ModelSpace), zaś jego dwuwymiarową projekcję i część dokumentacyjną (czyli właściwy rysunek techniczny) z wymiarami, opisami, zestawieniami, tabliczkami itp. w obszarze papieru (PaperSpace).
Powyższa animacja ilustruje działanie mojego krótkiego LISP-owego makra, tworzącego znaczniki środka w obszarze papieru, dla rzutni obiektów trójwymiarowych utworzonych w przestrzeni modelu. W znaczący sposób ułatwia i przyspiesza ono tworzenie końcowej dokumentacji. Zdefiniowane polecenie CC, po wskazaniu punktu, będącego środkiem znacznika środka, pozwala w dynamiczny sposób, poprzez określenie drugiego punktu, ustalić jego wielkość. Ponadto umożliwia stosowanie znacznika nie tylko dla obiektów typu okrąg i łuk, lecz wstawia go w dowolnym miejscu. Dodatkowo umożliwia wielokrotne wstawianie znacznika w innych punktach, jako kopię ostatnio zdefiniowanego. To działanie przyspiesza pracę, w sytuacji oznaczania wielu otworów tej samej wielkości. Możliwości te są niedostępne dla standardowego znacznika środka tworzonego poleceniem ZNACZNIKŚRODKA (_CENTERMARK). Jedyną wadą stosowania tego rozwiązania jest utrata wiązania znacznika środka z opisywanym obiektem. W zdecydowanej większości przypadków, zachowanie tego połączenia nie ma znaczenia – geometria ta, nigdy nie ulega już zmianie.

.

O obiektach typu CenterMark i CenterLine pisałem (nawet dokładnie) w przeszłości już TUTAJ, a o sposobach rozpoznawania bloków (jakimi w rzeczywistości są te obiekty) poświęciłem TEN wpis.

  .

( . . . )
AutoCAD, AutoLISP

AutoCAD 3D…

Czy AutoCAD nadaje się do modelowania 3D? Uprzedzając głosy sprzeciwu wszystkich codziennie modelujących, w programach za tysiące dolarów, gładkie powierzchnie n-tego stopnia… odpowiem – w pewnym stopniu – tak. W pewnym stopniu, oznacza także w ograniczonym stopniu. Czego bowiem nie powiedzieć, możliwości AutoCAD-a, w modelowaniu trójwymiarowym, nie są szczególnie wyszukane. Tym wpisem rozpocznę serię kilku omówień zagadnień modelowania 3D w AutoCAD-zie, z uwzględnieniem (oczywiście) jednego z narzędzi API – LISP-a.

Pewnym, (ale) niewątpliwie niebagatelnym problemem stosowania „surowego” trójwymiarowego modelowania w AutoCAD-zie, jest w dość szerokim stopniu ograniczony dostęp do informacji ma temat geometrii bryły. W pewnym zakresie specjalizowane programy oparte o AutoCAD-a (AutoCAD Architecture, AutoCAD Mechanical, AutoCAD Plant…), omijają te problemy, wykorzystując własne obiekty 3D (ściany, okna, drzwi, otwory, belki, słupy, ławy, skarpy itp.). Mają one własne specjalnie im dedykowane właściwości, zawierające większość potrzebnych specyficznych danych.

Używając tylko podstawowego AutoCAD-owego modelera 3D, trzeba liczyć się z dość szerokimi ograniczeniami. Na swój użytek, wykorzystuję narzędzie LISP-owe które napisałem w celu pobierania głównych gabarytów wskazanych obiektów 3D. Działanie tego narzędzia widać na poniższej animacji.

Zadaniem jest określenie gabarytów wskazanej bryły. Jak widać jedynie w przypadku obiektu typu 3DSOLID (box) możliwe jest pobranie pełnych informacji. Dla obiektów utworzonych przez wyciągnięcie (extrude – ale ważny jest typ wyciąganych elementów), można uzyskać jedynie wielkość wyciągnięcia. Dla innych (utworzonych w inny sposób, lub edytowanych przez ucięcie, sumę, różnicę itp. informacje te są całkowicie niedostępne. Wiedza ta, przydaje się w samym procesie modelowania. Bowiem, do osiągnięcia tego samego efektu, można  dojść różnymi drogami. Niektóre z nich mogą jednak ograniczać dostęp do pewnych podstawowych danych. Tak samo mogą zamykać drogę dalszej łatwej edycji obiektów.

W jakim celu, oraz w jaki sposób uzyskuję dostęp do tych informacji (i nie tylko), postaram się opisać w (niedalekiej) przyszłości…

. . .  )

AutoLISP

Jak ważne są wybory…

… niestety (czasem / coraz częściej) przekonujemy się zbyt (za (?)) późno…  O wyborach obiektów parę słów zatem. AutoCAD dla swoich poleceń oferuje dwie możliwości wyboru obiektów: po wywołaniu polecenia (to naturalny standard) oraz (dodatkowo) przed jego wywołaniem. Oczywiście ta druga opcja jest najbardziej elastyczna, bowiem oferuje użytkownikowi możliwość wcześniejszego wyboru obiektów, a potem zdecydowanie co zrobić z tym wyborem. Steruje tym zmienna systemowa o nazwie PICKFIRST. Ma ona domyślnie wartość 1 (umożliwia wybór obiektów przed uruchomieniem polecenia), lub 0 (obiekty mogą być wybierane po wywołaniu polecenia).

Powyższe rozważania mają zastosowanie nie tylko dla standardowych poleceń AutoCAD-a, ale również poleceń tworzonych przez dowolne API, w tym (co dla nas najważniejsze), definiowanych w AutoLISP-ie. Istnieje bowiem funkcja LISP-owa o nazwie ssgetfirst, która umożliwia stworzenie zbioru wskazań, dla obiektów zaznaczonych uchwytami. Funkcja zwraca dwuelementową listę, której pierwszy element ma zawsze wartość nil (uwarunkowania historyczne), a drugi jest zbiorem wskazań zaznaczonych (uchwytami) obiektów. Gdy nie ma takich obiektów funkcja zwraca listę w formie:

Mechanizm ten (gdy drugi element listy nie jest nil) pozwala, programującemu, na stworzenie takiego swojego polecenia, które będzie działało tak samo jak wszystkie standardowe polecenia AutoCAD-a. Czyli (gdy PICKFIRST = 1), polecenie działa na obiektach wybranych zarówno przed jak i po jego wywołaniu. Pomocna w tym będzie (krótka) funkcja:


(defun jk:SSX_ActiveSel ()
  (if
    (not (zerop (getvar "PICKFIRST")))
    (cadr (ssgetfirst))
  )
)

Zwraca ona (przy jednoczesnej pozytywnej wartości PICKFIRST) zbiór wskazań jeśli obiekty zostały zaznaczone, lub nil w przeciwnym wypadku. Działanie funkcji ilustruje poniższy (ruchomy) obraz:

Przyznam że niezbyt często zwracam uwagę w konstruowaniu poleceń, aby uwzględniały one wcześniejszy zbiór wskazań. Powodem jest dedykowanie działań dla ściśle określonych wyborów, zwykle zawężonych. Stąd dokonywanie wyborów (zbiorów wskazań) wymagane jest po wywołaniu polecenia. Rzecz jasna dla operacji ogólnych dla wszystkich dowolnych obiektów (usuwanie, zmiany cech itp.), warto stosować opisaną powyżej konstrukcję. Wygląda profesjonalnie i (co najważniejsze) zachowuje się tak jak każde standardowe polecenia AutoCAD-a. To ważna cecha, ceniona przez użytkowników.

.  .  .  )