AutoLISP

ARX load

ObjectARX ® (AutoCAD Runtime Extension) jest środowiskiem programowania służącym do tworzenia programów i aplikacji dla AutoCAD-a. Programy generowane są w języku kompilowanym i działają w tej samej przestrzeni adresowej co AutoCAD. Umożliwia to im bezpośredni dostęp do struktur baz danych, systemu graficznego oraz mechanizmów geometrii, tak samo jak robi to program AutoCAD. Pliki aplikacji mają rozszerzenie arx lub (od wersji AutoCAD 2014) także crx.

Z LISP-owego punktu widzenia, użyteczność programów ARX wynika z możliwości wykorzystania poleceń zdefiniowanych w aplikacji, oraz – w szczególnych przypadkach z dostępu do funkcji LISP-a w nich definiowanych. Typowymi przykładami może być funkcja cal (definiowana w module kalkulatora geometrycznego AutoCAD-a), biblioteka acetutil.arx z funkcjami definiowanymi w pakiecie Express Tool, czy (niezleżna) biblioteka DOSLib.

Korzystanie (przez LISP-a) z tych dobrodziejstw możliwe jest po wcześniejszym załadowaniu pliku biblioteki arx. Niestety AutoLISP nie robi tego automatycznie, i na programującym spoczywa obowiązek sprawdzenia czy możliwe jest wywołanie funkcji (lub polecenia), oraz w razie konieczności załadowanie odpowiedniego pliku. Często spotykanym błędem jest pominięcie tego procesu, w wyniku czego (cyt.) „program raz działa, a czasem wywala błąd… „. 

Dla obsługi aplikacji arx AutoLISP oferuje funkcje:

  • arx – zwraca listę aktualnie wczytanych (czyli dostępnych) plików bibliotek arx (bez ścieżek dostępu)
  • arxload – wczytuje (jeśli to możliwe) plik aplikacji arx.
  • arxunload – usuwa z pamięci (wczytany i dostępny) plik aplikacji arx.
  • vl-arx-import – pozwala załadować wybrane (lub wszystkie) funkcje zdefiniowane w pliku arx, dla programu lispowego VLX.

Ważne – ponieważ AutoCAD może korzystać zarówno z plików typu arx jak też crx, w wywołaniu funkcji arx można nie podawać rozszerzenia pliku. Poniższa animacja ilustruje przykład załadowania aplikacji geomcal.arx (AutoCAD 2013 i wersje niższe) lub geomcal.crx (w AutoCAD-zie wyżym niż wersja 2014), bez konieczności sprawdzania typu rozszerzenia aplikacji.

Co ciekawe – funkcja arxunload, tak samo nie działa, dla usunięcia z pamięci apliacji arx, trzeba podać rozszerzenie pliku, i najważniejsze – plików crx nie można „wyładować”, możliwe jest to tylko dla plików arx. Warto o tym pamiętać.

 

(   .  .  .  )

 

Reklamy
AutoLISP

Zbyt duże pliki rysunków…

Zbyt duże pliki rysunków bywają niekiedy utrapieniem projektantów, zwłaszcza w sytuacji gdy nie zawierają zbyt wiele treści. Przykładowy plik w którym narysowana jest tylko jedna (!) linia ma obiętość ok. 5,5 MB… Dochodzenie do prawdy dlaczego tak się dzieje nie zawsze jest łatwe a i samo wchodzenie na drabinkę przecież często nie wystarcza…

Częstą przyczyną takiego stanu rzeczy jest duża ilość niepotrzebnych elementów, zwykle obiektów niegraficznych, takich jak definicje bloków, słowniki, listy skal, materiałów, czy definicje rodzajów linii:

Tutaj nieużywane rodzaje linii, mają odniesienia w słowniku o nazwie ACAD_DGNLINESTYLECOMP.  Wpisy w słowniku tworzone są gdy wykorzystuje się podkłady geodezyjne generowane w Microstation – rysunki tworzone w plikach dgn i importowane do AutoCAD-a:

