AutoLISP, Excel

Bloki w tabeli

Tabela w AutoCAD-zie jest obiektem pozwalającym organizować dane w wiersze i kolumny, podobnie jak ma to miejsce w arkuszu kalkulacyjnym. Mało tego – tabelę można dynamicznie powiązać z arkuszem programu Microsoft Excel.

Ponadto, w komórkach tabeli można umieścić bloki, czyli obiekty graficzne. Wszystko to pozwala na tworzenie standaryzowanych, profesjonalnych i bezbłędnych zestawień różnych elementów. Dziś o blokach w tabeli właśnie. Rzecz jasna LISP-owo…

Wstawianie pojedynczych bloków do komórek tabeli, z pewnością jest czynnością fascynującą, pod warunkiem że, tych bloków jest nie więcej niż dwa… W każdym innym przypadku, warto jednak wydziobać LISP-em parę linii kodu… Automatyzację tego procesu, za pomocą paru nawiasów widać poniżej:

Oczywiście przykład jest uproszczony, najważniejsze jest pokazanie mechanizmu działania. Sposób w jaki tabela została utworzona (pusta tabela / tabela ze stylu tabel / import z Excel-a), nie ma właściwie znaczenia. Najważniejsze jest wypełnienie komórek, w których mają znajdować się bloki, tekstem zawierającym nazwę tegoż bloku. Aby jednak program „wiedział”, w których komórkach znajdują się te nazwy, poprzedzone są one prefiksem – tutaj postaci BL: . Całość można przygotować  w Excel-u, czy w pliku tekstowym. Następnie koniecznym jest załadowanie poniższego programu (+ oczywiście CADPL-Pack’a):


; =============================================================== ;
; C:IBLTAB - 2018 by kojacek                                      ;
; --------------------------------------------------------------- ;

(defun C:IBLTAB (/ e o v n i p)
  (setq p "BL:")
  (if
    (and
      (setq e (car (entsel "\nWybierz tabelę: ")))
      (= "ACAD_TABLE" (cdr (assoc 0 (entget e))))
    )
    (if
      (vlax-write-enabled-p e)
      (progn
        (setq o (vlax-ename->vla-object e))
        (setq v (apply 'append (jk:TAB-GetCellsVal o)))
        (cd:SYS_UndoBegin)
        (foreach % v
          (if
            (and
              (setq i (caddr %))
              (= (type i) 'STR)
              (= (substr i 1 (strlen p)) p)
            )
            (if
              (and
                (setq n
                  (substr i (1+ (strlen p))(strlen i))
                )
                (tblobjname "BLOCK" n)
              )
              (progn
                
                (vla-SetBlockTableRecordId
                  o (car %)(cadr %)
                  (vla-get-ObjectId
                    (vla-item (cd:ACX_Blocks) n))
                  :vlax-false
                )
                (vla-SetBlockScale o (car %)(cadr %) 1.0)
              )
            )
          )
        )
        (cd:SYS_UndoEnd)
      )
      (princ "\nTabela jest zablokowana do edycji. ")
    )
    (princ "\nNelezy wskazać tabelę: ")
  )
  (princ)
)
; --------------------------------------------------------------- ;
(defun jk:TAB-Cells (Obj / r c)
  (setq c (cd:CAL_Sequence 0 (vla-get-Columns Obj) 1)
        r (cd:CAL_Sequence 0 (vla-get-Rows Obj) 1)
  )
  (mapcar '(lambda (%1)(mapcar '(lambda (%2)(list %1 %2)) c)) r)
)
; --------------------------------------------------------------- ;
(defun jk:TAB-GetCellsVal (Obj / c)
  (setq c (jk:TAB-Cells Obj))
  (mapcar
     '(lambda (%1)
        (mapcar
         '(lambda (%)
            (append
              %
              (list
                (vlax-variant-value
                  (vla-GetCellValue Obj (car %)(cadr %))
                )
              ))
          ) %1)) c
  )
)
; --------------------------------------------------------------- ;
(princ)

… i wywołanie polecenia IBLTAB. Oczywistym jest też że, potrzebne bloki muszą znajdować się w rysunku. Ważnym jest także aby teksty, w komórkach w których mają znaleźć się bloki, zawierały tylko jego nazwę z określonym prefiksem, tekst nie powinien być formatowany (kolor / styl / wielkości czcionki itp.).

