| |
Title: comp.cad.autocad AutoLISP FAQ
Archive-name: CAD/autolisp-faq
URL: http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html
Version: 2.28
Last-modified: "2001-06-18 13:39:42"
Posted-By: Reini Urban <rurban@x-ray.at>
Posting Frequency: monthly
Copyright: see Appendix [A]
Zapraszamy do lektury! AutoLISP - Lista Często Zadawanych Pytań
AutoLISP jest językiem programowania interpretowanym w środowisku AutoCAD-a,
znanego pakietu CAD. Lista AutoLISP FAQ <* anglojęzyczny oryginał niniejszego
dokumentu *> jest co miesiąc rozsyłana do uczestników następujących list
dyskusyjnych: comp.cad.autocad, alt.cad.autocad oraz *.answers.
Kilka dokumentów typu FAQ można znaleźć na stronie
http://www.autodesk.com/support/autocad/ ale nie są one rozsyłane na listę comp.cad.autocad.
Treść tego dokumentu oraz załączone przykłady odnoszą się do wszystkich wersji AutoLISP-u, począwszy od wersji 10, włączając Visual LISP, Vital LISP oraz ACOMP.
Nie istnieje lista dyskusyjna dotycząca wyłącznie AutoLISP-u. Najlepszymi są comp.cad.autocad oraz autodesk.autocad.customization, ale nie warto zawracać sobie głowy comp.lang.lisp!
Kody źródłowe wszystkich funkcji przywołanych w tym dokumencie znajdują się w FAQ-CODE.LSP (zobacz [A.1]).
Dziękuję wszystkim zaangażowanym w tworzenie tego dokumentu. Poprawki i uzupełnienia proszę wysyłać
na adres rurban@x-ray.at, są one zawsze mile widziane.
Proszę o zapoznanie się z Netykietą: AcadWiki:RulesToLiveBy.
(oznaczenia: | zmiany,
+ nowe elementy w stosunku do poprzedniej wersji, <..> prywatne komentarze oraz wątpliwości).
<* W języku polskim można dyskutować o AutoLISP-ie na www.cad.pl oraz pl.comp.cad,
a tłumaczenie Netykiety znajduje się na stronie http://republika.pl/orzechp/netykieta.html. *>
- Część 1: Ogólna
- [0] Jaka jest przyszłość AutoLISP-u? Czy nie lepiej zamiast niego uczyć się VB?
- [0.1] Co się zmieniło z wprowadzeniem AutoCAD-a 2000?
- [0.2] Czy nie można już kompilować ARX?
- [1] Gdzie w Internecie można znaleźć procedury LISP?
- [1.1] Czy są gdzieś przechowywane artykuły z grupy dyskusyjnej comp.cad.autocad?
- [1.2] SDK Autodesku
- [2] Jakie są najlepsze książki do nauki AutoLISP-u?
- [2.1] Dokumentacja AutoLISP-u Online, Winhelp [usunięte w wersji rozsyłanej]
- [2.2] Styl pisania kodu AutoLISP
- [3] Jak sprawdzać poprawność programów AutoLISP?
- [3.1] Debuggery dla klasycznego AutoLISP-u
- [3.2] Styl strukturalny, TRACE
- [3.3] Do swojego kodu źródłowego możesz dołączyć funkcje BREAK oraz debug-print
- [4] W jaki sposób zabezpieczyć swoje programy LISP? Ochrona kodu
- [4.1] Kelvinator
- [4.2] Protect
- [4.3] Kelvinator i Protect
- [4.4] Convert
- [4.5] ACOMP
- [4.6] Vital LISP Professional
- [4.7] Lisp2C
- [4.8] Visual Lisp Autodesku
- [5] Kompilatory AutoLISP
- [5.1] ACOMP
- [5.2] Vital LISP Professional
- [5.3] Visual Lisp Autodesku
- [5.4] Najlepsze: Common LISP oraz Scheme
- [6] Edytory i inne narzędzia AutoLISP
- [6.1] Edytory AutoLISP
- [6.2] Analizatory kodu, pakowacze oraz kontrolery nawiasów
- [6.3] Formatery kodu
- [7] Problemy i błędy interpretera AutoLISP [dodane]
- [8] Sortowanie w AutoLISP-ie [dodane]
- [9] Rekursja
- [10] Iteracja funkcją MAPCAR...
- [11] Moje lispy nie są już wczytywane automatycznie podczas uruchamiania AutoCAD-a [poprawione]
- [12] Jak automatycznie wczytywać swoje programy?
- [13] W jaki sposób wprowadzić zmienną liczbę argumentów do funkcji LISP?
- [14] W jaki sposób zapobiec przepełnieniom stosu? [zmiany]
- [15] (command "ROTATE3D") nie działa! Dlaczego?
- [16] Programy LISP działające na wielu rysunkach
- [17] W jaki sposób wyeksportować funkcję Visual LISP-u do środowiska AutoLISP lub AutoCAD?
- Część 2: Przykłady, kod
- [20] Ogólne funkcje pomocnicze
- [20.1] Operacje na listach
- [20.2] Operacje na łańcuchach
- [20.3] Zamiana nazwy symbolu na łańcuch
- [20.4] Dostęp do entycji AutoCAD-a [zamiana nazwy SSAPLY na SSMAP]
- [21] Przykłady programów LISP:
- [21.1] Globalna zmiana właściwości tekstów, polilinii, funkcje obsługi warstw, datownik wydruków z plotera
- [21.2] Okienko dialogowe plotowania z poziomu LISP. Użycie DDE oraz ActiveX
- [21.3] Funkcje (entmod) oraz (entmake). Obsługa warstw bez użycia (command "_LAYER"...). Modyfikacja warstwy (ENTMOD)
- [21.4] Jak wybrać wiele plików w programie LISP?
- [21.5] Zamiana bloków
- [21.6] Funkcja (vports), entycja VIEWPORT, konwersja współrzędnych ekranu na współrzędne modelu
- [21.7] Wybór wszystkich widocznych obiektów, współrzędne narożników
- [21.8] W jaki sposób zapisać do pliku listę współrzędnych XYZ dla zbioru wskazanych obiektów?
- [22] Atrybuty bloków
- [22.1] W jaki sposób uzyskać dostęp do danych definiujących atrybuty bloków?
- [22.2] W jaki sposób zmodyfikować atrybuty bloku? DATESTAMP.LSP
- [22.3] W jaki sposób uaktualnić atrybuty bloku?
- [22.4] W jak sposób utworzyć blok z atrybutami funkcją ENTMAKE?
- [23] Polilinie
- [23.1] W jaki sposób uzyskać dostęp do danych definiujących wierzchołki polilinii?
- [23.2] W jaki sposób połączyć wiele linii w polilinię? [poprawione]
- [23.3] Zmiana szerokości polilinii
- [23.4] Tworzenie polilinii oraz splajnu funkcjami ENTMAKE oraz COMMAND
- [23.5] W jaki sposób obliczyć długość polilinii?
- [23.6] W jaki sposób odwrócić kierunek polilinii?
- [23.7] W jaki sposób odczytać środek polilinii? [nowe]
- [24] Geometria okręgu i łuku: definicja wypukłości (BULGE), nieco trygonometrii [poprawione]
- [25] DCL: okna kartotekowe ze znakami tabulacji oraz czcionką o stałej szerokości
- [26] EED. Dane rozszerzone elementu: odczyt i zapis
- [26.1] Wybieranie obiektów na podstawie ich EED funkcją (ssget "X")
- [26.2] Odczyt EED wybranego obiektu
- [27] HW jaki sposób przerwać wykonywanie polecenia w LISP-ie?
- [27.1] W jaki sposób wykonać nieograniczoną liczbę opcji wprowadzonych przez użytkownika?
- [28] W jaki sposób rozkodować geometrię ACIS w LISP-ie?
--
- [A] Zastrzeżenia, uwagi od autorów
- + [A.1] Lokalizacja FAQ
- [B] Podziękowania
- [C] Ostatnie zmiany
AutoLISP z pewnością będzie obsługiwany w przyszłych wersjach AutoCAD-a. VB został wprowadzony,
aby uprościć interfejs Office Automation, umożliwiający komunikację między AutoCAD-em a
Excelem lub Accessem.
Oba języki mają zalety i wady. Powinieneś zapoznać się z oboma.
VB sprawia wrażenie bardziej ukierunkowanego graficznie, a AutoLISP bardziej logicznego.
Obiektowa koncepcja VBA wydaje się łatwiejsza do nauki, ale nie będziesz mógł uruchamiać poleceń tak jak w AutoLISP-ie.
Nowy VBA (od R14.01) jest niezwykle szybki. Zobacz też [5.2].
Przyszłością AutoLISP-u jest niewątpliwie Visual LISP.
Odnośniki: www.autodesk.com/vlisp,
www.autodesk.com/develop/devres/visual/faq.htm,
także [0.1] poniżej.
Przede wszystkim nazwa :). Nie, tak naprawdę coś więcej, ale możesz nazywać ten program Wydaniem 2000, R15 (mimo że "15"
jest numerem wersji, a nie numerem wydania), A2000 lub w skrócie A2K.
Nowe jądro Visual LISP zastąpiło stare, oparte na XLISP-ie jądro AutoLISP.
Jakich problemów powinieneś się spodziewać w związku z Visual LISP-em w R2000? Mam wyłącznie "złe" wieści.
Na stronie xarch.tu-graz.ac.at/autocad/docs/r2000-news.txt
umieściłem odpowiednią dokumentację. Użyj LCA aby sprawdzić swoje lispy.
Najważniejsze różnice to:
- dokładniejsze sprawdzanie błędów podczas wczytywania;
- ACAD.LSP vs ACADDOC.LSP;
- brak konieczności kompilacji do ARX;
- niezgodności pomiędzy AutoLISP-em a Visual LISP-em:
- funkcje LISP są teraz atomami, a nie listami,
- w Visual LISP-ie symbole są chronione;
- lepsza obsługa wyjątków;
- ścieżka wczytanego VLX?;
- vl-export-symbol zastąpiono przez vl-doc-set...;
- tablica długich nazw symboli AutoCAD-a - EXTNAMES;
- interfejs ActiveX Automation, zmienne typu Variant oraz SAFEARRAY;
- FAS4 nie może być wczytany do R14.
W AutoCAD-zie 2000 nie możesz zrobić więcej, niż mogłeś w ViLL lub VLISP 4.
Natomiast możesz kompilować programy do VLX (Visual LISP Extension), który
ma w zasadzie taki sam zakres funkcjonalności jak stare ARX w Visual
LISP-ie i Vital LISP-ie, z następującymi różnicami:
- Możesz wczytywać program poleceniem (load). Wcześniej robiłeś to poleceniem (arxload).
- Zaleta: inicjalizacja jest łatwiejsza. Wczytywanie VLX nie jest przerywane,
nawet w przypadku wystąpienia błędu podczas tego procesu. Wcześniej cała
aplikacja ARX mogła się zawiesić z powodu różnych błędów.
- Zaleta: VLX jest znacznie mniejszy, ponieważ nie musi zawierać całego środowiska LISP,
wraz z VLRTS. Zamiast tego istnieje tylko jedno środowisko, VL.ARX, zawarte w samym acadzie.
Dzięki temu możesz rozprowadzać znacznie mniejsze aplikacje.
- Wada: po wczytaniu VLX nie ma łatwego sposobu odczytania ścieżki
dostępu do aplikacji. Wcześniej było to możliwe za pomocą funkcji (arx)
lub (vl-exe-filename).
- VLX posiada opcję oddzielnej lub wspólnej przestrzeni nazw. Poprzez
oddzielne aplikacje ARX mogłeś używać wyłącznie oddzielnych przestrzeni nazw
(w rzeczywistości były to odrębne środowiska LISP).
- Zaleta: to oznacza, że teraz możesz wybierać między szybszym a
bezpieczniejszym trybem kompilacji (LINK, DROP) i nadal zachowywać wspólną przestrzeń
nazw. (Większość moich aplikacji korzysta z tego. Dzięki temu mogę dzielić aplikację na
jeden główny moduł i kilka mniejszych).
- Zaleta: ARX jest zgodny tylko z jednym wydaniem, czyli zupełnie niekompatybilny!
VLX jest nowy i dlatego zgodny jedynie z nowszymi wydaniami (R16, ...), ale
jako aplikacja LISP jest znacznie bardziej kompatybilny niż aplikacja ARX.
- Funkcja (arx) wczytująca aplikację ARX zwracała ścieżkę dostępu do aplikacji,
funkcja (vl-list-loaded-vlx) wczytująca aplikację VLX zwraca jedynie symbol, nie
ścieżkę. Jest to wada projektowa.
Nie potrzebujesz już plików ARX. To jest cecha, nie błąd.
Interesujące strony z narzędziami dla AutoCAD-a to:
- AutoCAD Plugin Store prowadzona przez beyond.com:
- www.cadplugins.com/
Jest to strona "oficjalnie rekomendowana" przez Autodesk.
- CADalog - The AutoCAD Shareware Clearinghouse (Mike Clark):
- www.cadalog.com/
- The CAD Depot, dawniej znana jako CADSyst (David Whynot):
- www.caddepot.com/,
ostatnio kupiona przez TenLinks.
Serwisy te specjalizują się w oprogramowaniu związanym z AutoCAD-em i posiadają godne polecenia
kolekcje AutoLISP-u. Inne profesjonalne strony z programami shareware AutoLISP również przysłały
swoje adresy na grupę dyskusyjną.
Inne strony portalowe o podobnej tematyce to: [nowość]
TenLinks oraz
UpFront EZine są najlepszymi serwisami
ogłoszeń dotyczących tematyki CAD.
Autodesk uruchomił portal Point A.
Niektóre inne strony z kolekcją programów AutoLISP to:
-
xarch AutoCAD Info & Tools (Reini Urban)
- xarch.tu-graz.ac.at/autocad/
(z wyszukiwarką)
-
CAD Users Webring [nowość]
-
CADalyst magazine code (przygotowany przez "Hot Tip Harry" Art Liddle)
- www.cadonline.com/code/
-
Owen Wengerd
- www.manusoft.com
-
Terry Dotson
- www.dotsoft.com/
-
AcadX [nowość]
- www.acadx.com
-
Paul Turvill [nowość]
- www.turvill.com/t2/
-
Vladimir Nesterowsky
- members.tripod.com/
-
Theo L.A. Groenenberg
- http://members.xoom.com/acadvice/autolisp.htm
-
The CADshack (Jeff Foster)
- www.cadshack.com/lispfile.htm
-
Lisp Factory (Jay Garnett)
- www.enteract.com/~jgarnett/
-
Rakesh Rao - AutoCAD Tech Center
- www.4d-technologies.com/techcenter
Stare oraz nieaktualne odnośniki:
-
AutoCAD Tech Journal code (Peter Sheerin) [stary]
- www.atj.com
-
CADENCE magazine code (Peter Sheerin) [stary, nieaktualny]
- www.cadence-mag.com/
-
UCCB AutoCAD and AutoLISP page (Paul Standing)
- ucad1.uccb.ns.ca/acad/cad.htm
-
Dr.Lisp Utilities (Alexander Medwedew) [poprawiony]
- idt.net/~compvent/
-
McNeel's lisp archive [nieaktualny]
- ftp://ftp.mcneel.com/lisp/
-
Desi Moreno [nieaktualny]
- www.invsn.com/desmos/autolisp.htm
-
PIRS Online
- www.insa.com/
-
Henry Francis [poprawiony]
- paracadd.com/
-
SimTel - Coast To Coast - Archive [poprawiony, bardzo stary]
- www.simtel.net/pub/msdos/autocad.html
Na www.autodesk.com/support/autocad/ znajdują się dokumenty Autodesk Product Support, zawierające odpowiedzi na pytania techniczne (ich listy FAQ).
ASA (Aurodesk Support Assistance, rodzaj FAQ) znajdujące się do tej pory na stronie www.autodesk.com/support/autocad/asa2000.htm, teraz funkcjonuje jako poprawiona (ale nadal powolna) baza danych support.autodesk.com/KnowledgeBase.asp
Nie istnieje archiwum grupy comp.cad.autocad ani nic podobnego, ale niektóre wyszukiwarki przechowują artykuły usenetu. W szczególności:
- groups.google.com/ -
największe archiwum usenetu.[nowość]
- Dawniej znane jako deja.com/usenet.
- www.altavista.com/
- www.altavista.com/cgi-bin/query?pg=aq&what=news
- www.excite.com/
- www.excite.com/search.gw?collection=news
- Phoaks - People Helping One Another Know Stuff - automatyczny wyszukiwacz odnośników
- www.phoaks.com/phoaks2/newsgroups/comp/cad/autocad/index.html
Forum dyskusyjne Autodesku posiada własną wyszukiwarkę na stronie discussion.autodesk.com.
Niektóre (wybrane) stare artykuły są także przechowywane na stronie
xarch.tu-graz.ac.at/autocad/news/contents.html
Aż do wydania 12, Software Development Kit był dostępny wyłącznie bezpośrednio
w Autodesku. SDK2 był rozprowadzany z międzynarodowym R12 bez dodatkowych opłat.
Zawierał on sporo kodu źródłowego ADS i AutoLISP oraz biblioteki.
Od R13 Autodesk udostępnił specjalną sieć dla twórców aplikacji,
porównywalną z siecią Microsoftu - ADN. Zawartość płyt CD jest podobna
do starego SDK, ale bardziej ukierunkowana na programistów ObjectARX.
Skontaktuj się z najbliższym autoryzowanym przedstawicielem Autodesku, jeżeli chcesz zostać członkiem ADN.
Niektóre lispy są dostępne na stronie xarch.tu-graz.ac.at/autocad/code/adesk/SDK2/
W Stanach Zjednoczonych członkostwo w ADN kosztuje 600 dolarów rocznie. Płyty CD nie zawierają SDK jako takiego,
ale większość składników oryginalnego SDK znajduje się na nich w takiej czy innej postaci. (Owen)
- AutoLISP to Visual LISP [nowość]
- Kevin Standiford, Autodesk Press, ISBN 0-7668-1517
- AutoLISP: Programming for Productivity,
- William Kramer, Autodesk Press, ISBN 0-8273-5832-6
- Essential AutoLISP,
- Roy Harkow, Springer-Verlag, ISBN 0-387-94571-7
- AutoLISP in Plain English; A Practical Guide for Non-Programmers,
- George O. Head, Ventana Press, ISBN: 1566041406
- "Maximizing AutoLISP"
- Rusty Gesner, Tony i Mark Middlebrook, Tony Tanzillo.
More at www.group-a.com/~rusty/
- "AutoLISP Reference Manual"
- wydawane przez Autodesk Press.
Aż do R12 istniały oddzielne podręczniki AutoLISP. Przewodnik programisty. Później
AutoLISP stał się częścią Podręcznika adaptacyjnego dla R13. Od R14 dokumentacja ta
jest skompilowana jako Winhelp.
Ponadto istnieje całe mnóstwo książek o AutoLISP-ie.
Rekomendowanymi książkami dotyczącymi ogólnego języka LISP (nie AutoLISP-u!) są:
- ANSI Common Lisp, (Common Lisp primer)
- Paul Graham, Prentice Hall, ISBN 0-13-370875-6
- Structure and Interpretation of Computer Programs, (high-level Scheme)
- H.Abelson, GJ. Sussman, J. Sussman, MIT Press, ISBN 0-262-01153-0
- "Jest to niewątpliwie jedna z najlepszych książek o komputerach, jakie kiedykolwiek zostały napisane";
- LISP, 3rd Edition,
- Patrick Henry Winston and Berthold Klaus Paul Horn, Addison-Wesley Publishing Company, ISBN 0-201-08319-1
- Looking at LISP,
- Tony Hasemer, Addison-Wesley Publishing Company, ISBN 0-201-12080-1
R14 zawiera komplet dokumentacji w postaci Winhelp.
Pliki AutoLISP Winhelp są rozprowadzane z następującym oprogramowaniem:
- R14 (pełny pakiet dokumentacji);
- Visual LISP Autodesk wersja preview, zobacz [5.3]
- stary edytor Visual LISP (wersja 1.0 jest bezpłatna), zobacz [1]
- Vital LISP (pliki pomocy są zawarte również w wersji demonstracyjnej), zobacz [6.1]
Istnieje rezydentny program dla DOS-u, zwany LISPHLP.EXE
(uruchamiany przez Ctrl+PrawyShift+R, od 1988).
LSPDOC: na stronie xarch.tu-graz.ac.at/autocad/lsp_tools/#lspdoc lspdoc znajduje się narzędzie pozwalające na automatyczne tworzenie plików Winhelp dla programów LISP.
Większość przykładów publikowanych w magazynach lub na rozmaitych stronach
WWW jest napisanych niedbale, co dodatkowo utrudnia naukę AutoLISP-u
początkującym adeptom programowania. Zresztą LISP sam w sobie jest
trudny do czytania, z powodu jego zwięzłości i niezliczonych nawiasów.
Każdy jest zobowiązany do pisania czystego, czytelnego kodu. Przykłady
Autodesku są całkiem dobrze pisane, choć czasem aż do przesady :).
Automatyczne formatery kodu, tak zwane upiększacze (zobacz [6.3]) w sposób automatyczny formatują kod tak, aby spełniał wymagania standardu.
Na płycie CD R12, w pliku SDK2 ACG.DOC lub na
xarch.tu-graz.ac.at/autocad/docs/acg.txt
znajduje się dokumentacja Autodesku doskonale omawiająca zasady kodowania, komentowania i planowania kodu, aby pozostawał on czytelny.
Najważniejszymi zasadami są:
- Komentuj swój kod.
Używaj oznaczeń ;;; w pierwszym wierszu, ;; wewnątrz kodu oraz ; w celu
wyróżnienia komentarzy umieszczonych za komentowanym wyrażeniem (w wierszu 39.).
- Stosuj zasady planowania tak, jak to robią formatery, aby pisać kod w sposób
bardziej strukturalny, łatwiejszy w czytaniu, np. SETQ, DEFUN, IF, COND, PROGN.
- Staraj się unikać zmiennych globalnych. Jeżeli zdecydujesz się ich użyć
(ze względu na wydajność), oznacz je gwiazdkami i pisz je wielkimi literami, np.: *GLOBAL*.
- Nie zapominaj lokalizować swoich zmiennych (za znakiem "/" w liście
parametrów DEFUN). Jedynie na etapie sprawdzania programu tymczasowo możesz
pozostawić je jako niezadeklarowane.
- Chroń nazwy: ponieważ AutoLISP używa niechronionej przestrzeni nazw,
łatwo jest nadpisać nawet predefiniowane funkcje systemowe. Dlatego powinieneś
używać unikalnych krótkich prefiksów, przynajmniej wtedy, gdy publikujesz lub
udostępniasz innym swój kod.
Ja używam prefiksu UR- dla funkcji i UR: dla zmiennych. ADGE oraz Autodesk wymagają nawet 4 liter prefiksu. W ten sposób nazwy będą zabezpieczone przed nadpisaniem przez inne funkcje.
- Zawsze używaj znaku podkreślenia rozpoczynającego każdy łańcuch (nazwę polecenia lub opcji) przekazywany funkcji COMMAND lub OSNAP. Zdarzają się nawet komercyjne programy, które nie działają z wersjami narodowymi. Wywołanie funkcji
(command "_PEDIT" ss "_J") jest lepsze niż (command "PEDIT" ss "J").
- Nie używaj nadmiernie SETQ: LISP został zaprojektowany jako język czynnościowy, bez zmiennych. Istnieje wiele konstrukcji, które działają efektywnie na listach bez potrzeby przechowywania tymczasowych wartości w symbolach (zobacz przykłady kodu [21]...)
Jednakże dla czytelności i w celu sprawdzania kodu powinieneś zawsze używać przypisania do symboli.
- Stara zasada programowania LISP: dobra funkcja nie jest dłuższa niż 6 wierszy.
(LISP jest drugim chronologicznie językiem komputerowym, wprowadzonym przez Johna McCarthyego na MIT w roku 1958).
- Używaj CONS zamiast APPEND: trzy funkcje CONS i jedna REVERSE są lepsze niż jedna APPEND. Aby poznać cechy APPEND (ignorowanie NIL), zobacz w szczególności przykład zamieszczony przez Serge: REMOVE w [20.1] lub porównanie stylów w [23.1])
- Używaj języka angielskiego w nazwach symboli i komentarzach.
- Nie używaj T, MIN, MAX ani LAST jako nazw symboli! Są to funkcje systemowe!
Istnieją trzy debuggery:
- Visual Lisp i Vital LISP Professional mają je wbudowane w interfejs IDE (i te są najlepsze).
- ACOMP dla R10 był bezpłatny; możesz go nadal używać, ale wtedy możesz obsługiwać tylko funkcje AutoLISP-u R10, np. funkcji WCMATCH - nie.
- Ld, Ld, AutoLISP Debugger dla R14, R13c4 oraz R12/Dos, program z Czech (bezpłatny) - na www.cadstudio.cz/ftp.htm
Zobacz [5] Kompilatory AutoLISP.
Najlepszą metodą usuwania błędów programu jest pisanie swojego kodu w sposób dobrze
zaprojektowany, stylem strukturalnym, zawieranie poszczególnych zadań w osobnych
funkcjach oraz używanie zagnieżdżonego wywoływania funkcji. Pozwoli to na użycie
funkcji TRACE do zlokalizowania każdego błędu.
Przykład:
;;; Sprawdzanie poprawności funkcji
(defun break (s)
(if *BREAK*
(progn
(princ "BREAK>> (stop with )\nBREAK>> ")(princ s)
(while (/= (setq s (getstring "\nBREAK>> ")) "")
(print (eval (read s))))))) ;błąd usunięty od v1.3!
(defun dbg-print (s) ;akceptuje atomy i listy
(if *DEBUG*
(if (listp s)
(MAPCAR 'print s)
(print s))))
(defun C:DEBUG () (setq *DEBUG* (not *DEBUG*))) ;włącza i wyłącza znacznik
(defun C:BREAK () (setq *BREAK* (not *BREAK*)))
(defun CONT () (setq *BREAK* nil)) ;kontynuacja bez żadnego przerwania
;;;Przykład
(setq *BREAK* T *DEBUG* T)
(defun C:TEST ()
(foreach x '("1" "1.0" "1e-3")
(break "in foreach") ; Przerywa ewaluację, gdy znacznik *BREAK*
; jest włączony, możesz wpisać x
; i wartość zmiennej x jest wyświetlana,
; dopóki nie naciśniesz Enter.
(setq x (atof x)) ; Ten fragment kodu manipuluje zmienną x
(dbg-print x) ; To drukuje nową wartość x,
; jeżeli znacznik *DEBUG* jest włączony.
)
)
Command: TEST
BREAK>> (stop with )
BREAK>> in foreach
BREAK>> x
1.0
BREAK>> (CONT) ; Wyłącza znacznik break.
nil
BREAK>>
1.0
1.0
0.001
Możesz także wyłączyć wyświetlanie wyników sprawdzania poprawności w następujący sposób:
BREAK>> (setq *DEBUG* nil)
żeby wykonać większe pętle.
"Czy rzeczywiście je zabezpieczać? Jeżeli po prostu chcesz się podzielić swoimi programami
z przyjaciółmi, dlaczego nie udostępnić im kodu? Twój kod jest chroniony tak czy inaczej przez
prawo autorskie, nawet jeśli tego nie wyrazisz wprost. Współpraca z innymi może być wspaniałym
sposobem pozyskiwania nowych pomysłów i prowadzić do tworzenia lepszych aplikacji.
Niektóre z moich najlepszych programów zostały ulepszone przez moich przyjaciół, a ja
ulepszyłem niektóre ich programy." (Dennis)
- [4.1] Kelvinator
- KELV.EXE (na płycie CD R12 oraz na stronach internetowych [1])
Tak "zaszyfrowany" lisp możesz rozszyfrować dowolnym formaterem kodu. Jednak nazwy symboli (funkcji i zmiennych) nadal pozostaną zniekształcone, a komentarze zostaną utracone.
- [4.2] Protect
- PROTECT.EXE (na płycie CD R12 lub na stronach internetowych [1]). Pamiętaj, że istnieje program deszyfrujący. Za darmo.
- [4.3] Kelvinator oraz Protect
- Najpierw użyj Kelvinatora, następnie programu PROTECT. Za darmo.
- [4.4] Convert
- Program szyfrujący i deszyfrujący pliki LISP. Shareware. Autor: Maciej Łukasiewicz.
Pliki zaszyfrowane do postaci "Protected LISP" programem CONVERT nie mogą być rozszyfrowane innym programem,
ale tym samym - tak.
- [4.5] ACOMP
- Kompilator AutoLISP-u, ACOMP.EXE, na płycie CD R12 wydania międzynarodowego lub na stronach internetowych. Bezpłatny. Więcej dokumentacji do ACOMP-a na stronie
xarch.tu-graz.ac.at/autocad/bi4/
Zobacz też [5.1] Kompilatory AutoLISP.
- [4.6] Vital LISP Professional
- www.basissoftware.com/vill.htm
"ViLL". Przestarzały. Zobacz [5.2] Kompilatory AutoLISP.
- [4.7] Lisp2C
- Konwerter LISP do C, dla R12/R13/R14 Dos/Win (Watcom, Metaware, MSVC Libs).
Potrzebujesz licencji uprawniającej do korzystania z jakiegoś kompilatora C/C++.
www.basic.si
- [4.8] Visual Lisp by Autodesk
- "VLISP". To przyszłość. Zobacz [5.3]
Bezpieczeństwo plików FAS:
Swego czasu odbyła się dłuższa dyskusja na temat bezpieczeństwa plików FAS na obu grupach
dyskusyjnych. Najwyraźniej FAS może zostać zdekompilowany do czytelnego kodu źródłowego, ale
narzędzie, które to umożliwia, nie jest jeszcze dostępne w Sieci. Pogłoska niesie, że również
pliki MNC mogą być dekompilowane (od lat), ale to także nie zostało potwierdzone w Sieci.
Skonsolidowane i zamaskowane pliki FAS oraz VLX (kompilowane z opcją Optimized/Internal) są
podobne do tworzonych przez Kelvinator. Nazwy symboli, łańcuch i liczby są gorzej zabezpieczone
niż sam algorytm.
Podsumowane:
Poważne szyfrowanie jest możliwe jedynie za pomocą Vital LISP i jego następców.
Pliki LISP tworzone przez Kelvinator [4.1] są nieczytelne i szybciej się wczytują.
Pliki w formacie "Protected LISP" [4.2] mogą być łatwo odszyfrowane. Plik LISP
zaszyfrowany za pomocą CONVERT można odszyfrować jedynie za pomocą programu CONVERT.
Istnieją trzy kompilatory AutoLISP, lepsze być może będą używane w przyszłości.
Niektóre platformy LISP oraz Scheme obecnie obsługują ActiveX lub po prostu FFI.
- [5.1] ACOMP
- ACOMP był rozwijany aż do R12 jedynie w przypadku wersji międzynarodowych. Jest
on bezpłatny, ale nie działa z R13 ani z narodowymi R12/Win. Wynikiem kompilacji są
pliki *.BI4, które wymagają specjalnego rozszerzenia ACADL.EXP, dostarczanego jako ACADLC.EXP. Zobacz
xarch.tu-graz.ac.at/autocad/bi4/
Ostrzeżenia generowane przez kompilator są bardziej precyzyjne w zakresie lokalnych symboli
niż w przypadku ViLL lub VLISP.
- [5.2] Vital LISP Professional
- Był rozwijany przez Basis Software Inc. USA. Licencje uprawniające do bezpłatnego
korzystania z niego są dostępne w przypadku runtime-interpreterów
dla R12/R13/R14 DOS/Windows/NT.
Basis nie rozwija już Vital LISP. Zobacz także [6.1] i [4.6]
- [5.3] Visual LISP Autodesku
- VLISP 4 (dla R14), następca Vital LISP, jest zasadniczo tym samym, co ViLL 3.2. Różnice to
jedynie graficzny interfejs użytkownika, zmiany prefiksów nazw funkcji i
dokumentów: vill- => vlisp-, vlx- => vl-. Niektóre funkcje o prefiksie vlax- zawierają więcej myślników.
W AutoCAD-zie 2000 VLISP zastąpił interpreter starego AutoLISP-u. Zobacz [0.1]
VLX zawierają spakowane pliki FAS i opcjonalnie zasoby DCL używane przez R14/R15.
R15 FAS/VLX są niezgodne z poprzednimi wydaniami (FAS2 -> FAS4), ponieważ dodano nowe właściwości języka (oddzielne przestrzenie nazw).
- [5.4] Najlepsze: Common LISP oraz SCHEME
- Corrman Common LISP posiada wbudowaną możliwość obsługi ARX,
COM jest obsługiwany przez Allegro Common LISP 5, Lisp Works for Windows, a w przyszłości - także przez GambitC.
Poprzez FFI ("Foreign Function Interface") prawie każdy program LISP lub SCHEME może komunikować się z AutoCAD-em.
Pewna praca została wykonana z Corman LISP oraz ACL5, aktualnie tylko jeden komercyjny produkt używa ACL5 ("Design++" - Design Power).
Jeśli chcesz wiedzieć więcej, zobacz xarch.tu-graz.ac.at/autocad/bi4/.
Podsumowanie:
Kompilatory AutoLISP to kompilatory kodu binarnego wymagające własnego środowiska
runtime (AutoCAD 2000 używa obecnie VLISP i posiada wbudowane środowisko runtime).
Nie jest możliwe tworzenie za ich pomocą niezależnych aplikacji, chociaż ViLL oraz
VLISP (w wersji R14 i starszych) tworzyły samodzielne ARX. Zmienne są szyfrowane.
- Visual LISP Autodesku
- Zobacz [5.3].
Najlepsze i najbardziej rekomendowane narzędzie. Zawarte w AutoCAD-zie 2000, nie wymaga dodatkowych wydatków.
- Emacs dla NT
- Potężny edytor, dość trudny do opanowania, jednakże napisany (z możliwością dostosowania do własnych
potrzeb) w elispie - języku bardzo podobnym do AutoLISP-u. Przodek wszystkich edytorów.
Bezpłatny, dostępny na wszystkie platformy. Istnieje w dwóch odmianach: XEmacs oraz
GNU ntemacs.
Dostosowany do AutoLISP-u http://xarch.tu-graz.ac.at/autocad/lsp_tools/ntemacs.html
- Vital LISP został zastąpiony przez Visual LISP. Nie jest już dostępny. Zobacz:
[5.2] Kompilatory AutoLISP.
- LispLink 2000
- Commercial AutoLISP Editor with Syntax Highlight, Parenthesis
Komercyjny edytor AutoLISP z wyróżnianiem składni, sprawdzaniem nawiasów, menedżerem projektów, podglądem okienek dialogowych oraz obsługą Visual LISP-u i formatu FAS: www.caelink.com/.
- CodeMagic [nowość]
- Bezpłatny edytor tekstu z wyróżnianiem składni AutoLISP-u.
- Stare oprogramowanie:
- LispPad
- Edytor AutoLISP, napisany przez Tonyego Tanzillo.
- Visual Lisp (WSSW)
- Stary, mały edytor LISP dla Windows. Wesja 1.0 była nawet bezpłatna. Nie mylić z Visual LISP-em, który zastąpił AutoLISP jako język programowania. Tu chodzi po prostu o mały edytor. Zobacz
[1]
- WCEDIT 2.02
- Edytor ADS dla DOS R12, który potrafi samodzielnie ewaluować wyrażenia LISP, jest dostępny za darmo.
Zobacz [1]
- CODEKEY
- Stare komercyjne środowisko DOS IDE, zawierające formater kodu, posiadające możliwość szyfrowania i deszyfrowania "Protected LISP", Kelvinator <dostępny?>
- ALLY 3.0 oraz CADET
- Analizator i edytor LISP (shareware).
Zobacz [6.2]
- pred
- Bezpłatny, mały dosowy edytor wyróżniający nawiasy.
Dostępny na ftp://xarch.tu-graz.ac.at/pub/autocad/lsp_tools/pred.zip
Podobnym edytorem jest ADE.
- Edytory dla programistów takie jak MultiEdit Pro 7, WinEdit, E!, TextPad, UltraEdit lub PFE są także często używane.
- Wprawdzie nie oferują one kontroli składni LISP lub formatowania kodu, ale umożliwiają wyszukiwanie i zamianę (nawet wyrażeń regularnych) w wielu plikach naraz oraz konfigurowalne wyróżnianie składni.
Kontrolerów nawiasów nie trzeba już używać, ta funkcja jest wbudowana obecnie w edytory.
Analizatory generują raporty pokazujące zależności między funkcjami, drzewo wywołań i
odwrócone drzewo funkcji wywołujących. Pakowacze są używane do tworzenia bibliotek z
wielu różnych plików źródłowych, poprzez kopiowanie wszystkich potrzebnych funkcji.
Nie istnieje obecnie narzędzie do automatycznego wstawiania znaków podkreśleń w łańcuchach
nazw poleceń, ale R15 zawiera odpowiedni analizator kodu (LCA).
- Kompilator VLISP [5.3] analizuje (opcja: compile with full messages) oraz sprawdza nawiasy (Ctrl+Alt+C).
- Reini's AutoLISP Packager
- Dostępny na stronie xarch.tu-graz.ac.at/autocad/lsp_tools/#Packager
Pozwala tworzyć i przeglądać raporty zależności między funkcjami oraz odwrócone drzewo wywołań. Tworzy bibliotekę z plików źródłowych (program ten znany jest także pod nazwami "Packager" lub "Function Shaker").
- PEI's Findvars
- Pakowacz podobny do opisanego wyżej, lecz dodatkowo wskazuje, które symbole powinny zostać zadeklarowane jako lokalne
www.perceptual-eng.com
Ja osobiście używam właśnie jego oraz mojego własnego pakowacza.
- RapidLisp
- Analizator kodu dla R14 (shareware).
www.cps.de/cad/rapidlisp/
- AVC - AutoLISP Variable Collector
- Bezpłatny. Znajduje wszystkie zmienne, które powinny być zadeklarowane przez funkcję.
users.actcom.co.il/sysoft/vc.htm
- LCA - Autodesk's AutoLISP Compatibility Analyzer[nowość]
- Znajduje się na Migration CD. Pozwala uzyskać zgodność wskazanych plików AutoLISP (LSP) oraz plików menu (MNL) z AutoCAD-em 2000.
- ALLY30.ZIP (stare)
- Analizator LISP (shareware). Sprawdza składnię i drukuje raporty (drzewo zależności funkcji). Zobacz [1]
- lck21b.zip (stare)
- LCK Validator LISP 2.1b (graficzny)
- paran.zip (stare)
- Prosty
- PARNCH.ZIP (stare)
- Prosty
Istnieją także inne programy sprawdzające nawiasy w programach AutoLISP.
Zewnętrzne:
- FMT202S.ZIP
- Formater kodu LISP, DCL oraz FRM
- LB.EXE
- Formater kodu Autodesku.
Zawarty w SDK2 oraz w [1]. Występują problemy z długimi łańcuchami oraz nowymi stylami komentowania wyrażenia w samym wierszu.
- PPRINT.LSP
- Zawarty w SDK2 oraz w [1]
Wewnętrzne:
Visual LISP, Vital LISP, Emacs oraz Codekey zawierają wewnętrzne formatery, o ile się orientuję.
Użytkownicy AutoCAD-a 2000 oraz mniej doświadczeni użytkownicy Visual LISP-u powinni przeczytać rozdział [0.1].
Nie są znane poważne błędy AutoLISP-u. Interpreter języka jako taki (ACADL.EXE/.EXP, VLISP) działa bezbłędnie. Niektóre ograniczenia wynikają z natury AutoCAD-a, ActiveX oraz mechanizmu Proteus (DCL). Niektóre programy LISP z katalogu Support (np. DDMODIFY.LSP) czasami błędnie działają. Wszystkie błędy i ograniczenia Visual LISP-u są wymienione w pliku README.txt. Zawieszenia środowiska związane z reaktorami są spowodowane błędami AutoCAD-a.
Dwie nieoficjalne listy błędów są umieszczone na stronach:
www.cadonline.com/exclusive/bugs/bugwatchlist.htm (dłuższa);
www.dotsoft.com/buglist.htm (prywatna i krótsza).
- + LDATA wg Toma Bergera (VLISP dla R14 oraz A2000)
- Nie używaj LDATA nigdy. To może zniszczyć pliki DXF oraz DWG w A2000. Odczyt tych danych jest BARDZO utrudniony.
- PARY KROPKOWE w listach argumentów przesyłanych z AutoLISP-u do Visual LISP-u lub odwrotnie mogą spowodować utratę zewnętrznych nawiasów.
- Zobacz Visual LISP README (nieudokumentowane w Vital LISP-ie).
- JEDNOATOMOWE LISTY są zwracane niepoprawnie z ZEWNĘTRZNYCH APLIKACJI.
- Visual LISP nie potrafi odróżnić LISTY zawierającej pojedynczy atom (element) od pojedynczego atomu zwracanego przez zewnętrzną aplikację ARX lub ADS.
- ENTGET użyte wobec LWPOLYLINE, HATCH (tylko R14)
- TWspółrzędna Z (caddr (getval 10 ele)) ma wartość losową i często powoduje wyjątek w obsłudze liczb rzeczywistych, ponieważ może mieć zbyt małą lub zbyt dużą wartość.
Rozwiązanie (obejście) problemu: zobacz część II, pozycja [23.1]
- ENTMAKE VERTEX (tworzenie wierzchołków polilinii) wg Terry Dotson (tylko R14)
- Problem występuje podczas tworzenia (entmake) polilinii. Podczas tworzenia definicji wierzchołków (VERTEX) wymagane jest przypisanie im odpowiedniej warstwy (co dokumentuje Autodesk), ale także konieczne jest przypisanie warstwy do końcowej subentycji SEQEND. Pominięcie tego ostatniego spowoduje, że SEQUEND zostanie umieszczone na warstwie bieżącej. Jeżeli zamrozimy później tę warstwę, próba dostępu do tak utworzonej polilinii (np. próba przesunięcia) spowoduje błąd podczas odświeżania rysunku i zawieszenie się AutoCAD-a (wyłącznie R14).
- ACAD_STRLSORT: dziwna kolejność sortowania w Windows.
- Znaki w Windows nie są sortowane na podstawie odpowiadających im numerów ASCII! Zamiast tego użyta jest aktualna strona kodowa (getvar "SYSCODEPAGE"), co daje inny rezultat.
Windows: (acad_strlsort '("-1" "+1")) -> ("-1" "+1"),
DOS: (acad_strlsort '("-1" "+1")) -> ("+1" "-1")
W obu przypadkach: (mapcar 'ascii ("-" "+")) -> (45 43)
Więcej na stronie xarch.tu-graz.ac.at/autocad/docs/strlsort-bug.html
- AI_PROPCHK
- W dodatku uaktualniającym R13c3 zmieniono nazwę funkcji (ai_propchk) na (C:AI_PROP).
"Funkcja AutoLISP ai_propchk została zmieniona na c:ai_prop, tak aby zachowywała się podobnie do innych poleceń. To pozwala na powrót do polecenia DDMODIFY przez naciśnięcie ENTER, nawet jeżeli zostało ono wcześniej wybrane z paska narzędzi."
- Błędne zakończenie funkcji obsługi DCL w R13 powoduje zawieszenie AutoCAD-a
-
R13 zawiera usterkę, która powoduje zawieszenie AutoCAD-a, jeżeli wystąpi błąd krytyczny podczas wykonywania funkcji AutoLISP obsługującej suwak DCL w okienku dialogowym. Na przykład, jeżeli funkcja obsługi suwaka będzie zawierała wywołanie pustej (nieistniejącej) funkcji, AutoCAD zawiesi się natychmiast.
Z technicznego punktu widzenia nie jest to błąd interpretera AutoLISP-u, ale traktujemy go jak błąd AutoLISP-u.
- Od R13 nie możesz już polegać na wartości 64 kodowanej bitowo w znaczniku 70 w tablicy symboli, w przeciwieństwie do wcześniejszych wydań.
Co jeszcze? Zobacz nieoficjalną listę błędów AutoCAD-a utworzoną przez Stevea Johnsona, opisującą więcej błędnych programów i zachowań AutoLISP-u, na stronie
www.cadonline.com/exclusive/bugs/bugwatchlist.htm
(szczególnie: 33, 124, 126, 127, 139, 153, 158, 165, 176, 182, 192, 193, 238, 240, 254, 272, 295)
- Pliki w formacie "Protected LISP"
-
W wersjach wcześniejszych niż R13c4 pliki zaszyfrowane w formacie "Protected LISP" nie pozostawały zaszyfrowane po wczytaniu do pamięci. Naszym zdaniem ten problem powinien być znany wszystkim, aby nikt nie zakładał nierozważnie, że jego tak zabezpieczony kod jest chroniony przed wścibskimi oczyma.
Ten temat FAQ spowodował duży problem na moderowanym Forum AutoCAD-a w sieci CompuServe. Ale można tam znaleźć dobre metody zabezpieczeń. Zobacz [4].
- Ograniczona liczba otwartych zbiorów wskazań
-
Zbiory wskazań są na bieżąco przechowywane w plikach tymczasowych. Odczytanie niepotrzebnych zbiorów wskazań i przypisanie ich do symbolu NIL oraz uruchomienie (gc), gc = garbage collector spowoduje zamknięcie tych plików.
Maksymalna liczba zależy od systemu operacyjnego, np. w DOS-ie od wartości zmiennej FILES w CONFIG.SYS.
W R13 liczba ta została zwiększona.
- Liczby: zakres, dokładność, precyzja
-
Liczby całkowite są wewnętrznie reprezentowane jako typ "long fixnums" (32-bitowo, z bitem znaku), ale podczas przekazywania z AutoLISP-u do AutoCAD-a są zamieniane na 16-bitowy typ "short fixnums", o zakresie -32768 ... +32767, ponieważ AutoCAD posługuje się tylko typem "short fixnums".
Liczby rzeczywiste są typu "double" (64-bitowe IEEE). Wszystkie wewnętrzne obliczenia numeryczne AutoLISP-u oraz AutoCAD-a są wykonywane na liczbach formatu "double", co powinno być wystarczające. Co najmniej 14 cyfr jest dokładnych.
Powszechnym problemem jest niejednoznaczność między liczbą rzeczywistą a jej reprezentacją w postaci łańcucha (który odpowiada wartości zaokrąglonej). Liczby wyświetlane w linii poleceń są zawsze łańcuchami odpowiadającymi zaokrąglonym wartościom w zależności od LUPREC i DIMZIN.
Ze względu na to, że w trakcie porównywania geometrii często występuje błąd zaokrąglenia, należy do porównywania punktów używać dodatkowego współczynnika szumu (fuzz) o wartości [1e-12 - 1e-6]: (equal pt1 pt2 1e-6) ; 0.000001 tolerancja na błąd zaokrąglenia zamiast (equal pt1 pt2), szczególnie gdy dotyczy to porównywania kątów.
Zobacz www.autodesk.com/support/techdocs/td30/td301207.htm
VB: Jak to ostatnio zgłoszono, w zależności od wczytanych plików interfejsu Automation, dokładność obliczeń numerycznych oraz ustawienia lokalne separatora dziesiętnego (, lub .) powodują niepożądane efekty uboczne. Rozwiązanie oraz wytłumaczenie problemu jest w toku (dotyczy głównie krajów używających przecinka jako separatora dziesiętnego, jak Polska czy Niemcy) .
- Funkcja (EQ)jest bardziej dosłowna w kompilatorze ACOMP
- W przypadku kodu kompilowanego za pomocą [5.1] ACOMP's trzeba uważać na to,
że zachowanie funkcji (EQ) w plikach BI4 jest znacznie bardziej dosłowne niż w
zwykłym AutoLISP-ie. W AutoLISP-ie (eq "1" "1") zwraca T, podczas gdy kod skompilowany przez ACOMP zwraca NIL.
Poniżej wymienione błędy nie mogą zawiesić AutoLISP-u ani zwrócić niepoprawnej odpowiedzi. Są to raczej efekty niewłaściwej implementacji języka.
AND i OR spowinny zwracać wartość różnego od NIL argumentu zamiast T.
Zobacz xarch.tu-graz.ac.at/autocad/docs/and-bug.html
MAX i MIN powinny działać także na łańcuchach, skoro AND również akceptuje i przetwarza łańcuchy.
Zobacz ACAD_STRLSORT powyżej
O błędach przepełnienia stosu przeczytasz niżej. Zobacz [14].
W skrócie: użyj VL-SORT (ogólne zastosowanie) lub ACAD_STRLSORT (tylko łańcuchy).
Ale uważaj: VL-SORT usuwa duplikaty (spełniające warunek EQ)!
Zestawiony przegląd procedur sortowania jest na xarch.tu-graz.ac.at/autocad/lisp/#sort
W LISP-ie najczęściej używaną metodą jest sortowanie przez łączenie (użytą także w (str-sort) w przykładowym TABLES.LSP Autodesku), ponieważ jest to naturalna metoda dla połączonych list. Normalnie (np. w C) używa się algorytmu sortowania przez kopcowanie (dla dowolnych danych) lub sortowania szybkiego (dla danych losowych) oraz sortowania przez wstawianie dla małych list (< 7) lub sublist o znanym algorytmie.
Istnieje kod w LISP-ie realizujący sortowanie metodą Shella, sortowanie bąbelkowe, sortowanie przez wstawianie, sortowanie szybkie, dostępny dla dowolnych danych list oraz indeksów wskazujących na listy. W LISP-ie możesz ominąć wybór funkcji sortującej, który jest dokonywany w czasie wykonywania kodu (tutaj jest to określone przez parametr "method"). Z tego powodu wystarczy, że będziesz znał tylko jedną funkcję sortującą dla różnych typów danych (np. liczb, punktów po osi x lub y, łańcuchów...):
(sort data method) ;method: less-than-predicate
;default for numbers: '<
Niektóre przykładowe czasy wykonania sortowania ze strony xarch.tu-graz.ac.at/autocad/lisp/sort/ur_sort.lsp:
Sortowanie 100 elementów:
s. bąbelkowe : 13.639008 sec/ 30.08%
s. przez wstawianie : 13.368042 sec/ 29.48% (szybkie dla posortowanych list)
s. metodą Shella : 13.478973 sec/ 29.73% (słaba implementacja)
s. przez łączenie : 2.232971 sec/ 4.92%
s. szybkie : 2.433960 sec/ 5.37%
vlx-sort : 0.099976 sec/ 0.22% (wewnątrz Vital LISP-u)
acad_strlsort : 0.089996 sec/ 0.20% (wewnątrz AutoLISP-u, łańcuchy)
W przygotowaniu są czasy wykonania dla vl-sort, vl-isort, STDLIB std-fast-sort, std-sort, std-stable-sort oraz nowego merge-sort Vladimira.
To nie jest wprawdzie często zadawane pytanie, ale jedno z bardziej interesujących, ponieważ LISP jako taki jest zdefiniowany rekursywnie i to on jest najłatwiejszym sposobem wyrażenia trudnych problemów.
Szczegółowe dokumenty dotyczące rekursji znajdują się na stronie xarch.tu-graz.ac.at/autocad/lisp, szczególnie xarch.tu-graz.ac.at/autocad/lisp/recursive.html, a także w podręczniku Dennisa Shinna.
Tutaj jest to wyjaśnione w dużym uproszczeniu:
(defun FACT (n)
(cond
((zerop n) 1)
(T (* n (fact (1- n))))))
Uwaga!
Istnieje także samomodyfikujący się przykład tej funkcji, omówiony na stronie
xarch.tu-graz.ac.at/autocad/lisp/self-mod.lsp
Podobnie jak rekursja, jest to problem trudny do zrozumienia i pytania na jego temat są równie rzadko zadawane.
Iteracyjnymi operatorami w AutoLISP-ie są: WHILE, REPEAT, FOREACH oraz MAPCAR. Są one często używane w tym FAQ w przykładach kodu, ponieważ umożliwiają jego zwięzłość.
Tutaj znajduje się krótki kurs dotyczący LAMBDA, QUOTE, MAPCAR... wg Vladimira Nesterovskyego:
>> "Mamy 14 ścieżek i 12 świń.
>> Jak mogą być tutaj 24 kaczki?"
>> Czy istnieje polecenie LISP, które pozwoli mi wczytać te
>> wiersze tekstu i rozpoznać liczbę (liczby) w każdym wierszu,
>> w celu, powiedzmy, zwiększenia każdej z liczb dwukrotnie?
>> Pozostawiając strukturę zdania, etc., nienaruszoną?
To jest jeden ze sposobów (jestem pewien, że istnieje wiele innych sposobów):
(defun MULT2 (strng) ; by Vladimir Nesterovsky
(strlgather
(mapcar
'(lambda (s / n)
(if (zerop (setq n (atof s)))
s
(rtos (* n 2))))
(strlparse strng " ")) ; dzielimy po spacjach
" ")) ; zbieramy z powrotem ze spacjami.
Przykład ten jest wyjaśniony na members.tripod.com/~vnestr/mapcar.txt
Poniższy kod
;;; odwrócenie wierszy i kolumn w tablicy
(defun TRANSPOSE (l) ; by Doug Wilson
(apply 'mapcar (cons 'list l)))
jest objaśniony na xarch.tu-graz.ac.at/autocad/lisp/transpose.002.html
Pliki LISP mogą być wczytywane podczas uruchamiania przy użyciu funkcji LOAD w pliku ACAD.LSP. Niektóre pliki LISP, wymagane do pracy przez menu, powinny być wczytane z odpowiedniego pliku
<menu>.MNL file. The <menu>.MNL Plik <menu>.MNL - jeżeli jest różny od ACAD.MNL - powinien wczytać właśnie ACAD.MNL.
Funkcje LISP wywołujące polecenia w czasie uruchamiania powinny być zdefiniowane w funkcji
S::STARTUP w pliku ACAD.LSP. Ta funkcja zostanie uruchomiona automatycznie po
zakończeniu inicjalizacji. W przeciwnym razie otrzymasz komunikat o błędzie
"Command list interruption (6 . 2)".
Uwaga: funkcja (command) może być bezpiecznie wywoływana z plików MNL. Funkcja (S::STARTUP) jest obecnie używana do sprawdzenia częściowych menu.
Jeżeli nazwa była podana bez rozszerzenia, funkcja LOAD przyjmie *.LSP. Jeżeli nie podamy ścieżki dostępu do pliku, zazwyczaj zostanie użyta lokalizacja plików pomocniczych AutoCAD-a, dokładnie w poniższej kolejności:
- katalog bieżący;
- katalog zawierający bieżący rysunek;
- katalogi zdefiniowane przez zmienną środowiska ACAD (ustawianą w oknie Parametry, zakładka Pliki, ścieżka poszukiwań plików pomocniczych);
- katalog zawierający acad.exe.
Jeżeli twój program nie jest wczytywany automatycznie, sprawdź ustawienia powyższych katalogów.
W przypadku ACADLC (ACOMP) oraz narodowych wydań AutoCAD-a R12, plik ACAD.LSP nie jest wczytywany automatycznie. Dlatego musisz dopisać (load "ACAD" -1) w swoim ACAD.MNL.
Przykładowy ACAD.LSP:
;;;ACAD.LSP
;;; Fred the Beaver, 12/12/94
(load "init" -1) ; tu wczytujemy pewne narzędzia
(defun S::STARTUP ()
(load "new-end" -1) ; tu redefiniujemy polecenie END
)
Argument -1 zabezpiecza przed przerwaniem polecenia LOAD, nawet gdy polecenie LOAD się nie powiedzie (wystąpi błąd AutoLISP-u). Jeżeli niepowodzenie wystąpi w czasie wczytywania, zostanie zwrócona wartość -1, ale ewaluacja nie zostanie przerwana. "-1" może być równie dobrze wyrażeniem.
Przykładowy kod wykorzystuje funkcję S::STARTUP. W postaci skompilowanego kodu VILL lub VLISP nie działa, zamiast tego musi być zdefiniowane DEFUN-Q.
Funkcje nie są już w zasadzie listami! Zamiast używać DEFUN-Q dla S::STARTUP, lepiej sprawdzić, czy znane symbole są listami definiującymi funkcje użytkownika, które są wstawione i ewaluowane w czasie wykonania.
(defun MY::STARTUP () ;twój kod startowy
;..
(princ)
)
(setq S::STARTUP
(if (and S::STARTUP (listp S::STARTUP)) ;zdefiniowane wcześniej w
; ACAD.LSP lub gdzie indziej
(append S::STARTUP (cdr MY::STARTUP)) ;dołącza twój kod
MY:STARTUP)) ;wywołuje twój kod
Albo prościej:
(if (and S::STARTUP (listp S::STARTUP))
(setq S::STARTUP (append S::STARTUP (list func '(princ))))
(setq S::STARTUP (list nil func '(princ))))
Zobacz też [12] Jak automatycznie wczytywać swoje programy?.
Możesz zarówno wczytywać swoje programy podczas uruchamiania AutoCAD-a (zobacz [11] Moje LISP-y nie są już wczytywane automatycznie),
co zajmuje więcej czasu i pamięci w chwili uruchomienia, lub możesz zdefiniować je przez mechanizm autowczytywania.
Od R14 programy ARX używają nowego algorytmu autowczytywania (zwanego "wczytywaniem na żądanie"), który wymaga wpisów do rejestru i nie wymaga już pliku ACADRxx.LSP.
Spójrz na koniec swojego pliku ACADRxx.LSP, aby sprawdzić, jak AutoCAD automatycznie wczytuje swoje programy.
;;;===== AutoLoad LISP Applications =====
...
(autoload "dline" '("dline" "dl"))
...
Takie zdefiniowanie poleceń DLINE oraz DL w liście spowoduje, że zostaną one wczytane z pliku DLINE.LSP, w chwili gdy użytkownik po raz pierwszy wywoła polecenie DLINE lub DL. Wcześniej ta funkcja była po prostu zdefiniowana podobnie jak:
(defun C:DL () (load "DLINE")(C:DL))
W rzeczywistości definicja funkcji jest bardziej skomplikowana, ze względu na obsługę błędu Ctrl+C, błędu wczytywania, błędu niewłaściwej nazwy pliku lub ścieżki dostępu.
Po pierwszym wywołaniu funkcja jest nadpisywana przez definicję zawartą w pliku.
- Korzyści z mechanizmu autowczytywania:
- Uruchamianie jest szybsze, gdyż nie wymaga wczytania wszystkich twoich plików lisp. Po prostu definiujesz proste
funkcje-obwoluty tak, jak to pokazano wyżej. To jest wykonywane przez funkcję
(autoload).
Potrzebujesz mniej pamięci.
- Wady:
-
W przypadku błędów w twoim programie możesz wpaść w pętlę bez końca, która może być przerwana dopiero po przepełnieniu stosu lub przez Ctrl+C.
Uwaga: w przypadku skompilowanego kodu ACOMP przerwanie programu nie jest możliwe nawet przez wciśnięcie Ctrl+C, dlatego należy gdzieś wstawić wywołanie nieskompilowanej funkcji (princ).
Musisz definiować i nadzorować wszystkie nazwy funkcji ze swoich programów w definicjach (autoload). Zmiana nazwy pliku LISP lub nazwy polecenia może spowodować wyżej opisany błąd.
- Gdzie umieścić własne definicje
(autoload)?
-
Nie w pliku ACADR14.LSP. Rekomendujemy umieszczenie ich w plikach inicjalizujących, ale nie w ACAD.LSP, ponieważ jest on często zmieniany przez różne aplikacje, a ponadto ACAD.LSP powinien być raczej mały.
Na przykład wstaw je do plików AUTOLOAD.LSP lub INIT.LSP, które będą wczytywane przez ACAD.LSP. Zobacz [11] Moje LISP-y nie są już wczytywane automatycznie podczas uruchamiania AutoCAD-a.
Należy nadmienić, że użytkownicy *nie* powinni modyfikować pliku ACADRxx.LSP. Od kiedy ACAD.LSP nie jest nadpisywany podczas uaktualnienia, jest gwarantowane, że pozostanie on bezpieczny. Dodatkowo (co dotyczyło również łaty R13c4a), jeżeli plik ACADR13.LSP był modyfikowany, proces wstawiania łaty może przebiegać niepoprawnie, skutkując błędnym działaniem programu.
W czystym AutoLISP-ie nie jest to możliwe.
Możesz przekazać wszystkie argumenty w liście takiej jak ta:
;;; drukuje zmienną liczbę argumentów (dowolnego typu)
(defun MY-PRINC (x)
;; prosta wersja, lepsze znajdziesz na SDK2: PRINTF.LLB
(if (listp x)
(mapcar 'princ x)
(princ x)))
Możesz również zdefiniować funkcję ADS lub ARX i wyeksportować ją do AutoLISP-u. Następnie wpisz:
(ads-print "Hello " "World " 1 2 3)
lub nawet
(ads-printf "Hello %s %i %i" "World" 2 3)
Zobacz przykłady ADS Reiniego Urbana oraz Vladimira Nesterovskyego na stronie xarch.tu-graz.ac.at/autocad/ads/. Przedstawiają one implementacje powyższych kodów.
Autodeskowi zostały oficjalnie przekazane życzenia dotyczące dyrektywy &optional jako rozszerzenia języka AutoLISP, ale nie zostało to dotąd wprowadzone.
W starych wersjach AutoLISP-u wielkość stosu była niezmienna. Nie mógł
on być zwiększany, ale jego wielkość była wystarczająca do większości
celów. W IDE Visual LISP-u przepełnienie stosu zostało zasymulowane przy
984 rekursjach. W linii poleceń A2000 lub wczytanych programach (poza
IDE) nie udało się już osiągnąć przepełnienia stosu. Istnieje
niebezpieczeństwo wystąpienia błędu rekursji w twoich programach
(zobacz [9]). Większość błędów przepełnienia stosu występuje w
wyniku błędów w programach, chroniąc system przed wpadnięciem w
pętlę bez końca lub przed użyciem funkcji rekursywnych na dużych
listach. Z tego powodu jesteś ograniczony do stosowania całkiem
krótkich list w funkcjach rekursywnych w starych wersjach AutoLISP-u.
Nie możesz zmniejszyć rozmiaru używanego stosu poprzez mniejszą
liczbę parametrów lokalnych w swojej rekursywnej funkcji. Niemniej
jednak nie używaj APPLY, EVAL lub MAPCAR do rekursywnego wywołania
funkcji, gdyż one pochłaniają stos. Użycie "tail recursion" także
nie pomoże. Powinieneś zamienić swoją funkcję rekursywną na iteracyjną.
(Istnieje teoria matematyczna mówiąca, że każda funkcja rekursywna może
zostać zamieniona na iteracyjną, a funkcja "tail recursion" nawet w
sposób automatyczny). Iteracyjne wersje mogą używać stosu w sposób
podobny jak funkcje (push) oraz (pop), ale te wersje przechowują
stos w przestrzeni węzłów AutoLISP-u, która jest limitowana
wielkością dostępnej pamięci wirtualnej.
Możesz przetestować przepełnienie stosu prostą funkcją:
;;; Tworzy listę n liczb (na podstawie zera
(defun INTLST (l n)
(cond ((zerop n) l)
(T (intlst (cons (1- n) l) (1- n)))))
po czym spróbuj:
(setq n 100)(while (intlst nil (setq n (+ 10 n)))(print n))
W AutoLISP-ie R12/DOS mogłeś uzyskać granicę stosu przy (intlst
nil 138), w A13/Win przy (intlst nil 240), w ACOMP-ie bi4 przy
(intlst nil 1240), w Vital LISP IDE przy (intlst nil 984). W R10c10
(pierwsza wersja LISP dla rozszerzonej pamięci) mogłeś zmieniać
wielkość stosu za pomocą zmiennej systemowej LISPSTACK. ACOMP
dla R10 miał COMPSTACK. W Vital LISP lub Visual LISP RTS lub
A2000 (poza IDE) wielkość stosu jest nieograniczona.
W wyniku zamiany na postać iteracyjną uzyskujemy pożądane wyniki:
(defun INTLST (n / l)
(repeat n
(setq l (cons (setq n (1- n)) l)))) ;wygląda okropnie, ale działa
Niektóre polecenia nie są wewnętrznymi poleceniami AutoCAD-a, są po prostu programami AutoLISP o nazwach rozpoczynających się od C:, nawet jeżeli są zdefiniowane w programach ADS. Jedynie natywne aplikacje Rx (lub wykorzystujące vlax-add-cmd) eksportują prawdziwe polecenia.
Listę wszystkich takich poleceń można znaleźć w pliku ACADR13.LSP, w sekcji AUTOLOAD (zobacz też "[12]")
Wszystkie te polecenia powinny być wywoływane jako (C:ROTATE3D) zamiast (command "ROTATE3D").
Niemniej jednak funkcje ADS mogą pobierać opcjonalne argumenty. Więcej informacji znajdziesz w Podręczniku adaptacyjnym.
Na przykład poprawne jest (c:rotate3d ss p1 p2 angle), a nawet (rotate3d ...).
"Mam problemy z otrzymaniem pliku LISP otwierającego rysunek i kontynuującego działanie. W chwili gdy nowy rysunek jest otwierany, plik LISP przestaje istnieć w pamięci AutoCAD-a. Musi zostać ponownie wczytany, aby polecenie było rozpoznawane."
Pamięć LISP jest przeładowywana dla każdego rysunku. Istnieją pewne metody pozwalające wykonać program LISP na wielu rysunkach:
- Poprzez skrypt, który wykonuje się na wielu rysunkach:
MYSCRIPT.SCR.
(load "mylisp")
_QSAVE _OPEN !nextdwg
(load "mylisp")
_QSAVE _OPEN !nextdwg
...
- Zewnętrzne programy innych firm, takie jak RunLisp lub DDSCRIPT, automatyzują tworzenie skryptu z punktu 1.
- R14 ma nową właściwość, zwaną "Persistent LISP"
(okienko Parametry, zakładka Zgodność, Zachowaj programy AutoLISP między rysunkami).
- VVital LISP posiadał wbudowaną zmienną działającą jak Persistent LISP - była to
(setq *VILL-NEW-FULL-INIT* nil), przechowująca symbole między sesjami VLISP,
w Visual LISP-ie jej nazwa została zmieniona na *VLISP-NEW-FULL-INIT*.
Funkcje z przedrostkiem C: są automatycznie eksportowane do AutoLISP. Zwykłe funkcje VLISP lub ViLL muszą być albo eksportowane przez (vl-acad-defun 'myx-funcname), albo ich symbole muszą być eksportowane przez specjalną dyrektywę kompilatora zdefiniowaną w pliku LSP lub w pliku GLD (plik deklaracji globalnych). Lepiej użyć specjalnego przedrostka dla takich funkcji.
.GLD:
(AUTOEXPORT-to-ACAD-PREFIX
;| przedrostki nazw funkcji, które mają
; być automatycznie eksportowane do AutoCAD-a: (łańcuchy) |;
"myx-*"
)
lub jedna za drugą
.LSP:
(pragma '((export-to-acad myx-func1 myx-func2)))
Uwaga! W językach VLISP oraz ViLL może wystąpić znany błąd, dotyczący list atomów oraz list par kropkowych w argumentach i wartościach zwracanych przez tak zdefiniowane funkcje. Zobacz [7].
Funkcje eksportowane przez zewnętrzne aplikacje, które mają być użyte przez twoją aplikację, muszą być zdefiniowane w pliku XDF.
Symbole (zmienne), które są zmieniane przez Visual LISP i których wartości są także używane w AutoLISP-ie lub AutoCAD-zie (np. w menu), muszą zostać najpierw oznaczone przez kompilator jako zewnętrzne w następujący sposób:
(pragma '((not-localize myx:symbol)))
ale także muszą zostać wyeksportowane:
(vlisp-export-symbol 'myx:symbol)
Za każdym razem, gdy ich wartość zostanie zmieniona w Visual LISP-ie, sterowanie programem zostanie przekazane do AutoCAD-a, w celu odczytania aktualnej wartości w AutoLISP-ie lub AutoCAD-zie (np. przez !myx:symbol).
W AutoCAD-zie 2000 to jest znacznie prostsze, jednakże powinieneś eksportować swoje funkcje z chronionej przestrzeni nazw poprzez VL-DOC-SET.
Zobacz też www.autodesk.com/support/techdocs/td17/td175363.htm
Część II: Przykłady, kod
Więcej ogólnych funkcji AutoLISP-u znajdziesz w bibliotece AutoLISP Standard Library na
xarch.tu-graz.ac.at/autocad/stdlib/
Inny kod jest dostępny na niektórych stronach dotyczących AutoLISP-u [1] lub zawartych w SDK Autodesku [1.2].
Zamieściłem tutaj kilka funkcji pomocniczych, umożliwiających skrócenie kodu przykładowych programów zawartych w odpowiedziach umieszczanych w Sieci.
Możesz być pewny, że te funkcje są dostępne dla wszystkich, jak np. słynna funkcja DXF - zdefiniowana jako
(defun dxf (grp ele) (cdr (assoc grp ele))) oraz specjalny zamiennik funkcji (getval),
który może obsługiwać zarówno nazwy entycji, jak ich listy DXF.
Zobacz także http://xarch.tu-graz.ac.at/autocad/stdlib/STDLIST.LSP
Użytecznymi przykładami funkcji operujących na listach są również:
;;; Czy lista nie jest pusta?
(defun CONSP (x) (and x (listp x)))
;;; Zwraca pozycję (licząc od zera) pierwszego wystąpienia
;;; elementu na liście lub nil, jeżeli element nie występuje
;;; (position 'x '(a b c)) -> nil, (position 'b '(a b c d)) -> 1
(defun POSITION (x lst / ret)
(if (not (zerop (setq ret (length (member x lst)))))
(- (length lst) ret)))
;;; Usuwa element z listy (nawet w przypadku wielokrotnego wystąpienia)
;;; (remove 0 '(0 1 2 3 0)) -> (1 2 3)
(defun REMOVE (ele lst) ; by Serge Volkov
(apply 'append (subst nil (list ele) (mapcar 'list lst))))
;;; Warunkowe usuwanie z jednowymiarowej listy
;;; Warunek fun powinien być dokładnie jednym wyrażeniem
;;; (remove-if 'zerop '(0 1 2 3 0)) -> (1 2 3)
;;; (remove-if 'numberp '(0 (0 1) "")) -> ((0 1) "")
(defun REMOVE-IF (fun from)
(cond
((atom from) from) ;nil lub symbol (zwracany)
((apply fun (list (car from))) (remove-if fun (cdr from)))
(t (cons (car from) (remove-if fun (cdr from))))
)
)
;;; Zachowuje wszystkie elementy o wskazanych typach.
;;; Powiedz: "keep if" (zachowaj-gdy). Nie wymaga
;;; definicji rekursywnej [poprawione, podziękowania
;;; dla Serge'a Pashkova, w FAQ-CODE.LSP było poprawnie]
(defun REMOVE-IF-NOT (pred lst) ; by Vladimir Nesterowsky
(apply 'append
(mapcar '(lambda (e)
(if (apply pred (list e)) (list e))) lst)))
;;; Jeżeli ele nie jest elementem listy, zostanie wstawione
;;; na jej początek. Akceptuje także cytowane listy:
;;; (setq l '(1 2 3) (adjoin 0 'l)
;;; -> !l (0 1 2 3)
(defun ADJOIN (ele lst / tmp)
(if (= (type lst) 'SYM) (setq tmp lst lst (eval tmp)))
(setq lst (cond ((member ele lst) lst)
(t (cons ele lst))))
(if tmp (set tmp lst) lst)
)
;;; ROT1 - przesuwa pierwszy element na koniec listy,
;;; prosta wersja (przesunięcie o jedną pozycję)
(defun rot1 (lst) (append (cdr lst) (list (car lst))))
;;; BUTLAST - lista bez ostatniego elementu
(defun butlast (lst)
(reverse (cdr (reverse lst))))
Sprawdź http://xarch.tu-graz.ac.at/autocad/stdlib/STDSTR.LSP.
Niektóre użyteczne funkcje operujące na łańcuchach mogą być tutaj:
- Sprawdzanie typu:
- (stringp expr)
- - sprawdzanie typu łańcuchowego - czy wyrażenie jest łańcuchem?
(defun stringp (s) (= (type s) 'STR))
- (string-not-emptyp str)
- - czy łańcuch nie jest łańcuchem pustym?
(defun string-not-emptyp (s) (and (stringp s) (/= s "")))
- Usuwanie znaków:
- (str-trim string)
- - usuwanie spacji lewych i prawych, zdefiniowane AI_UTILS.LSP, podobnie jak:
- (str-left-trim string), (str-right-trim string),
- (str-left-trim-bag string bag), (str-right-trim-bag string bag)
- - usuwanie wszystkich znaków zawartych w łańcuchu bag.
- Wyszukiwanie:
- (strpos string substr)
- - zwraca pozycję (licząc od 1) pierwszego wystąpienia podłańcucha.
- Funkcje dzielenia i sklejania (zamiana listy na łańcuch i odwrotnie):
- (strtok str tokens)
- - zamiana łańcucha na listę rozdzieloną wg parametru tokens;
- (strlcat lst delim)
- - łączy elementy listy w jeden łańcuch, oddzielając poszczególne podłańcuchy wartością parametru delim;
-
- (string->list str)
- - zamiana łańcucha na listę znaków;
- (list->string str)
- - zamiana listy znaków na łańcuch.
- Wszystkie powyższe i jeszcze więcej funkcji znajduje się w bibliotece Stdlib (zobacz wyżej).
Niektóre są na xarch.tu-graz.ac.at/autocad/code/vnestr/strtok.lsp
lub w twoim AI_UTILS.LSP. Szczególnie będziesz potrzebował ich w funkcjach obsługi DCL.
Odwrotnością funkcji (read) będzie (symbol-name). Poniżej przedstawiono ogólny
sposób, ale istnieją lepsze, specjalne metody.
;;; SYMBOL-NAME zwraca nazwę symbolu jako łańcuch. Zamienia
;;; dowolne poprawne wyrażenie LISP na jego drukowaną reprezentację
;;; (symbol-name a) -> "a", (symbol-name '(0 1 2 a)) -> "(0 1 2 A)"
(defun SYMBOL-NAME (sym / f str tmp)
(setq tmp "$sym.tmp") ;plik tymczasowy, powinien zostać usunięty
(setq f (open tmp "w"))(princ sym f) (close f)
(setq f (open tmp "r") str (read-line f) f (close f))
str
)
Dla zwykłych symboli istnieje lepszy sposób, wyjaśniony przez Christophera Candido na http://xarch.tu-graz.ac.at/autocad/news/symbol-string.txt
W ViLL i VLISP wprowadzono szybszą funkcję VL-SYMBOL-NAME. Zobacz też http://xarch.tu-graz.ac.at/autocad/stdlib/STDINIT.LSP
Zobacz też http://xarch.tu-graz.ac.at/autocad/stdlib/STDENT.LSP
;;; Zwraca pierwszą wartość grupy DXF. Działa podobnie jak dobrze znana
;;; funkcja (dxf), ale akceptuje wszystkie typy określające entycję
;;; (nazwę, listę DXF, listę entsel).
;;; UWAGA: nie nadaje się do odczytu grup 10 w LWPOLYLINE!
(defun GETVAL (grp ele) ;"wartość dxf" dla danej entycji...
(cond ((= (type ele) 'ENAME) ;nazwa entycji
(cdr (assoc grp (entget ele))))
((not ele) nil) ;wartość pusta
((not (listp ele)) nil) ;błędny ele
((= (type (car ele)) 'ENAME) ;lista entsel
(cdr (assoc grp (entget (car ele)))))
(T (cdr (assoc grp ele))))) ;lista entget
;;; Np.: (gettyp pline) => "POLYLINE"
(defun GETTYP (ele) ;zwraca typ.
(getval 0 ele))
;;; Zamienia dowolne wskazanie na typ "nazwa entycji" (dla skrócenia kodu)
(defun ENTITY (ele) ;zamiana na nazwę entycji
(cond ;akceptuje następujące typy:
((= (type ele) 'ENAME) ele) ; nazwę entycji
((not (listp ele)) nil) ; błąd: nie jest listą
((= (type (car ele)) 'ENAME) (car ele)) ; listę entsel
((cdr (assoc -1 ele))) ; listę entget lub nil
)
)
;a teraz po prostu:
(defun getval (grp ele) (cdr (assoc grp (entget (entity ele)))))
;;; Np. (istypep ele "TEXT")
;;; Czy element jest entycją typu "SOLID"?
(defun istypep (ele typ) ;Sprawdzenie typu.
(= (gettyp ele) typ))
;;; np. (istypep ele '("TEXT" "ATTDEF"))
;;; czy element jest entycją typu "TEXT" lub typu "ATTDEF"?
(defun ISTYPEP (ele typ) ;better implementation to accept lists too
(cond
((listp typ) (member (gettyp ele) typ)) ;Poprawiono.
((stringp typ) (= (gettyp ele) typ)) ;Zakłada, że lista zawiera
;nazwy, których pisownia
;jest dokładna.
;Użycie funkcji uppercase
;oraz wcmatch.
(T nil)))
;;; np. (getpt (entsel)) => ( 0.1 10.0 24)
(defun GETPT (ele) ;Zwraca punkt początkowy elementu.
(getval 10 ele)) ;grupa DXF 10
;;; np. (getflag pline) => 1, jeżeli polilinia zamknięta.
(defun GETFLAG (ele) (getval 70 ele)) ;Niektóre entycje mają znacznik.
;;; Czy bitowa wartość znacznika jest ustawiona?
;;; Np. (flagsetp 1 pline) => T, jeżeli polilinia jest zamknięta.
;;; Np. (flagsetp 16 vertex) => T, jeżeli jest to punkt kontrolny splajnu.
(defun FLAGSETP (val ele)
(bitsetp val (getflag ele)))
;;; Np. (bitsetp 4 12) = T
;;; Wartość bitowa 4 (= drugi bit) w 12 (=4+8) jest ustawiona.
(defun BITSETP (val flag)
(= (logand val flag) val))
;;; Zamienia zbiór selekcji na listę. Powolne , ale łatwe do napisania.
;;; Uwaga: tu również dobrze jest użyć ai_ssget, ponieważ niektóre
;;; entycje mogą się znajdować na zablokowanych warstwach.
;;; Np. (sslist (ai_ssget (ssget))) => lista wybranych,
;;; niezablokowanych entycji
;;; lub (mapcar 'entupd (sslist (ssget "X" '((8 . "TEMP")))))
;;; - uaktualnia wszystkie entycje z warstwy TEMP.
(defun SSLIST (ss / n lst)
(if (= 'PICKSET (type ss))
(repeat (setq n (sslength ss))
(setq n (1- n)
lst (cons (ssname ss n) lst)))))
;;; Wykonuje funkcję na każdej entycji w ss, w odwrotnej kolejności.
;;; Szybsze, ale nie takie łatwe do zrozumienia. Zobacz [22.2]
;;; [zmiana nazwy z SSAPPLY na SSMAP, w celu dostosowania
;;; do nazewnictwa w bibliotece stdlib.
(defun SSMAP (fun ss / n)
(if (= 'PICKSET (type ss))
(repeat (setq n (sslength ss))
(apply fun (list (ssname ss (setq n (1- n))))))))
-
[21.1] Globalna zmiana właściwości tekstów, polilinii, funkcje obsługi warstw, datownik wydruków z plotera
- Do globalnej zmiany atrybutów tekstu użyj CHTEXT.LSP w swoim katalogu SAMPLE.
W celu globalnej zmiany właściwości polilinii, zamrożenia warstwy przez wskazanie elementu
i innych podobnych zadań przeszukaj bezpłatne lispy na dowolnym z portali AutoLISP-u. Zobacz także
[1] oraz niektóre przykłady kodu w [22],
[23], oraz [24].
W celu automatycznego umieszczenia "datownika" i tym podobnych informacji na swoich wydrukach z plotera, najpierw sprawdź, czy twój ploter obsługuje język HPGL/2. W tym przypadku użyj wewnętrznego sterownika HPGL/2 i skonfiguruj poleceniem HPCONFIG.
DATESTAMP.LSP: zmień atrybuty w bloku datownika wydruku samodzielnie, tak jak w [22.2].
Profesjonalny program obsługi datownika wydruku znajduje się na stronie:
http://ourworld.compuserve.com/homepages/tonyt/plotstmp.htm
-
[21.2] Okienko dialogowe plotowania z poziomu Lisp. Użycie DDE oraz ActiveX
Od R14 użyj INITDIA
(initdia)(command "_PLOT")
- Wywołanie okienka dialogowego PLOT z AutoLISP-u przed R14 było możliwe jedynie w środowisku Windows, np. za pomocą programu LISPPLOT Mikea Dickasona. Program ten wprowadzał znaki do bufora klawiatury. Informacje na ten temat znajdziesz na stronach:
www.cadalog.com/cadalog/files/lispd-l/lspplw.zip
oraz: ftp://ftp.mcwi.com/pub/mcwi/lisp/winplt.lsp
Stworzenie skryptu i wywołanie go na końcu twojego lispu nie spowoduje wyświetlenia okienka dialogowego.
Xiang Zhu: możesz użyć "ddelisp" w środowisku Windows w następujący sposób:
;;; [poprawione dla wszystkich wydań]
(defun DDECMD (str / tmp acadver ddestr)
(if (not (boundp 'initiate))
(cond
((= 14 (setq acadver (atoi (getvar "ACADVER"))))
(setq ddestr "AutoCAD.R14.DDE") (arxload "ddelisp"))
((= 13 acadver)
(setq ddestr "autocad.r13.dde") (xload "ddelisp"))
((= 12 acadver)
(setq ddestr "autocad.dde") (xload "ddelisp"))
(T (princ "DDE not supported")(exit))))
(if (not (zerop (setq tmp (initiate ddestr "system"))))
(progn
(execute tmp (strcat "[" str "]"))
(terminate tmp)
str)))
Dla R12 użyj "autocad.dde" jako nazwy serwera. Następnie wewnątrz swojego
lispu lub skryptu możesz wpisać (ddecmd "_plot "). Funkcja DDECMD zwróci
nil - jeżeli coś pójdzie niepomyślnie - lub przesłany łańcuch w przypadku powodzenia.
Łańcuch zawiera dokładnie to, co wpisujesz w odpowiedzi na zgłoszenie polecenia z
klawiatury, dlatego powinny być tam spacje oraz znak [Enter] zakodowany jako "^13",
aby zakończyć polecenie.
Dodatkowo ta funkcja jest bardzo użyteczna w następujących sytuacjach:
jeżeli za pomocą lispu chcesz wywołać polecenie nakładkowe, jak LAYER,
normalnie używasz (command "_layer"), ale użycie tej linijki kodu spowoduje,
że sam lisp nie będzie poleceniem nakładkowym. Używając omówionej funkcji,
rozwiążesz ten problem.
Weź pod uwagę, że AutoCAD akceptuje polecenia DDE jedynie, gdy linia poleceń jest aktywna, to znaczy nie może być otwartego okna dialogowego.
Za pomocą VLISP lub ViLL i metod ActiveX możesz użyć także następującego kodu:
;;; Składnia vlisp:
(setq vlax:ActiveDocument (vla-get-ActiveDocument (vlax-get-Acad-Object)))
(setq plt (vla-get-plot vlax:ActiveDocument)) ;=> plotowanie obiektu
(vla-PlotWindow plt pt1 pt2) ; definiowanie okna(pt1, pt2 w WCS)
(vla-PlotPreview plt 1) ; 0 dla podglądu częściowego, 1 dla pełnego
(vla-PlotToDevice plt "Default System Printer") ; jeżeli drukarka istnieje
W R14 została wprowadzona zmienna INITDIA, która może być stosowana do większości (nie wszystkich) dialogów:
(initdia)(command "_PLOT")
W A2000 użyj OLE (metod VLA- ) zamiast DDE.
-
[21.3] Funkcje (entmod) oraz (entmake). Obsługa warstw bez użycia (command "_LAYER"...).
- Modyfikacja warstwy (ENTMOD)
- Próbowałem zmienić właściwości warstwy bez wywołania funkcji COMMAND wewnątrz programu LISP.
Od R13 możesz włączać i wyłączać dowolną warstwę (nawet jeżeli jest ona bieżącą), używając poniższego lispu:
(setq tbl_lst (entget (tblobjname "LAYER" "ANY_LAYER"))
clr_grp (assoc 62 tbl_lst))
(entmod (subst (cons 62 (- (cdr clr_grp))) clr_grp tbl_lst))
you can toggle "ANY_LAYER" On or Off, even it is the current layer.
Ale AutoCAD nie rozpozna, że wpis w tablicy został zmieniony, dopóki nie klikniesz właściwości warstw na pasku narzędziowym lub nie zrobisz czegoś podobnego. Przy okazji możesz wydać polecenie 'DDLMODES, aby zobaczyć, czy warstwa "ANY_LAYER" została włączona lub wyłączona.
Robiąc to samo, aby zamrozić warstwę, nadal widzisz na ekranie należące do niej obiekty, ale nie możesz ich wybrać - dopiero, gdy zmienisz ustawienia warstw, AutoCAD ukryje te elementy.
- Tworzenie warstwy (ENTMAKE)
- Musisz odczytać wzorzec poleceniem ENTGET, używając słownika nazwanych obiektów jako argumentu. Słownik nazwanych obiektów można uzyskać przez funkcję TBLOBJNAME:
(entget (tblobjname "LAYER" "Any Layer Name")) ; R2000 może używać spacji!
;;; Ten program tworzy warstwę z dowolną nazwą, jaką wpiszesz:
(defun C:MLAY () ; by Reinaldo Togores
(setq laynam (getstring "\nLayer name: "))
(entmake
(list
'(0 . "LAYER")
'(5 . "28")
'(100 . "AcDbSymbolTableRecord")
'(100 . "AcDbLayerTableRecord")
(cons 2 laynam)
'(70 . 64)
'(62 . 7)
'(6 . "CONTINUOUS")
)
)
)
-
[21.4] Jak wybrać wiele plików w programie LISP?
-
[21.5] Zamiana bloków
- Przeszukaj archiwa LISP, zgodnie z poniższymi wskazówkami:
W archiwum Cadalyst: www.cadonline.com/search.phtml
znajdziesz 97code.htm (będziesz musiał się bezpłatnie zarejestrować, aby korzystać z archiwum).
W archiwum xarch: xarch.tu-graz.ac.at/autocad/code -
szukaj fraz "BLOCK;REPLACE"
Znajdziesz xarch.tu-graz.ac.at/autocad/code/cadalyst/94-02/replace.lsp
Także na stronie Cadalog:
www.cadalog.com/find.htm , podając słowa kluczowe "Block Replace"
znajdziesz www.cadalog.com/cadalog/files/lispr-z/replace.zip (to archiwum jest najlepsze).
-
[21.6] Funkcja (vports), entycja VIEWPORT, konwersja współrzędnych ekranu na współrzędne modelu
-
Entycja typu VIEWPORT:
"Mogę wykonać (entget) w odniesieniu do rzutni i odczytać jej lewy dolny (grupa DXF 10) oraz prawy górny (grupa DXF 11) narożnik. Ale tak odczytam współrzędne w układzie papieru. To, co mnie interesuje, to odczytanie, jaka część "prawdziwego" rysunku (w przestrzeni modelu) jest pokazana w danej rzutni."
Odpowiedź na powyższe pytanie znajduje się na xarch.tu-graz.ac.at/autocad/news/vports.lsp
Na www.ez-sys.net/~coopfra/lisp.htm#view także zapoznasz się z pewnymi sztuczkami.
Jak zmienić rzutnie w AutoLISP-ie?
Za pomocą (setvar "CVPORT" vport-id).
Zobacz xarch.tu-graz.ac.at/autocad/news/change_vports.html
Za pomocą poniższych funkcji możesz przeliczyć piksele na jednostki rysunku i odwrotnie:
;;; Zamiana piksela na wymiar w jednostkach rysunku
(defun PIX->UNITS (pix)
(* pix (/ (getvar "VIEWSIZE") (cadr (getvar "SCREENSIZE")))))
;;; Zamiana wymiaru w jednostkach rysunku na piksele
(defun UNITS->PIX (units)
(* units (/ (cadr (getvar "SCREENSIZE"))(getvar "VIEWSIZE"))))
Zobacz także artykuł opublikowany przez firmę Vibrant "Pixel Off by One" Errors in AutoCAD
http://xarch.tu-graz.ac.at/autocad/news/pixel-off-by-one-error.txt
- [21.7] Wybór wszystkich widocznych obiektów, współrzędne narożników
-
Weź pod uwagę, że funkcją (ssget) możesz jedynie wybrać widzialne obiekty, gdyż wszystkie funkcje (entsel, ssget, osnap) działają na podstawie pikseli wyświetlanych na ekranie, jedynie (ssget "X") może dokonać selekcji obiektów niewidocznych.
;;; Zwraca listę współrzędnych narożników aktualnej rzutni w układzie WCS
(defun ZOOMPTS ( / ctr h screen ratio size size_2)
(setq ctr (xy-of (getvar "VIEWCTR")) ;3D -> 2D
h (getvar "VIEWSIZE") ;real
screen (getvar "SCREENSIZE") ;2D: Pixel x,y
ratio (/ (float (car screen)) ;stosunek h/v
(cadr screen))
size (list (* h ratio) h) ;rozmiary ekranu we współrzędnych
size_2 (mapcar '/ size '(2.0 2.0)))
(list (mapcar '- ctr size_2)
(mapcar '+ ctr size_2)))
(defun XY-OF (pt) (list (car pt)(cadr pt))) ;przepisanie w punkt 2D
Uwaga!: Punkty zwracane przez funkcje są w WCS, ale to jest pozytywne, ponieważ opcje "CP", "WP" i "P" funkcji SSGET wymagają punktów w układzie WCS (opcje "W" oraz "C" wymagają punktów w układzie UCS - nie mam pojęcia, skąd takie zróżnicowanie).
;;; Jeden ze sposobów zdefiniowania tej funkcji
(defun SSALL-VISIBLE (/ l)
(ssget "C" (car (setq l (maptrans0-1 (zoompts)))) (cadr l)))
;;; lub inny
(defun SSALL-VISIBLE-1 () ;łączy "C" oraz (p1 p2) w jedną listę
(apply 'ssget (append '("C") (maptrans0-1 (zoompts)))))
;;; przetwarza niektóre punkty z WCS do UCS, łatwiej z jednym argumentem
;;; [poprawiono opis]
(defun MAPTRANS0-1 (pts)(mapcar '(lambda (pt)(trans pt 0 1)) pts))
-
[21.8] W jaki sposób zapisać do pliku listę współrzędnych XYZ dla zbioru wskazanych obiektów?
;;; CDF - łańcuch rozdzielany przecinkami
(defun cdf-point (pt)
(strcat (car pt) ", " (cadr pt) ", " (caddr pt)))
;;; SDF - łańcuch rozdzielany spacjami, łatwiejszy do
;;; powtórnego wczytania do AutoCAD-a
(defun sdf-point (pt)
(strcat (car pt) " " (cadr pt) " " (caddr pt)))
;;; Zamienia format SDF x powrotem na punkty
(defun str->point (s)
(eval (read (strcat "(" s ")"))))
;;; Zapisuje do pliku XYZ dla wszystkich obiektów (dla SDF patrz dalej)
(defun C:XYZ (/ ss fname f)
(if (and (setq ss (ssget))
(setq fname (getfiled "Write XYZ to file"
(strcat (getvar "DWGNAME") ".XYZ") "XYZ" 7))
(setq f (open fname "w")))
(foreach ele (sslist ss) ; -> [20.4]
(foreach pt (getpts ele) ; -> [23.1]
(write-line (cdf-point pt) f)
)
)
)
(if f (close f))
)
;;; => .xyz
;;; 0.45, 12.3, -34.0
Dla pliku ASC (format SDF) po prostu zamień wszystkie XYZ na ASC oraz cdf-point na sdf-point w powyższym kodzie.
W celu utworzenia polilinii z pliku ASCII x, y najlepiej zamienić ten plik na skrypt, jak poniżej:
PLINE
300.2,10
350.4,10.4
- [22.1] W jaki sposób uzyskać dostęp do danych definiujących atrybuty bloków?
- Sprawdź wszystkie subentycje występujące po INSERT, tak aby znaleźć atrybuty.
Zobacz xarch.tu-graz.ac.at/autocad/stdlib/STDENT.LSP.
;;; Zwraca listę DXF dla atrubutu s (łańcuch) w elemencie
;;; ele (ENAME) lub nil, jeżeli nie zostanie znaleziony
(defun ATTELE (ele attname / rslt)
(if (and (istypep ele "INSERT")
(= (getval 66 ele) 1))
(progn
(setq ele (entnext (entity ele)))
(while (and ele (istypep ele "ATTRIB"))
(if (= (strcase (getval 2 ele)) (strcase attname))
(setq rslt (entget ele) ele nil) ;break the loop
(setq ele (entnext ele))
)
)
)
)
rslt
)
;;Przykład
(attele (entsel) "TEST") ; zwraca listę DXF
; atrybutu "TEST", jeżeli blok go zawiera
Przy okazji: lepszymi funkcjami do odczytu kodów grup DXF są GET oraz EDLGETENT Vladimira Nesterovskyego.
;;; Przykładowe wywołanie:
;;; zwraca listę wartości grupy 2, 1 oraz -1
(defun get-attribs-look-up (block-ename)
(get '(2 1 -1) (cdr (edlgetent block-ename))))
(defun all-verticies-and-bulges (pline-ename)
(get '(10 42) (cdr (edlgetent pline-ename))))
Są one dostępne na members.tripod.com/~vnestr/
- [22.2] W jaki sposób zmodyfikować atrybuty bloku? DATESTAMP.LSP
-
Atrybuty bloku można modyfikować w bardzo prostym programie DATESTAMP.LSP,
po prostu przez entmod listy DXF atrybutu DATE w twoim bloku - listy,
która została wcześniej odczytana funkcją (attele) jak wyżej.
;;; Zmienia wartości atrybutu na nowe, grupa 1
(defun ATTCHG (ele attname new / b)
(if (setq b (attele ele attname))
(entmod (subst (cons 1 new) (getval 1 b) b))))
;;; Zmienia wszystkie atrybuty DATESTAMP
;;; we wszystkich wstawieniach bloków PLOT*
(defun C:DATESTAMP ()
(ssmap ; poprawiono i zmieniono nazwę
'(lambda (ele)
(attchg ele "DATESTAMP" (today))
(entupd ele)
)
(ssget "X" '((0 . "INSERT")(2 . "PLOT*")))
))
;;; Zwraca dzisiejszą datę w postaci łańcucha
(defun TODAY (/ s)
(setq s (rtos (getvar "CDATE") 2)) ;odczytuje datę juliańską
(strcat (substr s 5 2) "-" (substr s 7 2)"-"(substr s 3 2)))
Automatyczne wstawianie daty jest zazwyczaj realizowane przez
RTEXT (bonus/express tools) lub HPCONFIG w ploterach HPGL/2.
- [22.3] W jaki sposób uaktualnić atrybuty bloku?
-
Istnieje program SUPPORT\ATTREDEF.LSP, uaktualniający właściwości atrybutów (pozycja, warstwa...) dla każdego wstawionego wcześniej bloku.
- Dla entycji złożonych musisz wykonać funkcję ENTUPD na entycji głównej, aby zobaczyć zmiany na ekranie (to wymusza regenerację i przerysowanie entycji na ekranie).
;;; Przykład:
(setq s (getstring "Change Attribute to: "))
(attchg (attele (setq b (entsel "of block: ")) s)))
(entupd (car b)) ; blok, nie atrybut
;;; nieco więcej funkcji pomocniczych do odczytu entycji głównej
;;; dla dowolnego atrybutu lub wierzchołka
(defun MAIN-ENTITY (ele)
(setq b (entity b)) ; wymusza ENAME
(while (istypep b '("ATTRIB" "ATTDEF" "VERTEX"))
(setq b (entnext b))) ; pętla, dopóki nie będzie więcej subentycji
(if (istypep b '("SEQEND" "ENDBLK"))
(getval -2 b) ; główna entycja w przypadku entycji złożonej
b ; zwykła entycja
)
)
- [22.4] W jak sposób utworzyć blok z atrybutami funkcją ENTMAKE?
-
Zobacz xarch.tu-graz.ac.at/autocad/stdlib/ENTMAKE.LSP.
Tu znajduje się przykład, jak użyć wielokrotnego wywołania funkcji (entmake), aby
utworzyć główną entycję bloku, jego entycje składowe, zakończyć definicję bloku i
wreszcie wstawić blok funkcją (entmake). W przypadku bloków anonimowych zauważ, że
jedynie (setq bn (entmake '((0 . "ENDBLK")))) zwraca nazwę bloku
(entmake (list '(0 . "INSERT")'(70 . 1)(cons 2 bn) ...)).
Polilinie typu LW od wersji R14 zawierają informacje o wszystkich wierzchołkach
w jednej entycji jako wielokrotne grupy DXF 10! Z tego powodu funkcja (assoc) nie będzie działać poprawnie.
- [23.1] W jaki sposób uzyskać dostęp do danych definiujących wierzchołki polilinii?
- Wierzchołek polilinii jest subentycją polilinii (podobnie jak atrybut jest subentycją
wstawionego bloku, a definicja atrybutu - subentycją definicji bloku). Z tego powodu
możemy użyć tych samych funkcji, co w [22.1]-[22.3]
;;; Zwraca jedynie niektóre wartości grup na liście DXF (dla LWPOLYLINE)
(defun group-only (grp lst)
(mapcar 'cdr (remove-if-not '(lambda(pair)(= grp (car pair))) lst)))
;;; Zwraca listę wierzchołków polilinii lub innego elementu
(defun GETPTS (ele / pts)
(setq ele (entity ele)) ;wymusza typ ENAME
(cond
((istypep ele "POLYLINE")
(while (istypep (setq ele (entnext ele)) "VERTEX")
;; Opuszcza punkty dopasowania i kontrolne splajnu (w wersji klasycznej)
(if (not (or (flagsetp 1 ele) (flagsetp 8 ele))) ;poprawka!
(setq pts (cons (trans (getpt ele) ele 0) pts)))
(reverse pts)))
;; Przypadek specjalny: możesz przepisać dane, znajdując
;; jedynie pierwsze wystąpienia grup.
;; Poprawka błędu LWPOLYLINE w R14:
;; wewnętrznie przechowywane są jako punkty 2D,
;; (entget) zwraca przypadkowe wartości współrzędnej z.
((istypep ele "LWPOLYLINE")
(mapcar '(lambda(pt)(trans (list (car pt)(cadr pt) 0.0) ele 0))
(group-only 10 (entget ele))))
;; Wstaw tutaj możliwe inne typy, takie jak:
((istypep ele '("TEXT" "CIRCLE")) (list (getpt ele)))
;; raczej tak (w tylu serge'a). Kod dla LWPOLYLINE powyżej.
(T (apply 'append (mapcar
'(lambda (n / p) (if (setq p (getval n ele)) (list p)))
'(10 11 12 13)))
)
;; lub tak (wersja klasyczna):
;;(T (foreach n '(10 11 12 13)
;; (if (setq p (getval n ele)) (setq pts (cons p pts))))
;; pts
;;)
)
)
Sugestie Vladimira Nesterovskyego dotyczące różnych struktur wierzchołków (zobacz [22.1]).
(defun vertices-and-bulges( pline-ename )
(mapcar
'cdr
(remove-if-not '(lambda(ele) (bitsetp 9 x))
(get '(70 10 42) (cdr (edlgetent pline-ename))
=> lista par (10 42)
;;; co może być także zapisane jako:
(defun flag9p (ele) (flagsetp 9 ele))) ; prawdziwe, jeżeli punkt dopasowania
(mapcar
'(lambda (ele)
(remove-if-not 'flag9p (cdr (edlgetent pline-entname))))
Zobacz też [23.5], aby zapoznać się z różną strukturą wierzchołków (segmentów) polilinii.
- [23.2] W jaki sposób połączyć wiele linii w polilinię? [poprawione]
- Po prostu spróbuj dołączyć każdy element do wszystkich wybranych, ale zwróć uwagę, że entycje już dołączone nie mogą być odczytywane przez (entget), ponieważ informacje o nich zostały usunięte.
;;; Ten przykład zamienia wszystkie wybrane elementy
;;; w polilinie oraz próbuje je połączyć, jeśli to możliwe.
(defun C:JOINPOLY (/ ele ss)
(foreach ele (sslist (setq ss (ssget))) ;lepsze przetwarzanie list
(if (entget ele) ;jeszcze nie dołączony
(cond ;(następnie może wystąpić nil)
((istypep ele '("ARC" "LINE"))
;; ale powinieneś sprawdzić współrzędną Z dla linii oraz UCS
(command "_PEDIT" ele "_y" "_j" ss "" ""); zamiana i łączenie
)
((and (istypep ele '("POLYLINE" "LWPOLYLINE")) ;poprawka
(not (flagsetp 1 ele)) ;niezamknięta
(< (rem (getflag ele) 128) 8)) ;ignoruje siatki i podobne
(command "_PEDIT" ele "_j" ss "" "") ;sprawdzanie UCS ominięte
;dla zwięzłości kodu
)
)
)
)
)
- [23.3] Zmiana szerokości polilinii
- Za pomocą wyżej zdefiniowanej funkcji pomocniczej wystarczy po prostu wpisać:
(defun C:POLYWID (/ wid ele)
(initget 5)(setq wid (getdist "New Polyline Width: ")) ;nieujemne
(foreach ele (sslist (ssget '((0 . "*POLYLINE")))) ;tylko polilinie
(command "_PEDIT" ele "_W" wid "")))
- [23.4] Tworzenie polilinii oraz splajnu funkcjami ENTMAKE oraz COMMAND
-
- Możesz utworzyć plik skryptowy za pomocą programu LISP i później go uruchomić. To wygląda na najłatwiejszy sposób, ale mogą wystąpić błędy operacji wejścia-wyjścia podczas odczytu i zapisu pliku skryptowego. Jeżeli piszesz komercyjną aplikację, musisz wprowadzić obsługę takich błędów.
- Drugim sposobem jest utworzenie list DXF dla entycji i użycie ENTMAKE. Korzyści: szybkość, współrzędne punktów zwracane w WCS-ie, niezależność od ustawień zatrzasków.
Zobacz xarch.tu-graz.ac.at/autocad/stdlib/ENTMAKE.LSP.
- Trzecie rozwiązanie jest oparte na funkcjach COMMAND oraz MAPCAR. Działa na poliliniach, splajnach oraz liniach. Wady: UCS, zatrzaski.
;;; Rysuje polilinię z listy punktów (także splajny)
;;; oraz linie, w bieżącym UCS, z bieżącymi ustawieniami zatrzasków
(defun DRAW-PLINE (pts)
(command "_PLINE")
(mapcar 'command pts)
(command ""))
(defun DRAW-SPLINE (pts)
(command "_SPLINE")
(mapcar 'command pts) ; wymagane punkty dopasowania
(command "" "" ""))
- [23.5] W jaki sposób obliczyć długość polilinii?
-
Są dwa sposoby:
- Oczywisty, używający polecenia AREA; to sposób nieco "głośny" (wyświetla wynik), ale działa nawet na splajnach.
;;; Dodaje długości wszystkich obiektów, możesz to samo
;;; zrobić w celu policzenia powierzchni: po prostu zamień
;;; ostatnią linię na (getvar "AREA")
(defun C:LEN-OF ()
(command "_AREA" "_A" "_E") ;dodaje obiekty (działa w R12+R13)
(ssmap 'command (ssget)) ;zmieniona nazwa,
;przekazuje wszystkie elementy do AutoCAD-a
(command "" "") ;2 x ENTER
(getvar "PERIMETER")) ;tu mamy długość
- Wymaga nieco matematyki, ale tylko dla prostych entycji. Tutaj najlepiej znowu zdefiniować nieco funkcji pomocniczych. To jest także wprowadzenie do następnego rozdziału [24],
o trygonometrii wypukłości elementów krzywoliniowych w poliliniach.
;;; Oblicza długość polilinii, bez wyświetlania komunikatów
(defun POLY-LENGTH (poly / seg)
(apply '+ ; suma długości wszystkich pojedynczych elementów
(mapcar
'(lambda (seg) ;długość segmentu
(if (zerop (car seg))
(distance (cadr seg) (caddr seg)) ;segment liniowy lub
(abs (arclen seg seg)))) ;krzywy: zobacz niżej w [24]
(pline-segs poly))))
;;; Zwraca wszystkie kody grup XDF dla entycji złożonej
;;; (wierzchołki, atrybuty) jako listę,
;;; podobnie do funkcji (edlgetent)
(defun CPLX-LIST (grp ele / lst)
(if (= 1 (getval 66 ele))
(progn (setq ele (entnext (entity ele)))
(while (and ele (not (istypep ele "SEQEND")))
(setq lst (cons (getval grp ele) lst)
ele (entnext ele)))
(reverse lst))))
;;; PLINE-SEGS - tworzy listę segmentów polilinii
;;; jako listę zawierającą '(bulge p1 p2). Linia prosta ma bulge 0.0
;;; Punkty oblicza w ECS. Akceptuje typ LWPOLYLINE
(defun PLINE-SEGS (pname / pts segs)
(setq segs
(mapcar 'list
(if (istypep pname "LWPOLYLINE")
(group-only 42 (entget pname))
(cplx-list 42 pname))
(setq pts (getpts pname))
(rot1 pts))) ; ->[20.1]
(if (flagsetp 1 pname)
segs ;zamknieta
(butlast segs))) ;otwarta - bez ostatniego elementu, ->[20.1]
;;; Przykład (nieco zoptymalizowany dla zwięzłości kodu):
;;; dodaje wszystkie długości polilinii, CICHO
;;; Akceptuje także inne typy entycji, dodaje je do polilinii
(defun C:POLYLEN ()
(apply '+ (ssmap 'poly-length (ssget '((0 . "*POLYLINE"))))))
; zmieniona nazwa
Aby zsumować powierzchnie możesz użyć głośnego polecenia AREA lub zaimplementować wzór Herona dla powierzchni wieloboków (po prostu dla zwykłych zamkniętych wieloboków).
- [23.6] W jaki sposób odwrócić kierunek polilinii?
-
Sergei Komarov przysłał REVPOLY.LSP, który bierze pod uwagę także wypukłości i szerokości segmentów.
Zobacz xarch.tu-graz.ac.at/autocad/news/lisp_progs/revpoly.lsp.
Krótka wersja z biblioteki stdlib jest tutaj:
;;; Ignoruje informacje o szerokości segmentów
(defun POLY-REVERSE (segs)
(reverse (mapcar '(lambda (seg)
(std-make-seg (std-seg-p2 seg)(std-seg-p1 seg)
(- (std-seg-bulge-num seg))))
segs)))
(defun C:POLYREV (/ ele)
(std-require "ENTMAKE")
(if (setq ele (car (entsel "\nRevert Poly: ")))
(std-entmake-pline (entget ele '("*")) ; zachowuje dane rozszerzone
(poly-reverse (std-pline-segs ele)))))
- [23.7] W jaki sposób odczytać środek polilinii? [nowe]
-
rodek masy bryły można odczytać poleceniem MASSPROP. Możesz zapisać tę informację do pliku w celu późniejszej analizy. rodek masy polilinii jest różny, jeżeli rozpatrujemy go wektorowo. W znaczeniu geometrycznym, jako funkcja kilku punktów, jest prostszy.
(setq n (float (length pts)))
(list (/ (apply '+ (mapcar 'car pts)) n)
(/ (apply '+ (mapcar 'cadr pts)) n))
Wyznaczenie rzeczywistego środka masy jest nieco bardziej złożone. Wersja stdlib znajduje
xarch.tu-graz.ac.at/autocad/stdlib/STDPOINT.LSP STD-CENTROID-2D
W stdlib.arx lub na www.manusoft.com znajdują się także bardziej przydatne funkcje LISP, wyliczające środek masy dla brył. Następnie możesz wykonać (command "_REGION" ele)...(massprop entlast)...(command "_UNDO" 1). Za pomocą metod VLA masz także dostęp do własności massprop dla obiektów ACIS.
Co to jest wypukłość polilinii?
Wypukłość jest zdefiniowana jako tangens jednej czwartej kąta zawierającego segment krzywoliniowy. Wypukłość 0.0 oznacza segment prosty. Razem z punktem początkowym i końcowym jest to wystarczająca informacja do szybkiego obliczenia pozostałych informacji opisujących segment krzywoliniowy. Ujemna wartość wypukłości oznacza kąt liczony w kierunku ruchu wskazówek zegara ("matematycznie ujemny").
arclength = radius*angle
bulge = +/- tan( ang/4 ) (CCW: +, CW -)
angle = 4 * atan( bulge )
bulge = +/- ( 2*altitude ) / chord (CCW: +, CW -)
Zobacz też książkę "Maximizing AutoLISP" [2]
(Uwaga: drugi tom dokumentacji do R10/R11 zawiera błędną definicje wypukłości.)
(poprawione, błędny wzór! Podziękowania dla Sergeia Komarova)
;;; Zamienia wypukły element (bulge pt1 pt2) polilinii
;;; na okrąg (ctr rad). Punkty początkowy i końcowy są znane.
;;; Stąd także znane są kąty: (angle ctr pt1)(angle ctr pt2)
;;; Zwraca nil w przypadku prostego segmentu!
(defun SEG2CIR (seg / bulge p1 p2 cot x y rad dummy)
(if (zerop (car seg))
nil
(setq bulge (car seg) p1 (cadr seg) p2 (caddr seg)
cot (* 0.5 (- (/ 1.0 bf) bf))
x (/ (- (+ (car p1) (car p2))
(* (- (cadr p2) (cadr p1)) cot)) 2.0)
y (/ (+ (+ (cadr p1) (cadr p2))
(* (- (car p2) (car p1)) cot)) 2.0)
rad (distance (list (car p1) (cadr p1)) (list x y))
dummy (list (list x y) rad) ; return this, I hate progn's
)
)
)
;;; Odwrotne przeliczenie.
;;; Oblicza segment (bulge p1 p2) łuku
;;; dla danego okręgu (ctr rad), kąta początkowego i końcowego
(defun ARC2SEG (cir ang1 ang2 / p1 p2)
(setq p1 (polar (car cir) ang1 (cadr cir))
p2 (polar (car cir) ang2 (cadr cir)))
(list (arc2bul p1 p2 cir) p1 p2)
)
;;; Oblicza wypukłość łuku określonego przez punkty oraz
;;; okrąg (ctr rad) [poprawione przez Serge'a Pashkova]
(defun ARC2BUL (p1 p2 cir / ang)
(setq ang (- (angle (car cir) p2) (angle (car cir) p1)))
(if (minusp ang) (setq ang (+ (* 2.0 pi) ang)))
(tan (/ ang 4.0)))
;;; Zwraca kąt zawierający łuk (wypukłość)
(defun BUL2ANG (seg / ctr)
(- (angle (setq ctr (car (seg2cir seg))) (cadr seg))
(angle ctr (caddr seg))))
;;; Oblicza kąt zawierający łuk na podstawie jego
;;; cięciwy i promienia
(defun ARC2ANG (chord rad)
(* 2.0 (atan
(/ chord 2.0
(sqrt (- (expt rad 2)
(expt (/ chord 2.0) 2)
) ) ) ) )
)
;;; Długość łuku = promień*kąt.
;;; Uwaga na +/-, potrzebujesz (abs (arclen seg))
;;; jako definicji odległości
(defun ARCLEN (seg)
(* (cadr (seg2cir seg)) ; promień
4.0 (atan (car seg)))) ; kąt = 4*atan(bulge)
(setq *INFINITY* 1.7e308) ; największa wartość
(defun TAN (z / cosz) ; [poprawione]
(if (zerop (setq cosz (cos z))) *INFINITY*
(/ (sin z) cosz)))
(defun DTR (ang)(* pi (/ ang 180.0))) ; stopnie na radiany
(defun RTD (ang)(/ (* ang 180.0) pi)) ; radiany na stopnie
W systemie Windows jest trudno rozplanować rozmieszczenie tekstów, ze względu na czcionki proporcjonalne.
Spróbuj użyć atrybutu tabs dla wycinka list_box, tak jak:
tabs = "0 20 40";
(set_tile "listbox" "Layer:\t0\twhite")
Możesz też użyć znaków o stałej szerokości, z atrybutem "fixed_width_font":
: list_box {
label = "Drawing";
key = "dwglist";
width = 50;
fixed_width_font = true; // <-tekst o stałej szerokości znaków
}
Zapoznaj się także z procedurą zamieniającą znaki tabulacji na spacje:
xarch.tu-graz.ac.at/autocad/news/detab.lsp lub STD-DETAB xarch.tu-graz.ac.at/autocad/stdlib/STDSTR.LSP .
- [26.1] Wybieranie obiektów na podstawie ich EED funkcją (ssget "X")
;;; Zdefiniuj prefiks nazwy swojej aplikacji oraz znak rozdzielający
;;; (4-znakowa nazwa aplikacji zgodnie z wytycznymi AAIG,
;;; the Autodesk Application Interoperation Guidelines)
(setq appname "HUBU-")
;;; Zdefiniuj * dla wszystkich podtypów
(setq allappnames (strcat appname "*"))
;;; np: HUBU-LIST1, HUBU-LIST2
;;; Tutaj jest przykład sposobu odczytania listy
;;; EED dla jednego elementu
(defun GETEED-LST (ele)
(cdadr (assoc -3 (entget ele (list allappnames)))))
;;; Tutaj wybieramy wszystkie elementy zawierające dane
;;; aplikacji danego typu (znaki globalne są dozwolone)
(defun SSGET-APP (typ)
(ssget "X" (list (list -3 (list typ))))
;;; Wybiera jedynie elementy z danymi twojej aplikacji
(defun SSGET-HUBU (typ)
(ssget "X" (list (list -3 (list (strcat appname typ)))))
(ssget-hubu "*") ; spowoduje wybranie wszystkich elementów
; zawierających dane twojej aplikacji
- [26.2] Odczyt EED wybranego obiektu
Sprawdź dowolne dane rozszerzone XDATA poprzez: (entget (car (entsel)) '("*"))
Te funkcje zwracają wszystkie XDATA o pasującej nazwie aplikacji lub wszystkie XDATA o pasujących wartościach kodów DXF.
;;; Odczytuje wszystkie listy XDATA dla danego elementu,
;;; np. dla danych XDATA:
;;; (-3 ("HUBU-1" (1000 ."ASSHATCH")(1002 ."{")
;;; (1070 . 1)(1002 ."}")))
;;; =>(("HUBU-1" (1000 ."ASSHATCH")(1002 ."{")(1070 . 1)(1002 .."}")))
(defun GETXDATA (e apnlst)
(cdr (assoc -3 (entget e apnlst))))
;;; Wszystkie listy bez nazwy aplikacji
;;; => ((1000 ."ASSHATCH")(1002 ."{")(1070 . 1)(1002 ."}"))
(defun GETXDATA-ALL (e apnlst)
(apply 'append (mapcar 'cdr (getxdata e apnlst))))
Nazwa aplikacji została tutaj usunięta, ponieważ jest używana jedynie do szybkiego wykonania ssget. Różne aplikacje są rozdzielone przez różne grupy (1000 . name), tak jak to robi Autodesk.
W celu zapisu XDATA do elementu zobacz XDATA.LSP lub XED.LSP, chociaż te przykłady są nieco nieuporządkowane.
Aby poznać zaawansowane sposoby obsługi EED, np. zamianę danych ADS na listy LISP i odwrotnie, zobacz także
xarch.tu-graz.ac.at/autocad/news/eed_retrieval.txt.
Także "W jaki sposób nacisnąć Break w AutoLISP-ie?" oraz "W jaki sposób wysłać Ctrl+C do linii poleceń?"
Funkcja (command) bez parametrów działa dokładnie jak naciśnięcie Ctrl+C w DOS-ie lub Esc w Windows w linii poleceń. Ale nie zachowa się ona w sposób przypominający naciśnięcie Esc w okienku dialogowym ani nie będzie działała w skrypcie. Wywołanie funkcji (command nil) jest równoważne (command).
(command) przerywa jedynie funkcje będące poleceniami, np. jeżeli użyjesz polecenia "DIM" wewnątrz AutoLISP-u, musisz przerwać je przez (command) po zakończeniu wymiarowania.
Funkcja (command) nie przerwie wykonywania pętli w programie LISP. Istnieją inne funkcje: (exit) oraz (quit). Obie robią to samo - natychmiastowo przerywają wykonanie programu LISP.
Przykład:
(while T ; do ; wykonuj niekończącą się pętlę
(princ "\nEnter a=")
(setq a (getint))
(if (zerop a)(exit)) ; przerywa wykonywanie lispu i wraca do trybu poleceń.
)
W tym przykładzie funkcja (command) nie zadziała. Funkcja(exit) działa dokładnie jak Ctrl+C. Wyświetla "error: quit / exit abort" oraz wszystkie zagnieżdżone funkcje. Aby zapewnić "ciche" przerwanie programu, musisz do funkcji obsługującej błędy włączyć poniższy komunikat o błędzie, np.:
(setq *olderr* *error* *error* my-error)
(defun MY-ERROR (s)
(if (not (member s ;wersja angielska komunikatu:
'("Function cancelled" "console break" "quit / exit abort")))
(princ (strcat "\nError: " s))
)
(setq *error* *olderr*)
)
W przypadku skryptów należy zastosować obejście polegające na zdefiniowaniu funkcji (cancel) w lispie:
(defun SCRIPT-CANCEL ()
(command)
(command "resume")
)
oraz w SCRIPT.SCR:
..
[script commands]
(script-cancel)
[more script commands]
..
Aby umożliwić użytkownikowi zakończenie dowolnie wybranego polecenia bez pisania kodu uwzględniającego każdą możliwą opcję, po prostu powtarzaj (command PAUSE), aż polecenie zostanie zakończone.
(command "_ARC")
(while (= 1 (logand (getvar "CMDACTIVE") 1)) (command PAUSE))
Wszystkie obiekty ACIS (bryły 3D) są udokumentowane przez Spatial ("SAT Format Description"). Pomimo to wewnętrzna reprezentacja odczytywana przez (ENTGET) pozostaje zaszyfrowana, ale schemat szyfrowania został złamany (XOR 95).
Przykłady i kod są na: xarch.tu-graz.ac.at/autocad/stdlib/samples/ACIS-REGION.LSP [nowość]
Jeżeli nasunie Ci się jakieś pytanie dotyczące wykorzystania tej FAQ lub chciałbyś poprawić odpowiedź, proszę, wyślij wiadomość do Reiniego Urbana na adres: <rurban@x-ray.at> ale nie oczekuj, że odpisze.
Prawa autorskie Copyright © 1996, 97, 98, 99 do tej listy AutoLISP FAQ posiada Reini Urban.
Tłumaczenie na język polski wykonał Tadeusz Wróbel (sparrow@cad.pl) w 2000 ROKU. Prawa autorskie do polskiego tłumaczenia posiada Wydawnictwo Helion.
Przykłady kodu, jeżeli nie zaznaczono inaczej, są własnością © 1991-1997 Reiniego Urbana i mogą być swobodnie używane, kopiowane, modyfikowane i rozsyłane - ale nie sprzedawane.
Podstawowe funkcje, jeżeli nie zaznaczono inaczej, są własnością © 1991-1997 Reiniego Urbana i mogą być swobodnie używane, kopiowane, modyfikowane i rozsyłane.
Ta lista FAQ może być swobodnie dystrybuowana w całości i bez modyfikacji, w sposób gwarantujący, że niniejsza informacja dotycząca praw autorskich nie będzie usunięta. Lista nie może być sprzedawana w celu osiągnięcia zysku ani włączana do komercyjnych dokumentów (np. publikowana w celu sprzedaży na płytach CD-ROM, dyskietkach, w książkach, czasopismach lub w innej drukowanej formie) bez uprzedniej, pisemnej zgody właściciela praw autorskich. Niniejszym udziela się takiego pozwolenia na udostępnianie tego dokumentu poprzez nieograniczoną, anonimową usługę ftp w Internecie oraz szczególnie na włączanie do oficjalnej listy FAQ AutoCAD-a.
Jeżeli ta lista FAQ jest reprodukowana w inny sposób niż przez Internet (np. CD-ROM, formy drukowane, etc.), jeden egzemplarz powinien być wysłany na adres: Reini Urban, X-RAY, Nibelungeng 3, 8010 Graz, Austria.
Ten artykuł, zawartość oraz przykłady kodu są dostarczone w niniejszej formie, bez żadnych wyrażonych lub domyślnych gwarancji.
[A.1] Lokalizacja tej listy FAQ
- Wersja HTML:
- xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html
- Wersja z przypisami AcadWiki [new]:
- xarch.tu-graz.ac.at/acadwiki/AutoLispFaq
- Wersja ASCII (zawsze najnowsza, kopia wersji ostatnio rozesłanej do uczestników grup dyskusyjnych) znajduje się na stronach:
- xarch.tu-graz.ac.at/autocad/news/faq/autolisp.1
- xarch.tu-graz.ac.at/autocad/news/faq/autolisp.2
- Wersja Winhelp (spakowana zipem razem z faq-code.lsp):
- ftp://xarch.tu-graz.ac.at/pub/autocad/news/faq/autolisp.zip
- Archiwum usenetowe FAQ:
- www.faqs.org/faqs/CAD/autolisp-faq/ lub na
ftp://rtfm.mit.edu/pub/usenet-by-hierarchy/comp/cad/autocad/
- Kody LISP z tej listy FAQ:
- ftp://xarch.tu-graz.ac.at/pub/autocad/news/faq/FAQ-CODE.LSP
- Tłumaczenie na język francuski wykonane przez Rogera Roseca znajduje się na stronie:
- www.newz.net/acadplus/page5101.htm
- Tłumaczenie na język japoński wykonane przez MASAMI Chikahiro:
- www.page.sannet.ne.jp/chestnutsburr/autolisp-j.html
- Tłumaczenie na język rosyjski wykonane przez Igora Orellana:
- www.cad.dp.ua/stats/alfaq_ru.htm [poprawione]
- Tłumaczenie na język niemiecki wykonane przez Reiniego Urbana:
- xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html.de
- Częściowe tłumaczenie na język hiszpański zostało już rozpoczęte.
- Kontakt - Eduardo Magdalena.
- Tłumaczenie na język polski wykonane przez Tadeusza Wróbla dla serwisu WWW.CAD.PL:
- www.cad.pl/lisp_faq.html
- Odpowiednie listy FAQ Autodesku:
- AutoCAD Techsupport
[zmienione] Search AutoCAD+FAQ
Support Assistant 2000 [poprawione]
- Grupy dyskusyjne Autodesku [zmienione]
- news://discussion.autodesk.com/autodesk.autocad.customization,
na Google
lub WebX interface na nowym serwerze grup dyskusyjnych Autodesku.
Ta lista FAQ istnieje dzięki wielkiemu wysiłkowi społeczności comp.cad.autocad; na szczególne uznanie zasługują:
Tom Berger, Adi Buturovic, Christoph Candido, Mike Clark, Miles
Constable, Cara Denko, T.J. DiTullio, Chris Ehly, Jeff Foster, Rusty
Gesner, William Kiernan, Paul Kohut, Sergei M. Komarov, Joseph
M. Liston, Lu, Masami Chikahiro Georg Mischler, Desi Moreno,
Vladimir Nesterovsky, Roger Rosec, Serge Pashkov, Dennis Shinn, Tony
Tanzillo, Eugene Tenenbaum, Reinaldo Togores, Reini Urban, Serge
Volkov, Morten Warankov, Owen Wengerd, Alan Williams, Doug Wilson,
Ian A. White, David Whynot, Darren Young, Xiang Zhu oraz wielu innych.
- 18 czerwca 2001
- poprawiono deja.com na groups.google.com
- 23 kwietnia 2001
- aktualizacja odnośników
- v2.28 4 kwietnia 2001
- Zmiana adresu rurban@sbox... na rurban@x-ray.at (stary przestanie funkcjonować w przyszłym roku).
- Wszystkie części FAQ są dostępne w formacie AcadWiki.
- v2.27 styczeń 2001
- Pierwsze tłumaczenie w języku polskim (oryginał: wersja v2.27 z dnia 23 września 2000).
Opis wcześniejszych zmian, dotyczących tekstu oryginalnego, można znaleźć na stronie http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html#C.
|