Wpisów w słowniku może być, w zależności od wielkości i zakresu map naprawdę dużo:

W omawianym przykładzie jest ich dokładnie 49641… Trzeba przyznać że, liczba prawie pięćdziesięciu tysięcy słowników, robi wrażenie:

Ponieważ nie ma innego (niż programowe) sposobu na usunięcie słownika w AutoCAD-zie (PURGE tego nie robi), nie pozostaje nic innego jak użycie w linii poleceń kilku nawiasów. Rzecz jasna pomocnym jest (jak zwykle) CADPL-Pack:

Po takiej operacji polecenie PURGE (USUŃ), jest o wiele bardziej przyjazne – znajduje kolejno nieużywane definicje bloków, jak też związane z nimi definicje rodzajów linii:

Po wyczyszczeniu i zapisaniu rysunku, jego objętość radykalnie maleje. Rysunek „waży” tylko ~35 kB…

Omawiany przykład przedsatwiłem na podstawie dyskusji polskiego forum CAD.PL – wątek: Problem z wklejaniem

.  .  .  )

AutoLISP

Kreskowanie w bloku

Kreskowanie w blokach to właściwie nic szczególnego. Jednak zdarzają się sytuacje, gdy są zbędnym, uciążliwym balastem… Kilka rozwiązań tego problemu znalazło się na forum dyskusyjnym CAD.PL w wątku „Jak usunąc hatch…„.  Ze swej strony przedstawiam nieco inny sposób na kreskowania w blokach – nie usuwam ich, nie zmieniam im warstwy tylko… steruję widocznością obiektu – tutaj obiektu typu HATCH.

Każdy obiekt rysunkowy ma cechę o nazwie Visible, i właśnie ten sposób wykorzystuję w krótkim makrze, którego działanie widać na (ożywionym) obrazie poniżej:

Działanie programu polega na zmianie cechy widoczności wszystkich obiektów typu HATCH w definicji bloku, którego nazwa pobrana jest poprzez utworzenie zbioru wskazań. Taki sposób pozwala na sterowanie widoczności kreskowań w sposób wybiórczy dla różnych bloków. Zdefiniowane polecenie BLK-HAT, działa jak przełącznik: kreskowania są sekwencyjnie włączane i wyłączane.   Kod programu wygląda tak:


; ------------------------------------------------------------------ ;
; BLK-HAT by kojacek 2019 - Ukrywa / odkrywa kreskowania w bloku     ;
; ------------------------------------------------------------------ ;
(defun C:BLK-HAT (/ ss l jk:BLK_Hatch-OnOff)
  (defun jk:BLK_Hatch-OnOff (Name / l)
    (if
      (setq l (cd:BLK_GetEntity Name "HATCH"))
      (foreach % l
        (setpropertyvalue % "Visible"
          (abs (1- (getpropertyvalue % "Visible")))
        )
      )
    )
  )
  (princ "\nWybierz bloki do zmiany kreskowania...")
  (if
    (setq ss (ssget '((0 . "INSERT"))))
    (progn
      (setq l 
        (acet-list-remove-duplicates
           (mapcar '(lambda (%)
                      (cdr (assoc 2 (entget %)))
                    ) (cd:SSX_Convert ss 0)
           ) nil
        )
      )
      (foreach % l
        (jk:BLK_Hatch-OnOff %)
      )
      (vla-regen (cd:ACX_ADoc) acActiveViewport)
    )
    (princ "\nAnulowano. ")
  )
  (princ)
)
; ------------------------------------------------------------------ ;

Do poprawnego działania konieczne jest załadowanie biblioteki CADPL-Pack, oraz narzędzi z pakietu Express Tools – wykorzystuję autodeskową funkcję do usuwania duplikatów z listy o nazwie: acet-list-remove-duplicates.

 

(   . . .  )

AutoLISP

Match Dimension Text

Polecenia wymiarowania AutoCAD-a tworzą pokaźny zestaw narzędzi pozwalających w stosunkowo łatwy sposób opisywać rysunki. Do samego podstawowego tekstu wymiarowego, można dodawać inne informacje, umieszczając je w różnych (powyżej / poniżej / przed / za) miejscach obszaru tekstu wymiarowego. W praktyce brakuje prostego i szybkiego narzędzia kopiującego wartości dodatkowych tekstów, z wymiaru źródłowego, na inne docelowe wymiary. Tak działa polecenie MATCHPROP (UZGWŁASCIWOŚCI), jednak przenosi ono jednoczenie inne właściwości na przykład warstwę, styl wymiarowania, kolor itp. Oczywiście w opcjach polecenia można ustalić możliwość uzgadniania tylko tekstu, ale każdorazowa zmiana właściwości dla wymiarów, a później ich zmiana dla innych obiektów, wydaje się być zbyt uciążliwa…

Dlatego właśnie przy wykorzystaniu paru nawiasów, napisałem proste narzędzie którego działanie ilustruje animacja poniżej:

Jak widać zdefiniowane polecenie DIM-MA, przenosi poszczególne wartości tekstów ze wskazanych wymiarów (czerwone obiekty) na docelowy wymiar, nie zmieniając jego innych cech. Definicje polecenia zamieszczam poniżej:


; ------------------------------------------------------------------ ;
; Match Dimension Text by kojacek 2010, 2018, 2019                   ;
; ------------------------------------------------------------------ ;
(defun C:DIM-MA ()(jk:DIM_Match)(princ))
; ------------------------------------------------------------------ ;
(defun jk:DIM_Match (/ e d s)
  (princ "\nWybierz obiekt źródłowy...")
  (if
    (setq e (jk:DIM_Ssget T))
    (progn
      (setq e (ssname e 0))
      (redraw e 3)
      (princ "Wybierz obiekty docelowe...")
      (if
        (setq s (jk:DIM_Ssget  nil))
        (progn
          (cd:SYS_UndoBegin)
          (jk:DIM_MatchSet
            (jk:DIM_MatchGet e)
            s
          )
          (redraw e 4)
          (cd:SYS_UndoEnd)
        )
      )
    )
  )
)
; ------------------------------------------------------------------ ;
(defun jk:DIM_MatchSet (Data SS / l n)
  (setq l (cd:SSX_Convert SS 0)
        n '("Prefix" "Suffix" "DimensionText")
  )
  (foreach % l
    (foreach %1 n
      (if
        (/= (cdr (assoc %1 Data))(getpropertyvalue % %1))
        (setpropertyvalue % %1 (cdr (assoc %1 Data)))
      )
    )
  )
)
; ------------------------------------------------------------------ ;
(defun jk:DIM_MatchGet (Ent)
  (mapcar
    '(lambda (%)
       (cons % (getpropertyvalue Ent %)))
    '("Prefix" "Suffix" "DimensionText")
  )
)
; ------------------------------------------------------------------ ;
(defun jk:DIM_Ssget (Mode / ss)
  (ssget
    (if Mode "_+.:S:L" "_:L")
    (list (cons 0 "DIM*")(cons 410 (getvar "CTAB")))
  )
)
; ------------------------------------------------------------------ ;
(princ)
; ------------------------------------------------------------------ ;

Rzecz jasna, konieczne jest załadowanie biblioteki CADPL-Pack. Tematy związane z wymiarami i wymiarowaniem nie raz gościły już na moim blogu. O „półwymiarach” pisałem TUTAJ.  Zastosowanie indeksu górnego w wymiarach było tematem TEGO wpisu. Kilka słów o sumowaniu wymiarów można zaś znaleźć TU. Także opisując reaktory posłużyłem się programem ukrywającym wymiary. Zastosowanie wymiarów do tworzenia jednokreskowych szkiców konstrukcji omówiłem w TYM wpisie…

