AutoCAD... AutoLISP... VisualLISP...

  [44] Diesel

index  

  DIESEL Rudolf, 1858-1913, konstruktor niemiecki. W 1897 zbudował pierwszy wysokopręzny silnik spalinowy z samoczynnym zapłonem, stąd zwany też silnikiem Diesla. Z jego nazwiskiem związany też obieg diesla. Język DIESEL wykorzystywany w AutoCAD-zie, oczywiście nie ma nic wspólnego z twórcą silnika wysokoprężnego - jego nazwa powstała z połączenia pierwszych liter terminu:
Direct Interpretively Evaluated String Expression Language, co możemy (bardzo swobodnie) przetłumaczyć jako język wyrażeń łańcuchowych.
Niestety wśród użytkowników AutoCAD-a, panuje ogólne przekonanie, że nadaje się on tylko do modyfikacji linii stanu (poprzez zmienną MODEMACRO) i do zastosowań w menu. Z tego też powodu wielu użytkowników AutoLISP-u, niedocenia możliwości które oferuje nam ten język w programach lispowych. W rzeczywistości menu i modemacro, są głównymi obszarami zastosowania języka DIESEL, wskażę jednak też inne możliwości wykorzystania go w wyrażeniach AutoLISP-u. W praktycznym zastosowaniu, spotkałem się często z problemami, których rozwiązanie przy wykorzystaniu tylko AutoLISP-u, było bardzo skomplikowane. W niektórych sytuacjach osiągnięcie pewnego celu jest łatwiejsze (a niekiedy w ogóle możliwe) stosując DIESEL zamiast AutoLISP. Pomijając teraz zagadnienia związane z formatowaniem linii stanu i menu (są to tematy na tyle obszerne, że wymagają osobnego omówienia), zajmiemy się wykorzystaniem wyrażeń języka DIESEL w AutoLISP-ie.
Wartości wyrażeń języka DIESEL są wyznaczane w programach AutoLISP za pomocą funkcji menucmd. Choć funkcja ta ma jeszcze szereg innych zastosowań (odczyt stanu pozycji menu i wydawanie poleceń menu), w tej chwili interesuje nas tylko zastosowanie jej dla wyrażeń łańcuchowych DIESEL. Funkcja wymaga podania jednego argumentu (łańcucha tekstowego), który określa obszar menu i przypisaną mu wartość. W naszym przypadku wywołanie funkcji ma zawsze postać:
(menucmd "M=DOWOLNE_WYRAŻENIE_JĘZYKA_DIESEL")
czyli wartość argumentu musi zaczynać się od znaków "M=", a w dalszej części należy umieścić poprawne wyrażenie języka DIESEL. Ponieważ argument funkcji jest łańcuchem tekstowym, do jego formatowania, będziemy używać również funkcji strcat. Prezentowane w dalszej części funkcje zbudowane są według tego schematu. Wszystkie w podobny sposób wykorzystują możliwość AutoLISP-u do wykonania instrukcji języka DIESEL.

»  Podział łańcucha tekstowego na podłańcuchy

Użyteczna funkcja służąca do podziału łańcucha tekstowego na listę łańcuchów, gdzie separatorem jest przecinek. Wykorzystuje wyrażenie index zwracające określoną pozycję z łańcucha eleentów rozdziełonych przecinkami. Kolejne pozycje (zmienna inc) przypisywane są zmiennej tmp, które tworzą listę Res. Odwrócona lista (po odrzuceniu jej ostatniego elementu - łańcucha pustego) jest wynikiem działania funkcji. Przedstawiona funkcja może przydać np. podczas odczytu danych z pliku tekstowego. Tutaj jest również wykorzystywana do tworzenia list z łańcucha, będącym wynikiem działania innych wyrażeń DIESEL. Dodam że jest to jedna z najkrótszych funkcji z mojej kolekcji, służących do tego celu.

;; 1999 by kojacek                                                    ;;;
;; Funkcja zwraca listę łańcuchów tekstowych dzieląc  argument STR na ;;;
;; podłańcuchy. Separatorem łańcucha jest znak ",". UWAGA! - argument ;;;
;; [STR] nie może być łańcuchem w którym występują separatory jeden   ;;;
;; za drugim.                                                         ;;;
(defun jk:CON_Str->List (Str / inc tmp res)
  (setq inc 0)
  (while
    (/= tmp "")
    (setq tmp
      (menucmd
        (strcat "M=$(index," (itoa inc) ",\"" Str "\")")
      )
      inc (1+ inc)
    )
    (setq res (append (list tmp) res))
  )
  (reverse (cdr res))
)  
Przykład: (jk:CON_Str->List "AutoLISP,Diesel,AutoCAD,14")
zwraca listę: ("AutoLISP" "Diesel" "AutoCAD" "14")

»  Aktualna data

Bardzo krótka funkcja zwracająca listę łańcuchów tekstowych reprezentujących aktualną datę systemową. Lista składa się z rzymskiego numeru miesiąca, nazwy miesiąca, arabskiego numeru miesiąca, dnia, roku oraz nazwy dnia tygodnia. Nazwy dnia tygodnia i miesiąca zwracane są w języku w którym zlokalizowano AutoCAD-a.