. . . )

Reklamy
AutoLISP

Nowy PLAV

Rekonstrukcja ( 😉 co za słowo!) istniejącej polilinii polegająca na dodaniu jej nowych wierzchołków to, kolejny temat który (ponownie) postaram się przybliżyć. Program o nazwie plav.fas przedstawiłem już kiedyś w tym wpisie. Teraz przybywa w nowym, lepszym (mam nadzieję) wcieleniu.

Nowością jest polecenie PLAVC, które dodaje nowe wierzchołki dla wskazanej polilinii w środku każdego jej segmentu. Pozwala to w szybki sposób „zagęścić” ilość wierzchołków obiektu. To w połączeniu z możliwością „wyprostowania” segmentów łukowych polilinii (a które opisałem TUTAJ) pozwala, gdy zachodzi taka potrzeba, odwzorować uproszczoną (bo składającą się tylko z segmentów liniowych) grafikę różnych obiektów. Działanie polecenia PLAVC widać poniżej:

Istniejące wcześniej w plav.fas polecenia PLAV (dodanie jednego nowego wierzchołka w punkcie wskazania polilinii), oraz PLAVM (wielokrotne dodanie wierzchołków), działają tak samo jak w poprzedniej wersji. Poprawiłem ich wydajność, oraz usunąłem pewne błędy, które mogły występować przy dodawaniu wierzchołków na segmentach łukowych. Jeżeli zatem dotychczas używałeś plav.fas, zachęcam do pobrania najnowszej wersji.

Polecenia: PLAV , PLAVM i PLAVC         Plik do pobrania: plav.fas (~5kB)

( . . . )

AutoLISP

Suma wymiarów

Dziś, stosunkowo krótki kawałek kodu, niemniej wydaje się że, dość przydatnego. Służy do szybkiego sumowania wymiarów. Działanie makra przedstawiam na poniższej animacji:

Zdefiniowane polecenie DIMSUM pozwala szybko sprawdzić, rzeczywistą długość wskazanych wymiarów. Pamiętać bowiem należy że, w stylach wymiarowania zwykle ustawia się pewną tolerancję do której są zaokrąglane teksty wymiarowe. W rysunku architektonicznym i budowlanym, często spotyka się odstępstwa wielkości do 0,5 jednostki. Ustawienia stylu wymiarowego, pozwalają wtedy zwymiarować rzeczywistą długość np. 99,82 jako 100. Mając jednak na uwadze, swego rodzaju „higienę rysunku”, użytkownik może na bieżąco podczas wymiarowania kontrolować precyzję rysowania. Narzędzie może również służyć do sumowania wartości wskazanych wymiarów w dowolnym celu (sprawdzenie wysokości, obwodów itp.). Pomoże również wyłapać nadpisania tekstów wymiarowych, co jest ze wszech miar złą, ale (niestety) czasem spotykaną praktyką. Poniżej kod makra:


; =============================================================== ;
; dimsum - 2012 by kojacek                                        ;
; --------------------------------------------------------------- ;
(defun C:DIMSUM (/ ss)
  (if
    (setq ss (ssget '((0 . "DIM*"))))
    (apply '+
      (mapcar
        '(lambda (%)(cdr (assoc 42 (entget %))))
        (cd:SSX_Convert ss 0)
      )
    )
  )
)
; --------------------------------------------------------------- ;
(princ)

Rzecz jasna poprawne działanie gwarantuje wczytanie biblioteki CADPL-Pack. Na marginesie – suma wymiarów w rysunku demonstracyjnym, jest przypadkowa… 🙂 . Pierwotnie temat był (jakiś czas temu) poruszany tutaj.

( . . . )

 

AutoLISP

Rysowanie strzałek – aktualizacja

Pierwszy (zaplanowany) wpis w 2018 roku miał mieć zupełnie inną treść… ale wydaje się że, w ostatnim czasie (aż nadto długim), spotykam tylko rzeczy których nie planowałem, tak też jest trochę i w tym przypadku. Rzecz dotyczy mianowicie dość starego programu który przedstawiłem jakiś czas temu tutaj. Pewne problemy z wyświetlaniem ikon w oknie dialogowym na różnych platformach (Civil i AutoCAD 2015/2018, oraz Civil i AutoCAD 2017), spowodowały potrzebę pochylenia się raz jeszcze nad kodem tego już dość leciwego  (acz niezmiennie wykorzystywanego) programu. Skutkiem jest odświeżenie jego części, a co za tym idzie pewne zmiany w działaniu:

Pierwsza wyraźnie widoczna zmiana, to pliki programu. Poprzednio były to dwa pliki: arrow.vlx (skompilowany binarny zestaw programu LISP (lsp) i definicji okna dialogowego  (dcl)), oraz plik arrow.slb (biblioteka slajdów AutoCAD-a). Teraz jest to tylko jeden plik – arrow.fas –  plik szybkiego ładowania, czyli skompilowana binarna wersja pliku lsp. Zmiana jest także artykułowana w linii poleceń po załadowaniu pliku fas:

Inna widoczna zmiana to belka tytułowa okna dialogowego. Teraz wyświetlana jest tam nazwa pliku i rok 2018. Ponadto, teraz wyświetlany jest w oknie piktogram rzeczywistego koloru w trybie rysowania kolorem JakWarstwa. Poprzednio wyświetlany był kolor biały/czarny. To wprawdzie mała zmiana, ale wygodna:

Kolejna zmiana to, działanie okna dialogowego. Teraz, program zapamiętuje (w sesji) położenie okna, i wyświetla je w ostatnim miejscu. To cecha którą (z lubością) praktykuję w swoich programach. Oczywiście jeśli komuś ta funkcjonalność nie jest potrzebna, nie musi zmieniać położenia okna, program wyświetlać się będzie zawsze na środku ekranu. Ostatnia nowa funkcjonalność programu, to zapamiętanie ostatniej opcji (Tak/Nie), przy wyborze dokonania zmian, i proponowanie jej jako domyślną. To znacznie przyśpiesza działanie. W poprzednich wersjach, domyślną opcją był wybór: Nie.

Na koniec. Do teraz w programie używany był plik biblioteki slajdów arrow.slb. Slajdy wyświetlane były w wycinakach image_button. Ponieważ teraz zastosowałem technikę programowego wyświetlania wektorów w image_button, slajdy nie są już potrzebne. Bibliotekę slajdów na potrzeby programu utworzyłem prawie 18 lat temu… Przez cały ten czas plik nie był zmieniany:

Ciekawym może być teraz kwestia: ile kolejnych lat będzie działać arrow.fas? Tutaj: [spiral.lsp] przedstawiłem program z roku 1985… Wprawdzie, teraz nie ma on wielkiego zastosowania, ale daje się go uruchomić i działa prawidłowo. LISP ponadczasowy jest… 🙂

Plik programu do pobrania: [arrow.fas (~20kB)] – ostania wersja: styczeń 2018

( . . . )

AutoCAD, AutoLISP

Uproszczone wyświetlanie obiektów

Niezależnie od jakości karty graficznej, ogólnej mocy komputera, ustawień przyspieszenia  sprzętowego, na wydajność wyświetlania ekranu graficznego AutoCAD-a, realny wpływ ma ilość widocznych obiektów. Zależność jest od zawsze prosta – im mniej obiektów, i o mniejszym stopniu skomplikowania  geometrii, tym wydajność jest lepsza. Oczywiście jeśli dysponujesz sprzętem na który wydałeś więcej niż wynosi roczny budżet średniej wielkości afrykańskiego państwa… możesz dalej tego nie czytać… 😉 …

Ogólnie można zwiększyć szybkość edycji dla dużych, skomplikowanych plików rysunku przez ustawienia wyświetlania uproszczonych wersji pewnych rodzajów obiektów. Wydajność wyświetlania zwiększa się, gdy szerokie polilinie, wypełnienia jednorodne (obszary, trasy), kreskowania, wypełnienia gradientowe i obiekty tekstowe (teksty, teksty wielowierszowe, pola danych, wymiary) są wyświetlane w uproszczonej formie. Uproszczone wyświetlanie może zwiększać także szybkość tworzenia roboczych wydruków testowych, szkiców itp. AutoCAD ma mechanizmy do uproszczonego wyświetlania tych obiektów, poprzez ustawienia pewnych zmiennych systemowych. Są to zmienne: FILLMODE – sterująca wyświetlaniem kreskowań, gradientów, obszarów, tras, szerokich polilinii, QTEXTMODE – mająca wpływ na rzeczywistą, lub uproszczoną (w formie zarysów) reprezentację tekstów, atrybutów bloków, tekstów wielowierszowych, tekstów wymiarowych. Ponadto zmienna LWDISPLAY, pozwala przełączać tryb wyświetlenia szerokości linii, o ile są stosowane.

Dla lepszego komfortu pracy, większej kontroli nad rysunkiem i co za tym idzie większej wydajności, na własny użytek skoncentrowałem te wszystkie ustawienia w definicji jednego LISP-owego polecenia, które w dynamicznie tworzonym oknie dialogowym, pozwala dokonywać wszystkich zmian. Ponadto zmiany widoczne są podczas aktywności okna dialogowego, co pozwala szybko ocenić ich efekt:

Najważniejsze polecenie o nazwie DM, wywołuje okno dialogowe, gdzie bieżące ustawienia zmiennych są od razu odzwierciedlane w ustawieniach. Zmiany poszczególnych wycinków, powodują natychmiastowe zmiany wyświetlania obiektów. Ponadto zdefiniowane są jeszcze trzy polecenia, które działają w linii poleceń jak przełącznik zmiennej systemowej – każde wywołanie zmienia aktualne ustawienie na wartość przeciwną. Są to: polecenie – FIM – zmiana zmiennej FILLMODE, polecenie – QTM – zmiana QTEXTMODE, oraz polecenie: LWD – przełącznik zmiennej LWDISPLAY. Poniżej kod całego pliku DrawMode.lsp, z definicjami wszystkich potrzebnych funkcji:


;;; =============================================================== ;
;;; DrawMode.lsp 2010/2017 kojacek                                  ;
;;; Polecenia sterujace wyswietlaniem obiektow: zmienne systemowe   ;
;;; FILLMODE / QTEXTMODE / LWDISPLAY                                ;
;;; =============================================================== ;
(defun C:FIM ()(jk:SYS_DrawMode 0 nil T)(princ))   ;<- FILLMODE     ;
(defun C:QTM ()(jk:SYS_DrawMode 1 nil T)(princ))   ;<- QTEXMODE     ;
(defun C:LWD ()(jk:SYS_DrawMode 2 nil nil)(princ)) ;<- LWDISPLAY    ;
(defun C:DM ()(jk:SYS_DrawModeDlg)(princ))         ;<- okno dialogowe
; ----------------------------------------------------------------- ;
; Funkcja przelaczania zmiennej z wartosciami 0 / 1, gdy Mode=nil   ;
; dziala jak przelacznik                                            ;
; ----------------------------------------------------------------- ;
(defun jk:SYS_OnOff (SVar Mode)
  (cond
    ( (not Mode)(setvar SVar (abs (1- (getvar SVar)))))
    (T (if (member Mode '(0 1))(setvar SVar Mode)))
  )
)
; ----------------------------------------------------------------- ;
; Funkcja zmiany trzech zmiennych systemowych wyswietlania,         ;
; z opcjonalnym REGEN                                               ;
; ----------------------------------------------------------------- ;
(defun jk:SYS_DrawMode (Typ Mode Re)
  (jk:SYS_OnOff
    (nth Typ (list "FILLMODE" "QTEXTMODE" "LWDISPLAY"))
    Mode
  )
  (if Re (vla-regen (cd:ACX_ADoc) acActiveViewport))
)
; ----------------------------------------------------------------- ;
; Funkcja dynamicznego okna dialogowego do zmiany trzech zmiennych  ;
; systemowych wyswietlania obiektow. Zmiany podczas aktywnosci dlg  ;
; ----------------------------------------------------------------- ;
(defun jk:SYS_DrawModeDlg (/ fd tmp dc f q l r)
  (if (not *cd-TempDlgPosition*)
    (setq *cd-TempDlgPosition* (list -1 -1))
  )
  (setq f (getvar "FILLMODE")
        q (abs (1- (getvar "QTEXTMODE")))
        l (getvar "LWDISPLAY")
  )
  (cond
    ( (not
        (and
          (setq fd
            (open
              (setq tmp (vl-fileName-MkTemp nil nil ".dcl")) "w"
            )
          )
          (foreach %
            (list
              "DrawMode:dialog{"
              "label=\"Uproszczenia wyświetlania\";"
              ":boxed_column{"
              "label=\"Pełne wyświetlanie:\";"
              ":toggle{key=\"f\";"
              "label=\"Wypełnień (FILLMODE)\";}"
              ":toggle{key=\"q\";"
              "label=\"Tekst / Mtext (QTEXTMODE)\";}"
              ":toggle{key=\"l\";"
              "label=\"Szerokości linii (LWDISPLAY)\";}"
              "}ok_only;}"
            )
            (write-line % fd)
          )
          (not (close fd))
          (< 0 (setq dc (load_dialog tmp)))
          (new_dialog "DrawMode" dc ""
            (cond
              ( *cd-TempDlgPosition* )
              ( (quote (-1 -1)) )
            )
          )
        )
      )
    )
    ( T
      (foreach % '("f" "q" "l")
        (set_tile % (itoa (vl-symbol-value (read %))))
      )
      (action_tile "f"
        "(setq r T)(jk:SYS_DrawMode 0 (read $value) T)"
      )
      (action_tile "q"
        "(setq r T)(jk:SYS_DrawMode 1 (abs (1- (read $value))) T)"
      )
      (action_tile "l"
        "(setq r T)(jk:SYS_DrawMode 2 (read $value) T)"
      )
      (action_tile "accept"
        "(if r (setq *cd-TempDlgPosition* (done_dialog 1)))"
      )
      (start_dialog)
    )
  )
)
;;; =============================================================== ;
(princ)

Program (rzecz jasna) korzysta z biblioteki CADPL-Pack (co jest tu już tradycją 😉 ). Przedstawione makra wykorzystuję zwykle podczas tworzenia ustawień wydruku, definiowania layout’ów, dopasowywania rzutni, nakładania odnośników zewnętrznych, rastrów itp. gdzie zwykle „nie opłaca się” wyłączać dużej ilości warstw, a wygodniej jest pracować z uproszczoną grafiką.

( . . . )

AutoCAD, AutoLISP

Zmienne systemowe (znane i nieznane)

Parę słów o zmiennych systemowych. AutoCAD od samego początku swego istnienia posiadał szerokie możliwości adaptacyjne. Jedną z nich jest możliwość odczytu i (niekiedy) zmiana pewnych parametrów programu i (lub) dokumentu (rysunku). Ogólnie zmienne systemowe AutoCAD-a, wzorowane są na zmiennych środowiskowych systemu operacyjnego. Na marginesie AutoCAD ma do nich również dostęp – są to (w przeciwieństwie do nazwy systemowe) zmienne środowiskowe. Mechanizm jest wspólny – pod określoną nazwą, przechowywane są pewne dane. W AutoCAD-zie, tymi danymi mogą być: łańcuch tekstowy, liczba całkowita, liczba rzeczywista, punkt 2D, oraz punkt 3D. Wartości te mogą być przez program (lub działanie użytkownika) zmieniane, lub też mogą być w trybie tylko do odczytu (read-only). Zmienne przechowywane (zapisywane) mogą być w rejestrze Windows, w rysunku, lub nie są nigdzie zapamiętywane. Aktualnie w AutoCAD-zie istnieje ponad 900 zmiennych systemowych. Czy użytkownik musi je wszystkie znać? Zapewne nie – ale aby mówić że się dobrze zna AutoCAD-a, trzeba znać przynajmniej z 850 zmiennych… 😉 … Kilka z nich, być może mniej znanych, ale według mnie przydatnych, opiszę poniżej. Na początek o uchwytach (GRIPS) obiektów.

GRIPCOLOR, GRIPCONTOUR, GRIPDYNCOLOR

Trzy zmienne odpowiadające za wygląd uchwytów, pierwsza z nich GRIPCOLOR,  steruje kolorem uchwytów dla wszystkich wybranych obiektów. Zapisywana w rejestrze, a wartość domyśla to 150 (kolor niebieski) – jak na poniższym obrazie:

Dopuszczalne wartości to liczby (kolory) od 1 do 255. Zmienna GRIPCONTOUR – steruje kolorem konturu uchwytu. Tak samo jest to liczba całkowita określająca kolor (1-255), zapisywana w rejestrze. Domyślnie jest to odcień szarości – kolor 251. Trzecia zmienna o  nazwie  GRIPDYNCOLOR, odpowiada za kolor uchwytów niestandardowych dla bloków dynamicznych. Tak samo jest to kolor z zakresu 1-255, domyślnie jest odcień koloru niebieskiego o numerze 140.

Możliwości manipulowania kolorami uchwytów obiektów AutoCAD-a, z pewnością nie są najważniejsze, niemniej wygodniej jest pracować z indywidualnym zestawem kolorów. Ja czasem używam schematu tak jak powyżej: zwykłe uchwyty kolor 200 (lekki fioletowy), uchwyty parametrów dynamicznych bloków – żółte, obwódki uchwytów czerwone. Na marginesie, dla uwypuklenia różnic w obu obrazach uchwyty są nienaturalnie powiększone – odpowiada za to zmienna (ale o tym (przecież) wszyscy wiemy): GRIPSIZE

GRIPTIPS

Ta zmienna steruje wyświetlaniem etykiet uchwytów w trakcie trzymania kursora nad blokami dynamicznymi i obiektami niestandardowymi, które obsługują etykiety uchwytów. Z pozoru ma małe znaczenie, jednak przy bardziej skomplikowanych blokach dynamicznych (o większej ilości uchwytów), od razu dostrzeżesz jej zalety. Zmienna, ma dwie wartości: 0 oraz 1 – wyłącza (lub włącza) wyświetlanie podpowiedzi uchwytów. Zapisywana jest w rejestrze, a wartość domyślna to 1. Poniżej widać zachowanie bloku dynamicznego, po ustawieniu kursora nad uchwytem parametru bloku dynamicznego:

Aby jednak taka etykieta mogła się pojawić należy w definicji bloku dynamicznego, wypełnić opis odpowiedniego parametru:

Za pomocą opisów parametrów można wyraźnie poprawić czytelność bloku,  a co za tym idzie poprawić ich działanie. Zaobserwowałem też pewną przypadłość – zdarza się że etykieta nie jest wyświetlana dla parametru tabeli danych bloku dynamicznego.

PLINECONVERTMODE

Teraz w możliwie płynny sposób przejdziemy od zmiennych dotyczących uchwytów do zmiennych obiektów rysunkowych. Mało znana zmienna o nazwie PLINECONVERTMODE, jest bardzo użyteczna, jeżeli zachodzi potrzeba konwertowania obiektów typu SPLINE na polilinie. Zmienna zapisywana jest w rejestrze Windows i ma dwie wartości: 0 i 1.

Zmiany splajnów na polilinię umożliwa polecenie EDSPLAJN_SPLINEDIT). Wartość 0 zmiennej,  powoduje utworzenie polilinii składającej się z odcinków liniowych:

Natomiast wartość 1, pozwala tworzyć polininię składającą się z segmentów łukowych:

Wybór sposobu odwzorowania krzywych typu splan, przez polilinie składające się albo z segmentów liniowych, albo łukowych, może być ważne przy tworzeniu geometrii na potrzeby obrabiarek sterowanych numerycznie. Warto pamiętać o istnieniu tych dwóch możliwości konwersji. Pamiętać trzeba też że, każda konwersja splajnu na polilinię, wiąże się z utratą dokładności.

PLINEREVERSEWIDTHS

Ostatnia zmienna jaką dziś przypomnę to zmienna o nazwie PLINEREVERSEWIDTHS. Steruje ona wyglądem polilinii po odwróceniu jej kierunku. Zapisywana w rejestrze, z wartością początkową 0. Stan ten  powoduje że, kolejność segmentów wybranej polilinii zostaje odwrócona, lecz kolejność szerokości segmentów pozostaje bez zmian. Gdy zmienna ma wartość 1, to  zarówno kolejność jak i kierunek segmentów edytowanej polilinii zostają odwrócone – tak jak to widać poniżej:

Odwrócenie kierunku polilinii możliwe jest za pomocą polecenia ODWRÓĆ (_REVERSE), lub za pomocą opcji Odwróć polecenia EDPLIN (_PEDIT).

Temat zmiennych systemowych nieustannie przewija się w wielu tutejszych wpisach, znajomość ich stosowania, manipulowania wartościami, jest jednym z podstawowych elementów adaptacji AutoCAD-a. W jednym z wcześniejszych wpisów przedstawiam program realizujący automatyczne ustawianie wybranych zmiennych systemowych AutoCAD-a, na podstawie danych z pliku typu ini.

Z LISP-owego punktu widzenia, ważnymi funkcjami są: getvar i setvar (dla zmiennych systemowych), oraz getcfg i setcfg, (dla zmiennych środowiskowych). Te dwie ostatnie, w przyszłości zostaną wycofane. W ich miejsce zaleca się stosowanie funkcji dostępu do rejestru Windows (vl-registry-…).

( . . . )

 

AutoLISP

Gwiazdka (z nieba)…

Stare wrony mówią: Jeżeli nie ma czegoś w AutoCAD-zie, to… należy sobie  wydziobać trochę kodu LISP-em, żeby było.” Zwłaszcza jeśli tym dziobaniem, można jeszcze nieco pogwiazdorzyć… 😉 O gwiazdach zatem teraz będzie. Narysowanie wieloramiennej gwiazdy w AutoCAD-zie, nie jest szczególnym problemem, jeśli zna się ich konstrukcje geometryczne (prace ręczne), albo (bazując na poleceniu WIELOBOK (_POLYGON)), narysować ramiona gwiazdy i potem odpowiednio je przyciąć (również ręcznie). Alternatywą jest rzecz jasna napisanie prostego programu rysującego gwiazdy. Od najprostszej (i chyba najpopularniejszej) pięcioramiennej, do na przykład dziewięcioramiennej (choć jest to tylko zawężenie wynikające z estetyki, bo właściwie nie ma tu ograniczeń programowych). Oczywiście pominę tutaj wątek dotyczący symboliki gwiazd w różnych kulturach, skupię się na zagadnieniu ich konstrukcji, za pomocą krótkiego makra LISP-owego. Na początek nieco (cadowskiej) geometrii, na przykładzie najprostszej gwiazdy pięcioramiennej, zwanej też czasem gwiazdą pięciopromienną. Ogólnie konstrukcja jest taka sama dla wszystkich gwiazd. Założeniem jest że, do utworzenia dowolnej n-ramiennej gwiazdy potrzebujemy znać jej środek geometryczny (który jest jednocześnie środkiem okręgu ją opisującego) oraz  promień jej ramienia. W rzeczywistości jest to promień (tegoż samego) okręgu na obwodzie którego oparte są wszystkie wierzchołki. Wszystkie inne konieczne dane potrzebne do narysowania gwiazdy, oblicza program. W ostateczności sprowadza się to do wyliczenia wszystkich punktów charakterystycznych, by na ich podstawie utworzyć zamkniętą polilinię.

Powyższa ilustracja wyjaśnia cały mechanizm działania funkcji wyliczającej wszystkie punkty gwiazdy n-ramiennej, znając jej punkt środkowy (Cen), ilość ramion (n), i promień ramienia (Rad – na rysunku czerwona linia). Na początku wyliczane są punkty skrajne ramion – jest to n-elementowa (na rysunku 5-elementowa) lista punktów, leżących na obwodzie okręgu o promieniu Rad. Punkty są równo rozmieszczone na okręgu – wynika to z podziału kąta pełnego (2pi) na n równych części. Z góry założone jest że pierwszy wierzchołek każdej gwiazdy znajduje się „na górze”, czyli na „godzinie 12”. Gdyby w tej chwili przerwać obliczenia – jest to lista pozwalająca narysować wielobok foremny, analogicznie jak w poleceniu _POLYGON. Dla gwiazd należy jeszcze wyliczyć dodatkowe punkty – są to miejsca styku linii sąsiadujących ze sobą ramion gwiazdy. Pierwszy punkt (xp) wyliczany jest za pomocą funkcji inters – jest to przecięcie linii utworzonej z pierwszego i trzeciego wierzchołka zewnętrznego gwiazdy, z linią wyznaczoną przez trzeci i ostatni wierzchołek. Wyliczając taki punkt (xp), program  oblicza mniejszy promień (na rysunku zielona linia), oraz kąt (funkcja angle dla Cen i xp) początkowy. Mając te dane, tworzona jest druga lista punktów, tym razem punktów „wewnętrznych” gwiazdy. Na koniec z połączenia (naprzemiennie kolejnych elementów) obu list, otrzymujemy listę punktów pozwalającą narysować gwiazdę n-ramienną. Poniżej widać pięć różnoramiennych gwiazd, które rysowane są według tego schematu:

Samo rysowanie wygląda zaś tak. Tutaj dla zachowania tych samych wielkości, gwiazdy rysowane są w pomocniczych okręgach (choć nie ma takiej potrzeby – gwiazdy są rysowane bez okręgów). Po wywołaniu polecenia STAR, wystarczy wybrać typ gwiazdy (5- 6- 7- 8- lub 9- ramienną). Następnie trzeba wskazać punkt centralny oraz podać (lub wyznaczyć przez wskazanie punktu), promień okręgu opisującego gwiazdę, i… gotowe:

Cały kod programu czyli definicja polecenia STAR i funkcja jk:ENT_StarPts wygląda tak:


; ------------------------------------------------------------------ ;
; stars.lsp - rysuje 5 / 6 / 7 / 8 / 9 ramienna gwiazde              ;
; 2003, 2017 kojacek                                                 ;
; ------------------------------------------------------------------ ;

; ------------------------------------------------------------------ ;
(if (not *jk-Star*)(setq *jk-Star* "5"))
; ------------------------------------------------------------------ ;
(defun C:STAR (/ o c r p)
  (if
    (setq o
      (cd:USR_GetKeyWord
        "\nGwiazda. Podaj liczbę ramion:"
        '("5" "6" "7" "8" "9" "Koniec") *jk-Star*
      )
    )
    (if
      (/= o "Koniec")
      (if
        (setq c (getpoint "\nOkreśl środek: "))
        (if 
          (setq r (getdist c "\nOkreśl promień okręgu opisanego: "))
          (progn
            (setq p (jk:ENT_StarPts c (atoi o) r)
                  *jk-Star* o
            )
            (cd:SYS_UndoBegin)
            (cd:ACX_AddLWPolyline (cd:ACX_ASpace) p T)
            (cd:SYS_UndoEnd)
          )
          (princ "\nNie podano promienia. ")
        )
        (princ "\nBrak punktu. ")
      )
      (princ "\nAnulowano. ")
    )
  )
  (princ)
)
; ------------------------------------------------------------------ ;
(defun jk:ENT_StarPts (Cen Nv Rad / la pa xp lb rb pb l)
  (setq la (cd:CAL_Sequence (* 0.5 pi) Nv (/ (* 2 pi) Nv))
        pa (mapcar '(lambda (%)(polar Cen % Rad)) la)
        xp (inters (car pa)(caddr pa)(cadr pa)(last pa))
        lb (cd:CAL_Sequence (angle Cen xp) Nv (/ (* 2 pi) Nv))
        rb (distance Cen xp)
        Pb (mapcar '(lambda (%)(polar Cen % rb)) lb)
        l  (apply
            'append
            (mapcar 
              '(lambda (%1 %2) 
                 (list 
                   (list (car %1)(cadr %1)) 
                   (list (car %2)(cadr %2)) 
                 ) 
               ) pa pb 
             )
           )
  )
)
; ------------------------------------------------------------------ ;
(princ)

Oczywiście (tradycyjnie już) wykorzystuję tutaj bibliotekę CADPL-Pack. Korzystam z funkcji rysującej polilinię – cd:ACX_AddLWPolyline, określającą aktywną przestrzeń – cd:ACX_ASpace, pobierającą od użytkownika słowo kluczowe – cd:USR_GetKeyWord,  funkcje znaczników dla UNDOcd:SYS_UndoBegin i cd:SYS_UndoEnd, oraz niezwykle tutaj przydatnią funkcję tworzacą listę elementów ciągu arytmetycznego – cd:CAL_Sequence. Jest ona na tyle ciekawa że, postaram się opisać jej możliwości w osobnym wpisie.

A na koniec jeszcze parę gwiazdek… 😉 :

( . . . )