Do wymiarów (i LISP-owej ich manipulacji) zamierzam również powrócić w przyszłości, dzisiejszy wpis warto rozszerzyć o omówienie sposobów tworzenia prefiksów, sufiksów czy tekstów umieszczonych nad i pod tekstem wymiarowym…

< . . . >

AutoCAD

ByBlock… ByLayer…

Nie tylko o kolorach dziś będzie, ale od kolorów jednak zacznę, aby nikt już więcej nie wmawiał nam, że białe jest białe, a czarne – czarne… Dwa (tytułowe) kolory logiczne AutoCAD-a, (ByBlock / JakBlok i ByLayer / JakWarstwa) mają istotne znaczenie, w ustawieniach rysunku, zaś szczególne w definicji bloku. Każdy rysowany element może mieć przypisany (wprost) dowolny kolor, lub (domyślnie) kolor warstwy (kolor JakWarstwa) na której się znajduje.  Pozwala to łatwo zarządzać globalnie kolorami obiektów przez warstwę. Taki naturalny stan rzeczy jest prosty i czytelny.

Nieco bardziej złożony mechanizm ma zastosowanie dla obiektów wchodzących w skład definicji bloków. Rozpocząłem omawianie od koloru, ale oprócz niego, także takie właściwości, jak rodzaj, szerokość linii oraz przezroczystość obiektów mogą mieć przypisaną specjalną wartość ByBlock. Umożliwia to wtedy dziedziczenie tych cech dla wstawień bloku, z właściwości rysunku, warstwy odniesienia, czy też indywidualnych ustawień. Ponadto, równie ważnym w tej sytuacji jest też warstwa obiektu. Dziedziczenie warstwy zapewnia utworzenie obiektu definicji bloku na warstwie 0 (zero). 

Poniższa animacja ilustruje wygląd bloku w którym jeden z obiektów (okrąg o największej średnicy) ma przypisane właściwości (kolor oraz rodzaj linii i szerokość linii) na wartości ByBlock. Okrąg mniejszy i linie osiowe mają cechy przypisane wprost (czerwony okrąg z ciągłą linią, i szare osie z linią center, oraz szerokości linii równą 0.0)

Jak widać każda zmiana cech wstawienia bloku, odzwierciedlona jest dla tylko dla jednego elementu bloku – okręgu o największej średnicy. Można sterować jego wyglądem poprzez zmianę koloru, rodzaju linii oraz jej szerokości. Możliwe jest to dlatego właśnie, bo okrąg ten w definicji bloku miał przypisaną wartość ByBlock, dla tych trzech właściwości. 

Podsumowując – podstawowe bloki możemy tworzyć na trzy sposoby:

  • zachowujące swoje pierwotne cechy – właściwości elementów bloku muszą być różne od ByBlock i Bylayer, a warstwa inna niż warstwa 0 (zero).
  •  dziedziczące właściwości warstwy – właściwości elementów bloku muszą być JakWarstwa (ByLayer), a ich warstwa musi być 0 (zero).
  • cechy przypisane indywidualnie (w tym również JakWarstwa) – cechy elementów zawsze ByBlock (JakBlok) i warstwa zawsze 0 (zero).

Rzecz jasna, dla każdego z obiektów w bloku można przypisywać różne właściwości na podstawie tych powyższych trzech zasad. Ostatnia z nich, pozwala tworzyć bloki najbardziej uniwersalne, którym cechy można dowolnie zmieniać, tworząc różne dla wielu odniesień:

O tworzeniu bloków pisałem już wielokrotnie, problem z warstwami których nie można usunąć, bowiem przypisane są do obiektów w bloku opisywałem tutaj: Warstwy… bloki… purge…  Stary (ale jary) LISP-owy program do automatycznej redefinicji bloków był tematem tego wpisu: RedefineBlockProperties.lsp. Natomiast o kolorach ACI i pewnych problemach z nimi związanych wspominałem tutaj: Kolor . Zachęcam do czytania…

 

( . . . )

AutoLISP