;; 1999 by kojacek                                                    ;;;
;; Zwraca liste łańcuchów tekstowych reprezentujących aktualną        ;;;
;; datę o formacie: MM-rzym Miesiąc DD MM YYYY DzieńTygodnia          ;;;
;; Wymaga funkcji jk:CON_Str->List                                    ;;;
(defun jk:SYS_TodayList (/ Date Mont)
  (setq Date
    (jk:CON_Str->List
      (menucmd
        (strcat
          "M=$(edtime,$(getvar,date),MONTH"
          "\",\"MO\",\"DD\",\"YYYY\",\"DDDD)"
        )
      )
    )
  )
  (setq Mont
    (menucmd
      (strcat "M=$(index,"
              (itoa (1- (read (nth 1 Date))))
              ",\"I,II,III,IV,V,VI,VII,VIII,IX,X,XI,XII\")"
      )
    )
  )
  (cons Mont Date)
)
Przykład: (jk:SYS_TodayList)
zwraca: ("IV" "Kwiecień" "04" "18" "2000" "Wtorek")
Listę taką można następnie wykorzystać w programie lispowym formatując datę w zależności od potrzeb. Praktycznie można zastosować funkcję w wszelkiego rodzaju programach tworzących zestawienia lub raporty z rysunku AutoCAD-a w plikach tekstowych, procedurach wypełniajacych tabliczki rysunkowe itd. - wszędzie tam gdzie potrzebna jest aktualna data. Dodać należy że wykorzystując tylko funkcje AutoLISP-u, aby otrzymać nazwę dnia tygodnia, należałoby napisać dość pokaŸną funkcję, język DIESEL "załatwia" to w jednej linijce kodu!

»  Aktualny czas

Funkcja bardzo podobna co prezentowana powyżej - tym razem zwraca listę łańcuchów tekstowych reprezentujących aktualny czas: godziny, minuty, sekundy i milisekundy. Funkcja wygląda tak:

;; 1999 by kojacek                                                    ;;;
;; Awraca liste łańcuchów tekstowych reprezentujących aktualny czas:  ;;;
;; Wymaga funkcji jk:CON_Str->List                                    ;;;
;; Zwraca listę formatu: ("HH" "MM" "SS" "MSEC")
(defun jk:SYS_CurTime ()
  (jk:CON_Str->List
    (menucmd
      "M=$(edtime,$(getvar,date),HH\",\"MM\",\"SS\",\"MSEC)"
    )
  )
)
Przykład: (jk:SYS_CurTime)
zwraca: ("20" "06" "53" "326")
Analogicznie jak dla poprzedniej funkcji po uzyskaniu tego typu listy, można na jej podstawie dowolnie formatować łańcuch tekstowy reprezentujący aktualny czas.

»  Zmienne systemowe

Zmienne systemowe AutoCAD-a służą do przechowywania szeregu wartości liczbowych, list i łańcuchów tekstowych, odzwierciedlających różne stany pracy programu i ustawień rysunku. W programach lispowych często zachodzi konieczność uzyskania wartości zmiennej systemowej w postaci łańcucha tekstowego. Dotyczy to programów wykorzystujących okna dialogowe, podczas wypełniania wycinków typu okienko edycyjne, tworzenia list rozwijalnych, ustawiania przełączników itd., oraz np. dynamicznego tworzenia linii poleceń. Choć problem nie wydaje się specjalnie skomplikowany - jednak użytkownik każdorazowo musi dokonywać konwersji danych. Wykorzystując właściwości języka DIESEL (operującym przecież tylko na łańcuchach tekstowych), napisałem funkcję, zwracającą wartość dowolnej zmiennej systemowej AutoCAD-a w postaci łańcucha tekstowego. Funkcja przedstawiona jest poniżej:

;; 1999 by kojacek                                                    ;;;
;; Funkcja zwraca wartość zmiennej systemowej VAR jako string         ;;;

(defun jk:CON_GetvarAsStr (Var)
  (menucmd
    (strcat
      "M=$(getvar,\"" Var "\")"
    )
  )
)
Przykłady:
(jk:CON_GetvarAsStr "APERTURE") zwraca: "3"
(jk:CON_GetvarAsStr "OSMODE") zwraca: "183"
(jk:CON_GetvarAsStr "CDATE") zwraca: "20000418.2015435"
(jk:CON_GetvarAsStr "LIMMAX") zwraca: "420,297"
natomiast:
(jk:CON_Str->List (jk:CON_GetvarAsStr "LIMMAX"))
zwraca: ("420" "297")
W wielu sytuacjach wykorzystanie tego "konwertera" jest niezwykle wygodne. Funkcja realizująca to samo zadanie, lecz nie wykorzystująca wyrażeń DIESEL, byłaby z pewnością wielokrotnie dłuższa.

»  Zakończenie

W ten sposób zakończył się krótki przegląd kilku zastosowań języka DIESEL w AutoLISP-ie. Na pewno nie wyczerpują one całkowicie tematu. Mam nadzieję że przykłady te przybliżyły Czytelnikowi pewne techniki programowania w języku AutoLISP, zwłaszcza na niedoceniane (niestety) możliwości języka DIESEL. Dzięki swojej prostocie wyrażenia DIESEL mogą w znaczący sposób zmniejszych długość programów lispowych, wykonujących takie same zadania. Mam nadzieję że po przeczytaniu tych słów DIESEL zyska (odzyska) uznanie wśród użytkowników AutoCAD-a i AutoLISP-a.
  O zmiennej MODEMACRO jest jeszcze tutaj: [9] Linia stanu
  Tekst ten napisałem i publikowałem na tych stronach w 2000 roku. Aktualizacja (i skróty): 29-10-2009