DCL – Image

Parę słów o języku DCL (Dialog Control Language), a w zasadzie tylko o jego jednym elemencie – wycinku o nazwie image. Sterowane przez LISP-a okna dialogowe (właściwie ich opis) definiowane są w zwykłym pliku tekstowym ASCII. Choć wydaje się to rozwiązaniem nieco archaicznym, ma (moim zdaniem) jednak (mimo wszystko) kilka niezaprzeczalnych zalet. (Głównie) są to:

  • niezależność od platformy systemowej (DOS / dowolna wersja Windows / dowolna wersja systemu Mac)
  • zwięzłość opisu – predefiniowane wycinki, wraz z atrybutami tworzą krótki opis wyglądu, położenia i zachowania elementów okna.
  • opis w postaci tekstu – oprócz używania standardowego pliku dcl, umożliwia tworzenie okna „w locie”, jako tymczasowy plik definicji istniejący tylko w czasie trwania działania programu. (Nawiasem mówiąc) moja ulubiona cecha.
  • z uwagi na tekstową definicję łatwy do tworzenia różnych wersji, zarówno językowych, jak też dotyczących samego wyglądu, wielkości, zróżnicowanego działania itp.

Z pewnością temat dotyczący programowania DCL-a, będzie tu jednokrotnie powracał, dziś krótko o nieco szerszym ponadstandardowym wykorzystaniu wycinka image. Wycinek ten zwany też piktogramem jest prostokątnym obszarem w którym wyświetlany jest obraz wektorowy. To wyjątkowa cecha – bowiem zwykle współczesne języki programowania bazują na wyświetlaniu bitmap. Standardowo w image (i w image_button) wyświetla się obrazy wektorowe zapisywane jako slajdy AutoCAD-a (pliki *.sld), które mogą być łączone w jeden plik biblioteki slajdów (*.slb). Alternatywnym, programowym (i moim ulubionym) sposobem tworzenia obrazu w wycinku image, jest wykorzystywanie funkcji LISP-a o nazwie vector_image. Ta technika pozwala w niebywale elastyczny sposób tworzyć grafiki za pomocą kodu programu w trakcie jego wykonywania…

Powyższa animacja ilustruje właśnie takie działanie. W oknie dialogowym służącym do wyboru jednego z kilku typów profili stalowych (w trybie tworzenia bloku 2D  (przekrój) lub rysowania 3D (bryła), wyświetlany jest obraz, tworzony przez oprogramowanie. W zależności od typu profilu, w oknie zmienia się uproszczony jego obraz. Dodatkowo oprogramowałem możliwość wyboru wyświetlania obrazów. Są to dwa tryby: pierwszy – gdzie tłem jest czarny prostokąt, oraz drugi z tłem w kolorze okna dialogowego. Z powodu tych różnic, dla zachowania poprawności i czytelności wyświetlania obrazów. Tutaj w jednym przypadku – opisy są żółte (na tle czarnym), lub niebieskie (na jasnym). Całość uzależniona jest od nastaw zapisanych w pliku konfiguracyjnym ini. Rzecz jasna można stworzyć dowolną ilość różnych kombinacji zestawów kolorów. Co ważne różnice wymagą jedynie niewielkich zmian w danych z których korzysta program. O plikach ini pisałem już TUTAJ.

Współczesne graficzne interfejsy użytkownika stosują obrazy do szybszej, bardziej intuicyjnej i jednoznacznej komunikacji z użytkownikiem. Język DCL i AutoLISP, pozwalają na tworzenie stosunkowo prostych, ale również atrakcyjnie wyglądających, i przede wszystkim niezawodnych okien dialogowych dla własnych programów i makr. Nie jest pozbawiony pewnych wad, wynikających z jego nierozwijania (DCL jest niezmieniany od ponad dwudziestu lat). Mimo tego (moim zdaniem), warty jest poznania i wykorzystywania.

 

( . . . )

 

 

 

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.

(   . . .   )