comp.cad.autocad AutoLISP FAQ (deutsche Übersetzung)
URL: http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html.de
Version: 2.28
Last-modified: "2002-06-25 08:44:51"
Posted-By: Reini Urban <rurban@x-ray.at>
Posting Frequenz: wird nicht geposted
Copyright: siehe Appendix [A]
Willkommen beim comp.cad.autocad AutoLISP FAQ!
AutoLISP ist eine Skriptsprache für AutoCAD, ein bekanntes CAD Programm.
Dieses AutoLISP FAQ wird jeden Monat in comp.cad.autocad, alt.cad.autocad und
in den *.answers newsgroups gepostet.
Es gibt ein paar AutoCAD FAQ's bei Autodesk (
"Suche nach AutoCAD+FAQ"),
die werden aber nicht nach comp.cad.autocad oder de.comp.cad geposted.
Der Inhalt und die Beispielprogramme sollten bei allen AutoCAD Versionen ab R10
funktionieren, einschließlich den Versionen für die Lispcompiler Visual LISP, Vital Lisp und ACOMP.
Es gibt keine spezielle AutoLISP Diskussionsgruppe.
Die besten sind comp.cad.autocad, autodesk.autocad.customization und de.comp.cad.
comp.lang.lisp hat nichts mit AutoLISP zu tun.
Sourcecode von allen Funktionen dieses FAQ's ist in FAQ-CODE.LSP
(siehe [A.1]).
Dank alle Kollegen! Korrekturen und Beiträge
(an rurban@x-ray.at)
sind immer willkommen.
(| Änderungen,
+ Neue Punkte in dieser Version, vorläufige
Kommentare und Unsicherheiten sind in <..>)
- Teil 1: Allgemeines
- [0] Die Zukunft von AutoLISP? Soll ich nicht lieber Visual Basic lernen?
- [0.1] Was ändert sich mit AutoCAD 2000?
- [0.2] Warum kann man keine ARX mehr erzeugen?
- [1] Wo gibt's AutoLISP Programme im Internet?
- [1.1] Werden die comp.cad.autocad Artikel irgendwo archiviert?
- [1.2] AutoDESK's SDK
- [2] Was sind die besten Bücher um AutoLISP zu erlernen?
- [2.1] Online AutoLISP Dokumente, Windows Hilfe [veraltet]
- [2.2] AutoLISP Programmierstil
- [3] Wie debugge ich AutoLISP Programme?
- [3.1] Richtige AutoLISP Debugger
- [3.2] Modularer Stil, TRACE
- [3.3] break Funktion, debug print
- [4] Wie schütze ich AutoLISP Programme?
- [4.1] Kelvinate
- [4.2] Protect
- [4.3] Kelvinate und Protect
- [4.4] Convert
- [4.5] ACOMP
- [4.6] Vital Lisp Professional
- [4.7] Lisp2C
- [4.8] Visual Lisp von Autodesk
- [5] AutoLISP Compiler?
- [5.1] ACOMP
- [5.2] Vital Lisp Professional
- [5.3] Visual Lisp von Autodesk
[5.4] Bessere Lisp's: Common Lisp und Scheme
[6] AutoLISP Editoren und andere Utilities
- [6.1] AutoLISP Editoren
- [6.2] Analyzer, Packager und Klammernprüfer
- [6.3] Pretty Printer
[7] Probleme und Fehler mit AutoLisp [Änderungen]
[8] Sortieren mit AutoLISP [Änderungen]
[9] Rekursion
[10] Iteration mit MAPCAR,...
[11] S::STARTUP, Mein LISP wird beim Start nicht mehr geladen [Änderungen]
[12] Wie funktioniert AUTOLOAD?
[13] Wie kann ich eine variable Anzahl von Parametern an Lispfunktionen übergeben?
[14] Wie vermeide ich "Stack Overflows"? [Änderungen]
[15] (command "ROTATE3D") funktioniert nicht! Warum?
[16] Lisp Programme über mehrere Zeichnungen laufen lassen
[17] Wie exportiere ich interne Visual Lisp Funktionen nach AutoLISP/AutoCAD?
Teil 2: Beispiele, Quellcode
[20] Allgemeine Hilfsfunktionen
- [20.1] Listen
- [20.2] Zeichenketten
- [20.3] Symbol->String
- [20.4] AutoCAD Elementzugriffe
[21] Beispiel Programme:
- [21.1] Ersetze Texte global, mehrere Polylinien, Layer Utilities, datestamp, ...
- [21.2] Starte den Plotdialog von Lisp aus. Verwendung von DDE
- [21.3] (entmod) und (entmake) für Layer, ohne (command "_LAYER"...)
- [21.4] Auswahl von mehreren Dateien mit Lisp? (wie zB. in DATEIEN - Entsperren)
- [21.5] Ersetze mehrere Blöcke
- [21.6] (vports), VIEWPORT Element, Pixel Konversion
- [21.7] Auswahl aller sichtbaren Elemente: ZOOM Koordinaten
- [21.8] Wie schreibe ich die XYZ Daten von Elementen in eine Datei?
[22] Block Attribute
- [22.1] Zugriffsmethoden zu Block Attribute mit AutoLISP?
- [22.2] Wie ÄNDERE ich Block Attribute? (DATESTAMP.LSP)
- [22.3] Wie UPDATE ich Block Attribute?
- [22.4] Wie erzeuge ich Blöcke mit ENTMAKE?
[23] Polylinien
- [23.1] Zugriffsmethoden zu Polylinien Knotenpunkten (VERTICES)?
- [23.2] Wie VERBINDE ich automatisch mehrere Polylinien?
- [23.3] Wie ändere ich die BREITE von mehreren Polylinien?
- [23.4] Erzeugung von Polylinien oder Splines mit (ENTMAKE) oder (COMMAND)
- [23.5] Wie messe ich die Länge von Polylinien?
- [23.6] Wie drehe ich die Richtung von Polylinien um (REVPOLY.LSP)?
- [23.7] Wie errechnet man das Zentrum einer Polylinie? [neu]
[24] Kreis/Bogen Geometrie: BULGE Konversion. Ein bißchen Trigonometrie
[25] DCL: listboxen mit TABS oder MONOTXT Schriften
[26] EED Extended Entity Data: Zugriff und Speichern
- [26.1] Wähle Objekte über EED mit (ssget "X")
- [26.2] Zugriff auf Objekt EED's
[27] Wie breche ich in Lisp einen Befehl ab?
[28] Wie entschlüssele ich die interne ACIS Geometrie mit Lisp?
--
[A] Urheberrechtliche Bemerkungen
- [A.1] FAQ Links
[B] Danksagungen
[C] Revisionsliste
AutoLISP wird definitiv weiter unterstützt in allen zukünftigen Releases.
Der Sprache an sich scheint nicht weiterentwickelt zu werden. VB wurde eingeführt
um die Office Anpassung zu unterstützen: ACAD <-> Excel-Access
Beide Sprachen haben Vor- und Nachteile. Du solltest Dir beide anschauen.
VB scheint mehr "grafischer" und AutoLISP "logischer" zu sein.
VB ist sicher schneller zu lernen, weil die Objektstruktur sehr übersichtlich ist.
Das neue VBA (ab dem Update R14.01) ist extrem schnell. Siehe auch [5.2].
Die Zukunft von AutoLISP heißt bereits Visual LISP. Siehe dazu [0.1].
Der Name :) Nein, da ist viel mehr. Man nennt es Release 2000, R15
(15 ist die Versionsnummer und nicht die Release Nummmer), A2000 oder
abgekürzt A2K. ('A 2 Kilo')
Der neue Visual Lisp Kernel ersetzt den alten (xlisp) AutoLISP Kernel.
Welche Probleme solltest Du mit Visual Lisp in A2000 erwarten?
In http://xarch.tu-graz.ac.at/autocad/docs/r2000-news.txt
ist mein White Paper'. Benutze den LCA (LISP Compatibility Analyzer von den Migration Tools) um
deine Lisps zu prüfen.
Die wichtigsten Punkte sind:
- Strengere Fehlerprüfung beim Laden,
- ACAD.LSP vs ACADDOC.LSP,
- Man kann/braucht keine ARX mehr,
- Inkompatibilitäten AutoLISP - Visual LISP:
- Lisp Funktionen sind Atome, keine Listen mehr,
- Geschützte Symbole,
- Erweiterte Ausnahmenbehandlung,
- Pfadname der geladenen VLX?,
- vl-export-symbol -> vl-doc-set ...,
- Lange Acad Symboltabellennamen: EXTNAMES
- ActiveX Automatisierung, VARIANT und SAFEARRAYs
- FAS4 kann mit R14 nicht geladen werden
Mit AutoCAD 2000 kann man keine ARX Programme mehr erzeugen, wie mit
VLISP 4 oder Vital Lisp. Das hat technische und formale Gründe.
Dagegen erzeugt man jetzt VLX ('Visual Lisp Extension'), das dieselbe
Funktionalität gegenüber kleinerem Overhead bietet.
Die Unterschiede im Detail:
- Man muss die Anwendung mit (LOAD) laden. Vorher mit (ARXLOAD).
- + Die Initialisierung ist einfacher. Das VLX stürzt bei
einem Ladefehler nicht komplett ab, wie bei ARX, mit mysteriösen Fehlermeldungen.
- + VLX sind viel kleiner die sie nicht mehr die komplette VL Runtime VLRTS
beinhalten. Der Kernel VL.ARX ist bei mit acad dabei, man kann viel
kleinere Anwendungen ausliefern.
- - Von einem geladenen VLX kann man nicht mehr einfach den Pfadnamen der
Anwendung finden. Vorher hatte man (ARX) oder (VL-EXE-FILENAME).
- VLX bietet getrennte oder gemeinsame Namensbereiche ('namespace').
Mit ARX hatte man nur getrennte Namensbereiche, noch schlimmer, komplett
getrennte Lisp Umgebungen.
- + Man kann jetzt die schnellste und sicherste Kompilierungsoption
(LINK, DROP) verwenden bei gemeinsamen Namensbereichen. Das vereinfacht die
Kommunikation. Die meisten Anwendungen profitieren davon.
- + ARX ist nur Acad Release kompatibel, also komplett inkompatibel.
VLX ist neu, daher nur kompatibel zu neueren Releases (R16,...) aber
als Lispanwendung bei weitem mehr kompatibel als ein ARX.
- Geladene ARX Anwendungen geben mit (ARX) den Dateinamen zurück, geladene
VLX Anwendungen mit (VL-LIST-LOADED-VLX) nur ein Symbol, nicht den Pfad.
Das kann ein Problem sein.
In Summe: Man braucht keine ARX Module wie mit VLISP 4 oder Vital Lisp mehr.
Das ist ein Fortschritt, keine Rückschritt.
Die großen AutoCAD Tools Server sind:
- AutoCAD Plugin Store auf beyond.com.
- Das ist die von AutoDESK "offiziell" empfohlene Seite.
- CADalog - Das AutoCAD Shareware Clearinghouse (Mike Clark)
- http://www.cadalog.com
- The CAD Depot, früher bekannt als "CADSyst" und
"Rolling Stock Software" (David Whynot)
- http://www.caddepot.com/,
vor kurzem von
TenLinks.com gekauft.
Diese sind spezialisiert in AutoCAD Software und haben eine sehr gut
sortierte AutoLISP Sammlung. Andere professionelle AutoLISP Shareware
Server posten Ihre URL's auch in die Newsgroups.
Andere relevante Internet Portale sind:
TenLinks und
das UpFront Ezine (auch auf deutsch) sind die besten CAD news services.
Autodesk startete mit ihrem Portal Point A.
Einige andere Server mit AutoLISP Sammlungen sind:
- xarch AutoCAD Info & Tools (Reini Urban)
- http://xarch.tu-graz.ac.at/autocad/
(mit Suche)
-
CAD Users Webring [neu]
-
CADalyst Magazin code (gesammelt von "Hot Tip Harry" Art Liddle)
- http://www.cadonline.com/code/
-
CADshack (Jeff Foster)
- http://www.cadshack.com/lispfile.htm
-
Owen Wengerd
- http://www.manusoft.com
-
Terry Dotson
- http://www.dotsoft.com/
-
Vladimir Nesterowsky
- http://members.tripod.com/~vnestr/
-
UCCB AutoCAD and AutoLISP page (Paul Standing)
- http://ucad1.uccb.ns.ca/acad/cad.htm
-
Theo L.A. Groenenberg
- http://members.xoom.com/acadvice/autolisp.htm
-
Lisp Factory (Jay Garnett)
- http://www.enteract.com/~jgarnett/
-
Rakesh Rao - AutoCAD Tech Center
- http://www.4d-technologies.com/techcenter
Veraltete oder nicht funktionierende Links:
-
AutoCAD Tech Journal code (Peter Sheerin) [alt]
- http://www.atj.com
-
CADENCE magazine code (Peter Sheerin) [alt, broken]
- ftp://ftp.mfi.com/pub/cadence/
-
McNeel's lisp archive [fixed]
- ftp://ftp.mcneel.com/pub/lisp/
-
Dr.Lisp Utilities (Alexander Medwedew)
- http://tribeca.ios.com/~compvent/drlutils.html
-
Bob Jones [broken]
- http://www.io.com/~bcjones/files.html
-
PIRS Online
- http://www.insa.com/
-
Henry Francis [broken]
- http://www.ez-sys.net/~coopfra/
-
Desi Moreno [broken]
- http://www.invsn.com/desmos/autolisp.htm
-
Das SimTel - Coast To Coast - Archiv [uralt, fixed]
- http://www.simtel.net/simtel.net/msdos/autocad.html
Auf http://www.autodesk.com/support/autocad/
gibt's offizielle Seiten vom Autodesk Product Support, die technische Fragen erörtern. ("Ihr FAQ")
Es gibt kein offizielles comp.cad.autocad Archiv, aber es gibt einige Suchmaschinen,
die Newsartikel speichern.
Im Einzelnen:
- groups.google.com/ -
Das größte und beste News Archiv. [neu]
- Vorher bekannt unter deja.com/usenet.
- http://www.altavista.com/
- http://www.altavista.com/cgi-bin/query?pg=aq&what=news
- http://www.excite.com/
- http://www.excite.com/search.gw?collection=news
- Phoaks - People Helping One Another Know Stuff - Automatic Links Extractor
- http://www.phoaks.com/phoaks2/newsgroups/comp/cad/autocad/index.html
Die Autodesk Diskussionsforen haben auch eine Suchfunktion,
discussion.autodesk.com.
Einige spezielle News Postings gibts auch auf
http://xarch.tu-graz.ac.at/autocad/news/contents.html
Bis einschließlich Release 12 war ein Software Development Kit (SDK) von AutoDESK
erhältlich. Das SDK2 war auf der CD für alle internationalen R12 dabei.
Es beinhaltete viel ADS und AutoLISP Quellcode und Bibliotheken.
Ab R13 gibt es ein spezielles Entwickler Netzwerk, vergleichbar
dem Microsoft's, das ADN (AutoDESK Developer Netzwerk).
Die vierteljährlichen CD's sind vergleichbar mit
dem alten ADK, aber wenden sich hauptsächlich an professionelle
ARX/ObjectARX Entwickler.
Kontaktiere das nächstes AutoDESK Hauptquartier um Mitglied zu werden.
Einige Lisp Bibliotheken sind auch auf
http://xarch.tu-graz.ac.at/autocad/code/adesk/SDK2
In den Staaten kostet die ADN Mitgliedschaft US $600.00 pro Jahr.
Die CD's beinhalten kein SDK per se,
aber das meiste vom alten SDK ist in der einen oder anderen Form enthalten. (Owen)
- "AutoLISP Referenz Handbuch"
- von AutoDESK.
Weiters auf Englisch:
- AutoLISP to Visual LISP [neu]
- 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 and Mark Middlebrook, Tony Tanzillo.
Mehr bei http://www.group-a.com/~rusty
Es gibt viele andere AutoLISP Bücher.
Empfehlenswerte generelle LISP Bücher (nicht AutoLISP!) sind:
- ANSI Common Lisp,
- Paul Graham, Prentice Hall. Auch auf deutsch.
- LISP, 3rd Ausgabe,
- Patrick Henry Winston und Berthold Klaus Paul Horn, Addison-Wesley Publishing Company.
Auch auf deutsch.
- Looking at LISP,
- Tony Hasemer, Addison-Wesley Publishing Company, ISBN 0-201-12080-1
Die meisten Beispielprogramme, die in verschiedenen Magazinen und auf Webseiten
publiziert wurden, sind formal sehr schlecht geschrieben. Deshalb ist AutoLISP auch
für Anfänger recht schwierig zu erlernen.
Lisp ist sowieso schwer zu lesen, wegen der Kürze und den endlosen Klammern.
Gerade auch deshalb sollte jeder klaren, lesbaren Code schreiben.
Die AutoDesk Beispiele sind ziemlich gut geschrieben, aber manchmal übertreiben auch Sie :)
Es gibt Lisp Formatierer ("pretty printers") oder sogenannte "beautifier" (siehe
[6.3]) die Code automatisch nach dem Standard formatieren.
Es gibt eine exzellente Beschreibung von AutoDESK über "coding, commenting and
intentation standards" (auf englisch) um Lispcode lesbar zu halten. Es ist auf der R12 CD-ROM
im SDK2: ACG.DOC oder auf
http://xarch.tu-graz.ac.at/autocad/docs/acg.txt
Die wichtigsten Punkte sind:
- Benütze Kommentare
Benutze ";;;" in Spalte 1, ";;" innerhalb einer Funktion (indentiert)
und ";" für Endkommentare (in Spalte 39)
- Befolge die Indentierungsregeln wie sie "pretty printer" anwenden,
um besser strukturierten Code zu schreiben und lesbarer zu machen.
- Besonders für SETQ, DEFUN, IF, COND, PROGN
- Vermeide globale Variablen. Wenn schon (wegen der Effizienz),
dann setze sie großgeschrieben zwischen Sterne, z.B. *GLOBAL*
- Vergesse nicht deine Variablen zu lokalisieren! (setze sie hinter das / in der DEFUN
Parameter Liste). Nur fuer Debugging Zwecke darf man sie temporaer auskommentieren.
- Name protection: Da AutoLISP Symbole nicht geschuetzt sind, ist es leicht sogar
Systemfunktionen unabsichtlich zu ueberschreiben. Benuetze daher persoenliche
Prefixes, wenigstens wenn du den Quellcode veroeffentlichst oder weitergibts.
Ich benutze UR- fuer Funktionen und UR: fuer Variablen. Die ADGE und adesk
empfehlen sogar 4 Buchstaben Prefixes. Nur dann sind deine Symbole sicher vor anderen
Kamikaze Funktionen.
- Benutze IMMER den Unterstrich bei jedem Befehl oder Option bei (command) oder (osnap).
Es gibt leider schon genug Kommerzielle Programme die nicht in allen internationalen Versionen funktionieren.
(command "_PEDIT" ss "_J") anstatt (command "PEDIT" ss "J")
- Übertreibe nicht mit zu vielen SETQ's: Lisp war
ursprünglich eine funktionale Sprache, ohne Variablen. Es kostet
Speicher und Zeit. Die Sprache ist reich genug um auch komplett ohne
Variablen zu arbeiten, oder Zwischenwerte immer abzuspeichern. (siehe
auch die Beispiele [21]...)
Aber aus Gründen der
besseren Lesbarkeit und zum Debuggen sollte man immer Variablen
verwenden.
- Eine alte Lispregel lautet: Jede gute Funktion ist nicht länger als 6 Zeilen
(Und Lisp ist die zweitälteste Programmiersprache, entwickelt von John McCarthy am MIT um 1958)
- Besser CONS als APPEND: Drei CONS und ein REVERSE sind besser als ein APPEND.
Aber es gibt einige Tricks (zB. NIL auszulassen) die den Einsatz von APPEND favorisieren.
(siehe besonders Serge's Beispiel: remove [20.1] oder zum
Vergleich [23.1])
- Verwende englische Symbolnamen und Kommentare
- Verwende nicht T,MIN,MAX oder LAST als Symbolnamen. Das sind Systemfunktionen!
- Vital Lisp Professional und Visual Lisp haben einen grafischen Debugger
in der IDE (am besten).
- ACOMP für R10 hatte einen, gratis, aber man kann ihn immer noch benutzen,
wenn man nur R10 Funktionen benutzt, und kein WCMATCH
- Ld, AutoLISP Debugger für R14, R13c4 und R12/Dos aus cz (gratis)
- auf http://www.cadstudio.cz/ftp.htm
Siehe auch [5] AutoLISP compiler?
Am besten teilt man seine Programme übersichtlich in Funktionen ein, im Gegensatz zum Spagetticode,
um Unterfunktionen mit TRACE Funktionsaufrufe, Argumente und Rückgabewerte verfolgen zu können.
Außerdem kann man solche Funktionen auch immer weiterverwenden.
Beispiele:
;;; Debugging Funktionen
(defun BREAK (s)
(if *BREAK*
(progn
(princ "BREAK>> (Ende mit )\nBREAK>> ")(princ s)
(while (/= (setq s (getstring "\nBREAK>> ")) "")
(print (eval (read s)))))))
(defun DBG-PRINT (s) ;akzepiert Atome und Listen
(if *DEBUG*
(if (listp s)
(mapcar 'print s)
(print s))))
(defun C:DEBUG () (setq *DEBUG* (not *DEBUG*))) ;schalte es aus und ein
(defun C:BREAK () (setq *BREAK* (not *BREAK*)))
(defun CONT () (setq *BREAK* nil)) ;Weitere Ausführung ohne Unterbrechung
;;; Beispiel
(setq *BREAK* T *DEBUG* T)
(defun C:TEST ()
(foreach x '("1" "1.0" "1e-3")
(break "in foreach") ; stoppt Evaluierung wenn *BREAK* ein ist,
; man kann jedes symbol eingeben (ohne !)
; und der Wert wird ausgedruckt
(setq x (atof x)) ; mache etwas mit x
(dbg-print x) ; Das druckt x aus, wenn *DEBUG* ein ist.
)
)
Befehl: TEST
BREAK>> (Ende mit ) ; in der Break Schleife
BREAK>> in foreach
BREAK>> x ; wie ist der Wert von x?
1.0
BREAK>> (CONT) ; schalte break aus
nil
BREAK>> ; weiter mit dem Programm
1.0
1.0
0.001
Du kannst auch die Debugging Ausgabe in der Breakschleife mit
BREAK>> (setq *DEBUG* nil)
ausschalten, um größere Schleifen zu beschleunigen.
Bist du dir sicher? Wenn du sie deine Freunden weitergeben willst, warum
nicht den Quellcode? Geschützt ist der Quellcode sowieso durch das Urheberrecht,
und Zusammenarbeit kann dir sehr weiterhelfen.
Einige der besten Tools sind welche die meine Freunde verbessert haben oder ich habe welche meiner
Freunde verbessert. zB. Linux wurde nur so groß, weil viele daran weiterentwickeln können.
-
[4.1] Kelvinate
- Mit kelv.exe (auf der R12 CD-ROM oder auf den großen AutoLISP Servern
[1])
De-Kelvinate Lisp's mit einem pretty printer.
Aber Symbolnamen bleiben unleserlich und Kommentare bleiben verloren.
-
[4.2] Protect
- Mit protect.exe (auf der R12 CD-ROM oder auf den großen AutoLISP Servern
[1])
Beachte: Es gibt freie Entschlüsselungsprogramme.
-
[4.3] Kelvinate und Protect
- Kelviniere zuerst dein Programm um es unlesbar zu machen, dann
verschlüssle es mit protect.
-
[4.4] Convert
- Shareware Lisp En-/Decryptor von Maciej Lukasiewicz
Mit Convert verschlüsselte "Protected Lisps" können nur mehr von Convert selber
entschlüsselt werden.
Decryptor v2.0 sollte nicht mehr verwendet werden.
-
[4.5] ACOMP
- AutoLISP compiler acomp.exe
(mit dem R12 International Release oder auf den AutoLISP Servern)
Mehr Dokumentation über acomp gibt es auf
http://xarch.tu-graz.ac.at/autocad/bi4
Siehe auch [5.1] AutoLISP compiler?
-
[4.6] Vital Lisp Professional
- http://www.basissoftware.com/vill.htm
sprich "ViLL", veraltet, lebt als Visual Lisp weiter.
Siehe auch [5.2] AutoLISP compiler?
-
[4.7] Lisp2C
- Lisp nach C Konverter, für R12/R13/R14 Dos/Win, für Watcom, Metaware, MSVC C/C++ Compiler.
http://www.basic.si
-
[4.8] Visual Lisp von Autodesk
- sprich "VLISP". Die Zukunft. Siehe dazu [5.3]
Sicherheit des FAS Formates:
Es gab eine längere Diskussion in beiden Newsgruppen über die Sicherheit des
FAS Formates initiert von Tony Tanzillo. Anscheinend gibt es einen FAS Decompiler
der "lesbaren" Quellcode erzeugt, aber diesen Decompiler gibt es nicht am Netz.
Weitere Gerüchte sprechen seit Jahren von einem MNC Decompiler.
Linked and Dropped FAS/VLX (kompiliert mit Optimized/Internal) ist ähnlich der
Kelvination. Symbolnamen, Zeichenketten und Zahlen sind nicht so sicher wie Algorithmen.
Zusammenfassend:
Seriöse Verschlüsselung wird jetzt sogar von Autodesk mit Visual LISP unterstützt.
Kelvinierung [4.1] macht Programme nur unleserlich und schneller zu laden.
Protected [4.2] Lisp Programme sind leicht zu entschlüsseln, BI4 und FAS nicht.
Mit Convert -e$GUARD verschlüsselte Lisps können nur mit Convert wieder
entschlüsselt werden.
Es gibt drei AutoLISP Compiler, bessere vielleicht in der Zukunft. Einige
Lisp und Scheme Platformen unterstützen bereits oder werden in naher
Zukunft ActiveX Unterstützung oder ein einfaches FFI bieten.
-
[5.1] ACOMP
- ACOMP wurde bis R12 nur für die Internationalen Releases von AutoDesk offiziell
unterstützt. Es war gratis und funktioniert nicht mehr ab R13 oder dem englischen R12/Windows.
Es erzeugt .BI4 Programme und benötigt ein spezielles ACADL.EXP (namens ACADLC.EXP).
Mehr siehe unter http://xarch.tu-graz.ac.at/autocad/bi4
Die Compiler Warnungen zu lokalen Variablen sind besser als bei ViLL/VLisp.
-
[5.2] Vital Lisp Professional
- von Basis Software Inc. USA.
Lizenz-freie Runtime Module für R12/R13/R14 DOS/Windows/NT
Basis entwickelt Vital Lisp nicht weiter, es wurde an AutoDESK als Visual Lisp verkauft.
Siehe auch [6.1] und [4.6]
-
[5.3] Visual Lisp von Autodesk
- VLISP 4, der Nachfolger von Vital Lisp, ist intern gleich wie ViLL 3.2.
Nur die Oberfläche, einige Funktionsnamen und die Hilfe wurde verbessert:
vill- => vlisp-, vlx- => vl- prefixes. Einige vlax- Funktionen
haben mehr Bindestriche ("konsistente Hyphenierung").
Mit AutoCAD 2000 ersetzte VLISP den alten AutoLISP Kernel. Siehe [0.1]
VLX Dateien sind FAS Dateien mit optionalen DCL Resourcen für A2000 oder R14 mit geladenem RTS.
A2000 FAS/VLX sind zu vorigen Versionen inkompatibel
(FAS2 -> FAS4) weil neue Sprachfeatures hinzugefügt wurden (zB. getrennte Namensräume).
-
[5.4] Bessere: Common Lisp und Scheme
- Es gibt ein ARX für Corman Common Lisp (eine einfache Textkonsole),
COM Unterstützung gibt es auch für Allegro Common Lisp 5 (ACL5), Lisp Works for Windows (LWW)
und bald gibt es VisualScheme mit AutoCAD Unterstützung.
Mittels FFI
("Foreign Function Interface") kann fast jedes Lisp oder Scheme
mit AutoCAD kommunizieren.
Etwas Unterstützung gibt es für Corman Lisp und ACL5, momentan verwendet ein kommerzielles Product
ACL5: "Design++" von Design Power.
Siehe http://xarch.tu-graz.ac.at/autocad/bi4/.
Zusammenfassend:
AutoLISP Compiler kompilieren wie Java, VB oder manch andere Lisp Compiler
zu Bytecode, die ein externes Runtime System (RTS) benötigen. Man kann keine
selbstständigen Programme (EXE) erzeugen, mit ViLL und VLisp (<= R14) aber ARX Programme.
Die Variablen sind verschlüsselt.
- Visual Lisp von Autodesk
- siehe [5.3].
Das beste und empfehlenswerteste Lisp Tool. Mit
AutoCAD 2000 ist es inkludiert.
- Emacs für NT
- Riesiger Editor und recht eigenwillig zu erlernen, aber er kann beliebig
erweitert werden, mit elisp, das sehr ähnlich zu AutoLISP ist. Die Mutter aller Editoren.
Gratis, für alle Platformen. Gibt es in zwei Varianten, XEmacs oder GNU ntemacs.
AutoLisp Mode auf
http://xarch.tu-graz.ac.at/autocad/lsp_tools/ntemacs.html.
- Vital Lisp Abgelöst von Visual Lisp, und nicht mehr erhältlich.
- Es gab eine "Lite Edition" (nur Editor) für US $50,
eine "Standard Edition" (+ Debugger) für US $350
und die "Professional Edition" für US $675 (+ Compiler, Zusatzbibliotheken).
Siehe [5.2] AutoLISP Compiler?
- LispPad
- AutoLISP Editor von Tony Tanzillo.
http://ourworld.compuserve.com/homepages/tonyt/LispPad.htm
Eine Vorabversion war im Buch Maximizing AutoCAD R14,
http://www.group-a.com/~rusty
- LispLink 2000
- Kommerzieller AutoLISP Editor mit Syntax Hervorhebung, Klammernprüfung,
Projekt Manager, Dialog Vorschau, Visual LISP Funktionsunterstützung und FAS Kompilierung.
http://www.caelink.com/
- CodeMagic
- Shareware Texteditor mit AutoLISP Syntax Hervorhebung.
- Visual Lisp von WSSW
- Alter kleiner Windows Lisp Editor, nicht zu verwechseln mit Autodesk's Visual LISP IDE.
Die alte Version 1.0 gibt's frei am Netz. Siehe [1]
- WCEDIT 2.02
- ADS Editor für DOS R12. Kann Lisp Code evaluieren innerhalb des Editors, frei.
Siehe [1]
- CODEKEY
- Alte kommerzielle DOS IDE. Interner Pretty Printer, Protector, Unprotector,
Kelvinator.
- ALLY 3.0 und CADET
- Shareware Lisp Analyzer und Editor.
Siehe [6.2]
- pred
- Gratis, sehr kleiner DOS Editor mit Klammern Ausleuchtung.
At ftp://xarch.tu-graz.ac.at/pub/autocad/lsp_tools/pred.zip
ADE ist so ähnlich.
- Allgemeine benutzeranpassbare Programmier Editoren wieMultiEdit Pro 7,
WinEdit, E!, TextPad, UltraEdit oder PFE werden auch recht häufig benutzt.
- Diese unterstützen keine Lisp Syntax Prüfung oder "pretty printing", aber
Suchen/Ersetzen über mehrere Dateien (einige sogar mit regulärten Audrücken) und anpassbare Syntax und Schlüsselwort Hervorhebung.
Externe Klammern Prüfer werden eigentlich nicht mehr benötigt, das sollte
im Editor passieren.
Analyzers erzeugen Funktions Kreuzreferenzen, Aufruf- und 'Reverse' Aufrufbäume
Packager generieren automatisch Bibliotheken aus verschiedenen Quelldateien.
es gibt momentan keine 'code-walker', der COMMAND Zeichenketten Internationalisiert
(Englisch->Deutsch Übersetzung), aber seit A2000 gibt es einen Lisp Analyzer (LCA).
- VLISP's [5.3] Kompilierer analysiert (kompiliere mit 'full messages') und
prüft Klammern (Ctrl-Alt-C).
- Reini's AutoLISP Packager [new]
http://xarch.tu-graz.ac.at/autocad/lsp_tools/#Packager
Browsable Funktions Cross-Referencer, reverse calling tree, erzeugt automatische
Projekbibliotheken von Quelldateien. ("Packager" oder "Function Shaker")
- PEI's Findvars [new]
Ähnlich dem Packager, aber analysiert nicht nur Funktionen, auch Variablen
http://www.perceptual-eng.com
- RapidLisp
v1.0c, Shareware Lisp analyser für R14. (in deutsch)
http://www.cps.de/cad/rapidlisp/
- AVC - AutoLISP Variable Collector
Freeware, findet alle undeklarierte Variablen.
http://users.actcom.co.il/sysoft/vc.htm
- LCA - Autodesk's AutoLISP Compatibility Analyser
Auf der AutoCAD 2000 Migration CD.
Findet automatisch AutoCAD 2000 Kompatibilitätsprobleme in LSP oder MNL Dateien.
- ALLY30.ZIP (alt)
- Shareware AutoLISP Analyzer, prüft Syntax und erstellt Statistiken.
(wie Funktionsabhängigkeiten), siehe [1]
- lck21b.zip (alt)
- LCK Lisp Prüfer 2.1b (grafisch)
- paran.zip (alt)
- einfach
- PARNCH.ZIP (alt)
- einfach
Es gibt auch einige Lispprogramme, um Klammern zu zählen.
extern:
- LB.EXE
- AutoDESK's offizieller Source Sode Beautifier
im SDK2 oder auf [1]
- FMT202S.ZIP
- Lisp, DCL und FRM Source Code Formatierer
- PPRINT.LSP
- im SDK2 oder auf [1]
intern:
Emacs, Visual Lisp, Vital Lisp und Codekey haben interne "Beautifier"
(automatische Identierung), soviel ich weiß.
Für AutoCAD 2000 und unerfahrene VLISP Benutzer siehe [0.1].
Es gibt fast keine ernsten AutoLISP Fehler (Bugs). Der Sprachinterpreter an sich
(ACADL.EXE,.EXP,VL.ARX) funktioniert zweifelsohne fehlerfrei. Aber es gibt einige
Einschränkungen in Zusammenarbeit mit dem Acad Subsystemm ActiceX oder Proteus (DCL).
Und es gibt manchmal einige fehlerhafte SUPPORT Lisp Programme. (z.B. DDMODIFY.LSP)
Für Visual Lisp siehe unbedingt das README.txt das alle bekannten Fehler und Einschränkungen auflistet.
Abstürze mit Reaktoren (SCHIEBEN, STRECKEN, ...) sind AutoCAD Fehler.
- + LDATA von Tom Berger (VLISP für R14 und A2000)
- In Kürze: Verwende überhaupt keine LDATA! Sie können DXF und DWG Dateien in
A2000 zerstören. Es ist auch SEHR schwierig sie wieder loszuwerden.
- Listen Argumente mit DOTTED PAIRS
beim Im-/Export von AutoLISP nach Visual LISP oder zurück können ihre äußeren
Klammern verlieren!
- Siehe das Visual Lisp README (undokumentiert in Vital Lisp)
- Falsche Rückgabe von SINGLE ATOM LISTS von externen Anwendungen
- Visual LISP kann nicht zwischen einer LISTE mit einem einfachem ATOM
(ein Element) und einem einfachem ATOM bei der Rückgabe von einer externen
ObjectARX oder ADS Anwendung unterscheiden.
Es verliert dadurch eine Klammernebene, wie oben.
- ENTGET mit LWPOLYLINE, HATCH (nur R14)
- Die Z Koordinate (caddr (cdr (assoc 10 ele))) verweist auf eine
nicht existierende Speicherstelle. Die Zahl ist zufällig und meist sogar ungültig.
(Abbruch mit "floating point exception").
Abhilfe: siehe Teil 2, Kapitel [23.1]
- ENTMAKE VERTEX von Terry Dotson (nur R14)
- Bei (entmake) von Polyline Punkten gibt es Probleme mit Layern.
Wenn man einem VERTEX Element eine Layergruppe zuordnet, muß man es
auch bei dem abschließendem SEQEND Element tun! Ansonsten wird das SEQEND
Element am aktuellem Layer erzeugt, der später gefroren werden kann. Beim
Versuch die Polylinie zu verschieben wird ein EREGEN Fehler erzeugt und R14
stürzt ab (nur R14).
- ACAD_STRLSORT: Komische Sortierreihenfolge unter Windows.
- Unter Windows werden Buchstaben nicht gemäß des ASCII Zeichensatzes
sortiert, sondern gemäß dem lokalen Zeichensatz
Windows: (acad_strlsort '("-1" "+1")) -> ("-1" "+1"),
DOS: (acad_strlsort '("-1" "+1")) -> ("+1" "-1")
Both: (mapcar 'ascii ("-" "+")) -> (45 43)
- AI_PROPCHK
- (ai_propchk) wurde beim R13c3 Update in (C:AI_PROP) umbenannt.
"The AutoLISP function ai_propchk has been
changed to c:ai_prop so that it behaves similarly to other commands. This
allows pressing return to bring back DDMODIFY if selected from
toolbar."
siehe http://www.autodesk.com/support/techdocs/td11/td111682.htm
- Fehlerhafte "action callbacks" in R13 DCL Funktionen bringen ACAD
zum Absturz
- Es gibt einen Fehler in R13, der ACAD sofort mit einem "Fatal Error" zum
Absturz bringt, wenn während der Ausführung eines AutoLISP DCL "action
callback" Funktion ein Fehler passiert, zb. wenn die Funktion
undefiniert ist. Technisch ist das kein AutoLISP Fehler, eher von ACADAPP,
aber wir nennen es trotzdem einen AutoLISP Fehler.
- Man kann sich seit R13 nicht mehr auf den Bitwert 64 im Flag 70
in Symboltabellen verlassen.
Was noch? Siehe die unoffizielle AutoCAD Bugliste zusammengestellt
von Steve Johnson betr. mehr fehlerhafte AutoLISP Programme und Auswirkungen
auf http://www.cadonline.com/exclusive/bugs/bugwatchlist.htm
- Protected Lisp Funktionen
- Von R13 bis R13_c3 blieben "Protected LISP" Funktionen nicht als geschützt
markiert im Speicher! Unserer Meinung nach sollte dieses Problem allen
klargemacht werden, um nicht Entwickler im Glauben zu lassen, daß ihre
Funktionen geschützt seien.
Dieser FAQ Punkt hat größere Problem im moderierten AutoCAD CompuServe
Forum verursacht, daß uns daraufhin veranlaßt hat, das FAQ daraus rückzuziehen.
Es gibt ordentliche Verschlüsselungsmethoden. Siehe [4]
- Beschränkte Anzahl von offenen Auswahlsätzen
-
Diese wurden in temporären Dateien gespeichert. Lösche nicht gebrauchte
Auswahlsätze mittel setzen auf NIL und führe (gc), den Garbage Collector,
aus, um diese Dateien zu schliessen.
Die maximale Anzahl von geöffneten Dateien hängt vom Betriebssystem
ab, z.B. in DOS vom Wert FILES= in CONFIG.SYS
R13 hat die Anzahl verbessert.
- Zahlen: Wertebereich und numerische Genauigkeit
-
Ganzzahlen (Integer) sind intern longint fixnums (signed long int, 32-bit,
+-2147483647), aber die Schnittstelle von AutoLISP nach AutoCAD akzeptiert
nur 16-bit kurze Ganzzahlen (signed short int), -32768 .. +32767, weil
AutoCAD nur short int benötigt.
Gleitkommazahlen (Float, REAL) sind vom Typ double (64-bit IEEE). (+- 1.7e308,
ca. 15 Stellen Genauigkeit)
Alle internen numerischen Berechnungen in AutoLISP und AutoCAD arbeiten mit
dem selben Format, das ausreichen sollte. Wenigstens die ersten 14 Stellen
sind exakt.
Aber mit häufigen trigonometrischen Berechnungen treten oft
Rundungsprobleme auf, so daß es besser ist AutoCAD Funktionen wie
(trans) zu verwenden und Punkte mit
(equal pt1 pt2 1e-6) ; 0.000001 Rundungsfehlertoleranz
anstatt eines simplen (equal pt1 pt2) zu verwenden,
besonders bei trigonometrischen oder AutoLISP Matrix Berechnungen.
Häufige Probleme enstehen aus der Verwechslung der extakten Zahlen und der
inexakten Zeichendarstellung in der Befehlszeile. Die angezeigte Zahl ist
immer die Stringrepresentation, die den LUPREC und DIMZIN Variablen unterliegt.
Siehe http://xarch.tu-graz.ac.at/autocad/docs/lisp-genauigkeit.txt oder
http://www.autodesk.com/support/techdocs/td30/td301207.htm.
VB: In letzter Zeit häufen sich mysteriöse Problem mit gewissen
Automation controls. Numerische Genauigkeit und länderspezifische
Einstellungen (Komma anstatt Punkt) scheinen ungewollte Seiteneffekte
in AutoLISP Zahlen zu zeigen. Eine allgemeine Erklärung oder Lösung
harrt noch aus. (ServicePacks?) Das betrifft besonders Länder mit
Komma als Dezimaltrennzeichen. (Ähnlich dem bekannten ACIS 60006
Problem, aber ohne Crash).
- ACOMP's (EQ) Problem [alt]
-
Mit [5.1] ACOMP kompilertem Code muß man darauf achten,
daß die Funktion (EQ) wie in einem echtem Lisp viel strenger
vergleicht, als in reinem AutoLISP oder VLISP. In AutoLISP (eq "1"
"1") ist T aber in acomp kompiliertem Code NIL.
Folgende Punkte sind keine Fehler die AutoLISP zum Absturz bringen oder
falsche Ergebnisse retournieren. Sie sind mE. lediglich eine schlechte
Sprachimplementierung:
AND und OR sollten den Rückgabewert des letzten nicht-NIL
Argumentes zurückgeben und nicht nur T. Siehe http://xarch.tu-graz.ac.at/autocad/docs/and-bug.html
MAX und MIN sollten auch Zeichenketten bearbeiten,
weil < und > auch für Zeichenketten funktionieren.
siehe ACAD_STRLSORT oben
Für Stack Overflow Fehler siehe [14]
In Kürze: Benutze die eingebauten Funktionen VL-SORT und ACAD_STRLSORT.
aber Achtung: VL-SORT entfernt doppelte Einträge (die EQ sind)!
Ich habe eine Übersicht über Sortiermethoden auf
http://xarch.tu-graz.ac.at/autocad/lisp/#sort
aufgestellt.
In LISP mit den Daten als einfach verkettete Liste ist die beste Methode
entweder merge sort (in (str-sort) in AutoDesk's TABLES.LSP Beispiel) oder
tree sort.
Es gibt Lisp Code für shell-sort, bubble-sort, insertion-sort, quick-sort
für alle Datentypen, Listen, Listen von Listen oder inidices zu Listen.
In Lisp übergibt man einfach das Vergleichsprädikat an die Funktion, und kann
daher alle Datentypen verarbeiten.
(sort data method) ;method: Funktion mit 2 Argumenten, wie "kleiner als"
;Vorgabe für Zahlen oder Strings: '<
Benchmarks, siehe http://xarch.tu-graz.ac.at/autocad/lisp/sort/ur_sort.lsp:
Sortiere 100 zufällige Elemente:
bubble sort : 13.639008 sec/ 30.08%
insertion sort: 13.368042 sec/ 29.48% (schnell für vorsortierte Listen)
shell sort : 13.478973 sec/ 29.73% (schlechte Implementierung)
merge sort : 2.232971 sec/ 4.92%
quick sort : 2.433960 sec/ 5.37%
vlx-sort : 0.099976 sec/ 0.22% (Vital LISP intern, auch VLISP)
acad_strlsort : 0.089996 sec/ 0.20% (AutoLISP intern, nur Strings)
Interessant wären noch Benchmarks für vl-sort, vl-isort,
STDLIB std-fast-sort, std-sort, std-stable-sort und Vladimir's neuer merge-sort
Dies ist eine nicht häufig gestellte Frage, aber ein interessantes Thema,
weil LISP selbst rekursiv definiert ist und es oft der einfachste Weg
ist um Probleme zu beschreiben und zu lösen.
Es gibt einige gute Texte und Beispiele über Rekursion auf
http://xarch.tu-graz.ac.at/autocad/lisp/
besonders das http://xarch.tu-graz.ac.at/autocad/lisp/recursive.html
Tutorial von Dennis Shinn.
Es erklärt in voller Länge
(defun FACT (n)
(cond
((zerop n) 1)
(T (* n (fact (1- n))))))
Anmerkung:
Von dieser Funktion gibt es auch ein Beispiel einer selbst-modifizierenden Funktion, auf
http://xarch.tu-graz.ac.at/autocad/lisp/self-mod.lsp
Wie mit der Rekursion ist das eine nicht so oft gestellte Frage, aber oft
auch genauso schwer zu verstehen.
Iterative Ausdrücke in AutoLISP sind: WHILE, REPEAT,
FOREACH und MAPCAR. Wir verwenden diese in diesem FAQ oft weil sie kurze
Audrücke erlauben.
Eine kurze Einführung in LAMBDA, QUOTE und MAPCAR... von Vladimir Nesterowsky:
>> "Es gibt 14 Wege und 12 Schweine.
>> Wie kommt es zu 24 Enten?"
>> Gibt eine Lisp Funktion, die es mir erlaubt diese zwei Zeilen Text zu nehmen,
>> die Zahlen daraus zu extrahieren, um dann zB. jede Zahl um 2 zu erhöhen?
>> Aber der Text sollte intakt bleiben
Das ist ein Weg. (Ich bin sicher es gibt noch andere)
(defun MULT2 (strng) ; von Vladimir Nesterowsky
(strlgather
(mapcar
'(lambda (s / n)
(if (zerop (setq n (atof s)))
s
(rtos (* n 2))))
(strlparse strng " ")) ; trenne string an spaces
" ")) ; und verbinde wieder mit spaces
Dieses Beispiel ist erklärt in http://members.tripod.com/~vnestr/mapcar.txt
;;; Wechselt Zeilen mit Spalten in einer Matrix
(defun TRANSPOSE (l) ; von Doug Wilson
(apply 'mapcar (cons 'list l)))
ist erklärt in http://xarch.tu-graz.ac.at/autocad/lisp/transpose.002.html
LISP Programme können beim Startup mit LOAD in ACAD.LSP automatisch geladen werden.
Einige LISP Funktionen, die aus einem Menü aufgerufen werden, sollen aus
der korrespondierendem <menu>.MNL datei geladen werden. Diese <menu>.MNL Datei
soll wiederum ACAD.MNL laden, wenn eine anderes Hauptmenü als ACAD verwendet wird.
LISP Funktion die AutoCAD Befehle beim Startup aufrufen müssen in einer
S::STARTUP Funktion in ACAD.LSP definiert sein. Diese Funktion
wird bei der Initialisierung automatisch aufgerufen. Sonst kommt es zu den
bekannten "Befehlslistenunterbrechung (6 . 2)" Fehlern.
Wenn der Dateiname ohne .LSP Erweiterung bei (LOAD) angegeben wird, wird .LSP
angenommen. Wenn kein Pfad angeben wird, wird er übliche AutoCAD Bibliotheks Pfad
durchsucht, der so definiert ist:
- ) Das aktuelles Verzeichnis
- ) Das Verzeichnis mit der aktuellen DWG Zeichnung
- ) Alle Verzeichnisse definiert in der ACAD Umgebungsvariable
(Voreinstellungen, SUPPORT Pfade)
- ) Das ACAD.EXE Verzeichnis
Wenn dein Programm nicht mehr automatisch geladen wird, überprüfe alle diese Punkte.
Mit ACADLC (von ACOMP) und dem Englischem Release von AutoCAD R12 wird ACAD.LSP
nicht mehr automatisch geladen. Daher füge den folgenden Befehl an ACAD.MNL an:
(load "ACAD")
Beispiel ACAD.LSP:
;;;ACAD.LSP
;;; Freddy Bär, 12.12.94
(load "init" -1) ; Lade meine Tools, bei Fehler gehe weiter
(defun S::STARTUP ()
(load "new-end" -1) ; Definiere END um
)
Das -1 Argument in LOAD verhindert eine Fehlermeldung beim Laden,
es wird lediglich -1 zurückgegeben, aber die Ausführung nicht abgebrochen.
-1 ist nur ein Beispiel, jeder Wert ist möglich.
Beispiele um S::STARTUP zu erweitern. Mit Visual Lisp/Vital LISP funktioniert
das nicht. Entweder definiere S::STARTUP mit DEFUN-Q
(VLISP 2000), kompiliere S::STARTUP nicht (VILL) oder lade in S::STARTUP
eine Liste von "hooks" -benutzerdefinierten Funktionen- die zur
Laufzeit eingefügt und aufgerufen werden können.
(defun MY::STARTUP () ;Deine startup funktionen hier
;..
(princ) ;Unterdrückt Ausdruck des Rückgabewertes
)
(setq S::STARTUP
(if (and S::STARTUP (listp S::STARTUP)) ;wenn schon in ACAD.LSP definiert
; oder woanders
(append S::STARTUP (cdr MY::STARTUP)) ;hänge deine Funktion an oder
MY:STARTUP)) ;führe deine Funktion aus
oder noch einfacher:
(if (and S::STARTUP (listp S::STARTUP))
(setq S::STARTUP (append S::STARTUP (list func '(princ))))
(setq S::STARTUP (list nil func '(princ))))
Vladimir Nesterovsky:
The main difference now in A2K+ versions is that functions
defined with DEFUN are now a new datatype, USUBRs, and not
lists as before. But when the function is defined with
DEFUN-Q, it is a list still, like in previous versions.
Here's the utility function to use that works in both
cases:
(defun plug-into-startup (funcname) ;by VladimirNesterovsky
"to be called with quoted function name"
(eval (list
'defun 's::startup ()
(if s::startup (list (list 'quote s::startup)))
(list funcname))))
so if you have all your startup code packed into one routine
(defun my-startup ()
(alert "My Startup"))
you make it work with the call
(plug-into-startup 'my-startup)
inside your code that is executed on startup, e.g. acaddoc.lsp or whatever.
Siehe auch das nächste Kapitel
[12] Wie funktioniert Autoload?
Wie lade ich meine Programme mit AUTOLOAD? Wie laden sich meine Programe automatisch?
Du kannst entweder deine ganzen Programme beim Starten in den Speicher laden.
(siehe vorher [11] Mein LISP wird beim STARTUP nicht mehr geladen!)
Das braucht mehr Zeit und Speicher beim Startup, oder Du kannst deine Funktionen mit
dem AUTOLOAD Mechanismus laden.
Seit R14 gibt es ein neues Autoloading Schema für ARX Programme: "DEMAND-LOAD"
mit einigen Registry Einstellungen.
Sonst werden alle AUTOLOAD Funktionen in SUPPORT/ACADRxx.LSP definiert.
;;;===== AutoLoad LISP Anwendungen =====
...
(autoload "dline" '("dline" "dl"))
...
Das definiert 2 kurze Befehle DLINE und DL (2. Argument in der Liste) und
erst wenn der Benutzer diese Befehle zum ersten mal aufruft, wird das Programm DLINE.LSP
automatisch geladen, die zwei Befehle umdefiniert und aufgerufen.
Ein sehr kurzer Autolader kann wie folgt definiert werden:
(defun C:DL () (load "DLINE")(C:DL))
Wegen der Fehlerbehandlung (Ctrl-C, Ladefehler, falsche Datei oder Pfad)
ist die wirkliche Definition etwas komplizierter.
Nach dem erstem Aufruf wird die Funktionsdefinition überschrieben mit der
Definition in DLINE.LSP
- Vorteile von Autoload:
- Startup ist schneller, weil nicht alle Programme geladen werden.
Das kostest Speicher und Scuhzeit in den Verzeichnissen.
Mit dem Aufruf von (autoload) wird lediglich die kurze "wrapper"
Funktion wie oben definiert.
Weniger Speicher.
- Nachteile:
-
Bei Fehlern in deinem Program kommt es zu Endlosschleifen, und es komm nur
nach Ctrl-C oder einem Stack Overflow zu einem Abbruch.
Anmerkung: Mit acomp kompiliertem Code ist sogar Ctrl-C unmöglich!
Füge einen Aufruf zu einer unkompilierten Funktion mit (princ) ein.
Man muß alle Programmnamen und -dateien in der Autoload Definition definieren und warten.
Bei Änderungen der Funktions- oder Dateinamen kann es zu obigen Problemen kommen.
- Wohin mit meinen
(autoload) Definitionen?
-
Nicht in ACADR13.LSP, (resp. die versionspezifische Datei) und nicht ACAD.LSP!
Wir empfehlen eine eigene private Initialisierungsdatei.
ACAD.LSP wird oft von anderen Anwendungen geändert. Und ACAD.LSP soll ziemlich
klein und übersichtlich bleiben.
z.B. verwende ein eigenes AUTOLOAD.LSP oder INIT.LSP, das von ACAD.LSP oder
anders geladen wird. z.B von einem privaten <:menuname>.MNL
siehe [11] Mein LISP wird beim STARTUP nicht mehr geladen!
Es wird noch einmal darauf hingewiesen, daß niemand SUPPORT/ACADR13.LSP
(resp. die versionspezifische Datei) verändern darf!
ACAD.LSP wird bei AutoCAD Patches nicht verändert und ist daher sicher.
Mit dem R13c4 Patch wurde ACADR13.LSP verbessert, das Patchen wird aber bei
modifierten Dateien abgebrochen!
Mit reinem AutoLISP ist es nicht möglich so eine Funktion zu definieren.
Man kann entweder alle Argumente in einer Liste übergeben, so wie
hier:
;;; akzepiert eine beliebige Anzahl von Argumenten belibeigen Typs
(defun MY-PRINC (x)
;; einfache Version, siehe auch SDK2: PRINTF.LLB oder weiter unten.
(if (listp x)
(mapcar 'princ x)
(princ x)))
Oder man die Funktion in ADS oder ObjectARX schreiben und nach
AutoLISP exportieren. Dann kann man schreiben:
(ads-print "Hello " "World " 1 2 3)
oder sogar
(ads-printf "Hello %s %i %i" "World" 2 3)
Siehe Reini Urban's und Vladimir Nesterovsky's ADS Code
in http://xarch.tu-graz.ac.at/autocad/ads/
für Implementierungen zu den obigen Beispielen.
Offizielle Wünsche wurden bereits an Autodesk gerichtet &optional als AutoLISP
Spracherweiterung einzuführen.
neu: In old AutoLISP the stack size was hardcoded. It couldn't be extended,
but its size should be sufficient for most purposes. In the Visual
Lisp IDE the stack overflow is simulated at 984 recursions, on the
A2000 commandline or loaded programs outside the IDE there's no
overflow anymore. This is dangerous on recursion errors of yours,
see [9]. Most stack overflow errors occur on a program error of
yours, preventing the system from falling into an endless loop, or
from using recursive functions on large lists. Therefore you are
limited to quite short lists with recursive functions and old versions.
alt:
In AutoLISP die Stack Größe ist fixiert pro Release. Sie kann nicht
erweitert werden, aber die Größe sollte für alle Anwendungen
ausreichen.
Die meisten Stack Overflow Fehlermeldungen passieren in fehlerhaften rekursiven
Funktionen (falsche Abbruchbedingungen) und werden erzeugt um Endlosschleifen zu
vermeiden oder wenn die Rekursion zu tief ist, zB. bei zu großen Listen, die
rekursiv abgearbeitet werden.
Die Länge solcher Listen ist beschränkt auf max. ca. ~200 Elemente mit rekursiven
Funktionen in reinem AutoLISP.
Man diesen Kennwert nicht vergrößern mit weniger lokalen Parametern in der
rekursiven Funktion! Benutze nicht APPLY, EVAL oder MAPCAR um die Funktion
rekursiv aufzurufen, wiel sie Stack kosten. Tail-Rekursion hilft auch nicht.
Sonst muß man die problematische rekursive Funktion in eine iterative Version
umschreiben, was aber kein Problem sein sollte. (Es gibt ein mathematisches
Theorem, das sagt, daß jede Rekursive in Iteration umgewandelt werden kann.
Tail-rekursive sogar automatisch)
Iterative Versionen verwenden meist Hilfsvariablen aber können auch Stack
ähnliche Funktionen wie (push) und (pop) verwenden. Diese Version speichert
den Stack auf dem Heap (AutoLISP node space), dessen Größe nur vom verfügbaren
virtuellem Speicher begrenzt ist.
Man die max. Stackgröße mit folgender einfacher Funktion testen:
;;; Liste von n natürlichen Zahlen:
(defun intlst (l n)
(cond ((zerop n) l)
(T (intlst (cons (1- n) l) (1- n)))))
;Und jetzt:
(setq n 100)(while (intlst nil (setq n (+ 10 n)))(print n))
Mit AutoLISP in R12/DOS wird der Fehler mit (intlst nil 138) erzeugt,
mit A13/Win mit (intlst nil 240), in acomp bi4's mit (intlst nil 1240),
in der Vital/Visual LISP IDE mit (intlst nil 984).
Mit DOS-Extended Lisp Version (R10c10) konnte man den Lisp Stack
mit der Environment Variable LISPSTACK setzen. acomp für R10 hatte COMPSTACK.
Mit dem Vital LISP oder Visual LISP RTS bzw. in A2000
(aber nur außerhalb der IDE) ist die Stackgröße unlimitiert.
Die Konvertierung in die iterative Version bringt folgendes Resultat:
(defun INTLST (n / l)
(repeat n
(setq l (cons (setq n (1- n)) l)))) ;furchtbar, aber es funktioniert!
Einige Befehle sind keine internen AutoCAD Befehle. Sie sind entweder einfache
AutoLISP Funktionen deren Namen mit C: beginnen, oder C: Funktionen
definiert in ADS. Nur Rx Anwendungen können echte interne Befehle exportieren
und mit dann mit (command) aufgerufen oder transparent verwendet werden.
Viele solche Befehle können in ACADRnn.LSP unter AUTOLOAD gefunden werden.
(Siehe auch "[12]")
Alle diese C: Funktionen müssen wie (C:ROTATE3D) anstatt mit
(command "ROTATE3D") aufgerufen werden.
Allerdings, ADS Funktionen können optionale Argumente akzeptieren. Siehe
das Handbuch für Benutzeranpassungen.
z.B. (c:rotate3d ss p1 p2 angle) ist gültig, auch (rotate3d ...)
"I am having trouble getting a lisp file that will open a drawing and
continue running. Once the new drawing is opened the Lisp file ceases
to exist in the Autocads memory. It has to be reloaded to recognise
the commands."
AutoLISP wird nach dem Öffnen jeder Zeichnung neu initialisiert. Es gibt
einige Tricks um das zu bewerkstelligen:
- Ein Script, das mehrere Zeichnungen öffnet:
MYSCRIPT.SCR:
(load "mylisp")
_QSAVE _OPEN !nextdwg
(load "mylisp")
_QSAVE _OPEN !nextdwg
...
- Externe 3rd-party Software wie RunLisp oder DDSCRIPT können das
automatisieren.
- R14 hat ein neues Feature 'Persistent LISP'.
Siehe 'Preferences-Compatibility-Persistent Lisp'
- Vital LISP hatte eine eingebaute Variable um als Persistent Lisp zu arbeiten:
(setq *VILL-NEW-FULL-INIT* nil) ;behält Symbolwerte zwischen Sessions.
- auch mit Visual LISP: (setq *VLISP-NEW-FULL-INIT* nil)
- AutoCAD 2000 ist MDI, das ermöglicht daneben noch bessere Möglichkeiten.
C: Funktionen werden automatisch nach AutoLISP exportiert. Normale VLISP/VILL Lisp
Funktionen entweder dynamisch mit (vl-acad-defun 'myx-funcname) oder statisch
mit einem speziellem Kompiler PRAGMA, entweder in der LSP Datei oder besser in der
GLD ('global declarations') datei. Besser ist es einen speziellen Prefix für solche
Funktionen zu verwenden.
.GLD:
(AUTOEXPORT-to-ACAD-PREFIX
;| Namens Prefixe für autoexportierte Funktionen (strings) |;
"myx-*"
)
oder einzeln:
.LSP:
(pragma '((export-to-acad myx-func1 myx-func2)))
Beachte: Es gibt bekannte ADS Kommunikationsprobleme in VLISP/VILL mit Listen
von 'atomic symbols' und 'dotted pair' Listen in Argumenten und
Rückgabewerten von solchen Funktionen. See [7].
Funktionen, die von externen ADS/ARX Anwendungen in Deiner Lispanwendung
aufgerufen werden, müssen mittels XDF Dateien (oder auch dynamisch)
deklariert werden.
Symbole (Variablen) deren Werte in Visual Lisp geändert werden und die
auch in AutoLISP oder AutoCAD (im Menü zB.) verwendet werden, müssen im Kompiler
als extern markiert werden:
(pragma '((not-localize myx:symbol)))
und die Werte mit
(vlisp-export-symbol 'myx:symbol) exportiert werden,
jedesmal wenn der Wert in Visual Lisp geändert und die Kontrolle zurück zu
AutoCAD übergeben wird, um in AutoLISP oder AutoCAD (!myx:symbol)
den aktuellen Wert zu haben.
Mit AutoCAD 2000 ist es viel einfacher, in getrennten Namensbereichen
muß kann man die Funktion mit VL-DOC-SET exportieren.
Siehe auch
http://www.autodesk.com/support/techdocs/td17/td175363.htm
Teil 2: Beispiele, Programme
Für eine komplette Bibliothek von Hilfsfunktionen siehe die freie
AutoLISP Standard Library auf http://xarch.tu-graz.ac.at/autocad/stdlib/.
Andere aber schlechtere Funktionen gibt es auch auf anderen AutoLISP Seiten [1] oder waren im alten R12 SDK
von Autodesk [1.2]
Hier sind einige wichtige Definitionen um die Hilfestellung in den
Diskussiongruppen zu erleichtern. Diese sollten im Allgemeinwissen sein, sowie
zum Beispiel die berühmte DXF Funktion, die so definiert ist
(defun DXF (grp ele) (cdr (assoc grp ele))) oder die spezifische
Erweiterung (GETVAL), die auch mit ENAME und (ENTGET) Listen funktioniert.
Siehe besonders
http://xarch.tu-graz.ac.at/autocad/stdlib/STDLIST.LSP
Einige nützliche Beispiel Funktionen für Listen sind:
;;; CONSP - nicht leere Liste?
(defun CONSP (x) (and x (listp x)))
;;; POSITION - Rückgabe des Index des ersten gefundenen Elementes in der Liste,
;;; Basis 0, oder nil wenn nicht gefunden.
;;; (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)))
;;; REMOVE - "Entfernt" eine Element aus einer Liste (Doubletten erlaubt)
;;; dh. besser: "Rückgabe einer Kopie der Liste ohne dieses Element"
;;; (remove 0 '(0 1 2 3 0)) -> (1 2 3)
(defun REMOVE (ele lst) ; von Serge Volkov
(apply 'append (subst nil (list ele) (mapcar 'list lst))))
;;; REMOVE-IF - bedingtes "remove" aus einer flachen Liste. "Alle die"
;;; Funktionsargument func benötigt exakt ein Argument.
;;; (remove-if 'zerop '(0 1 2 3 0)) -> (1 2 3)
;;; (remove-if 'numberp '(0 (0 1) "")) -> ((0 1) "")
(defun REMOVE-IF (func from)
(cond
((atom from) from) ;nil oder Symbol (gib das zurück)
((apply func (list (car from))) (remove-if func (cdr from)))
(t (cons (car from) (remove-if func (cdr from))))
)
)
;;; REMOVE-IF-NOT - behalte alle Elemente auf die das Prädikat zutrifft.
;;; Sage: "behalte wenn". Es geht auch iterativ, nicht nur rekursiv.
;;; [fixed, thanks to Serge Pashkov, in FAQ-CODE.LSP it was okay]
(defun remove-if-not (pred lst) ; von Vladimir Nesterowsky
(apply 'append
(mapcar '(lambda (e)
(if (apply pred (list e)) (list e))) lst)))
;;; ADJOIN - cons'e neues Element zu Liste, wenn nicht bereits enthalten.
;;; Trick: Akzepiert auch gequotete Liste ("destruktiv").
;;; (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 - Stelle das erste Element ans Ende. Einfache Version
;;; "Rotiere um eins"
(defun ROT1 (lst) (append (cdr lst) (list (car lst))))
;;; BUTLAST - Liste ohne dem letzten
(defun BUTLAST (lst)
(reverse (cdr (reverse lst))))
Einige nützliche String (Zeichenketten) Funktionen sind:
- Prädikate:
- (stringp expr)
- - Ist ein String?
(defun stringp (s) (= (type s) 'STR))
- (string-not-emptyp str)
- - Ist ein nicht leerer String?
(defun string-not-emptyp (s) (and (stringp s) (/= s "")))
- Trimmen: (rechts und links Leerzeichen wegschneiden)
- (str-trim string)
- - str without any whitespace, to the right
and left, defined in AI_UTILS.LSP, as well as:
- (str-left-trim string), (str-right-trim string),
- (str-left-trim-bag string bag), (str-right-trim-bag string bag)
- - entferne aller Zeichen aus dem bag (= STR)
- String Zugriff:
- (strpos string substr)
- - Position des Substrings in string (Basis 1)
- String - Listen: Parsen und aufsplitten (list<->string):
- (strtok str tokens)
- - string -> list delimited by tokens
- (strlcat lst delim)
- - concat list -> string seperated by delim
-
- (string->list str)
- - string -> list of chars
- (list->string str)
- - list of chars -> string
- Siehe evtl. auch http://xarch.tu-graz.ac.at/autocad/code/vnestr/strtok.lsp
oder in Deinem AI_UTILS.LSP. Du wirst sie speziell für DCL Funktionen brauchen.
Die inverse Funktion zu (READ) nennen wir (SYMBOL-NAME).
Mit VLISP benutze VL-SYMBOL-NAME.
Frage nicht warum, aber die folgende Funktion ist die einzige kompatible
Möglichkeit für alle Ausdrücke oder Elementtypen:
;;; SYMBOL-NAME konvertiert den Symbolnamen zu einer Zeichenkette
;;; Konvertiert jeden gültigen Lisp Ausdruck (auch Listen) zu der gedruckten
;;; Repräsentation
;;; (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") ;temp. Dateiname, sollte gelöscht werden
(setq f (open tmp "w"))(princ sym f) (close f)
(setq f (open tmp "r") str (read-line f) f (close f))
str
)
Für reine Lisp Symbole gibt es bessere Tricks, erklärt von Christoph
Candido: http://xarch.tu-graz.ac.at/autocad/news/symbol-string.txt
;;; Rückgabe des ertsen Gruppenwertes eines Elementes.
;;; Wie die bekannte (DXF) Funktion, aber akzeptiert alle möglichen
;;; Element Repräsentationen (ENAME, entget Liste + entsel Liste)
;;; Beachte: Nicht für 10'er Gruppen in LWPOLYLINIEN geeignet!
(defun GETVAL (grp ele) ;"dxf Wert" eines Elementes
(cond ((= (type ele) 'ENAME) ;ENAME
(cdr (assoc grp (entget ele))))
((not ele) nil) ;leer
((not (listp ele)) nil) ;ungültiges ele
((= (type (car ele)) 'ENAME) ;entsel Liste
(cdr (assoc grp (entget (car ele)))))
(T (cdr (assoc grp ele))))) ;entget Liste
;;; zB: (gettyp pline) => "POLYLINE"
(defun GETTYP (ele) ;Rückhabe des Typs
(getval 0 ele))
;;; => ENAME
;;; Konvertiert das Element zum Typ ENAME
(defun ENTITY (ele)
(cond ;akzeptiert:
((= (type ele) 'ENAME) ele) ; ENAME
((not (listp ele)) nil) ; error: keine Liste
((= (type (car ele)) 'ENAME) (car ele)) ; entsel Liste
((cdr (assoc -1 ele))) ; entget Liste oder nil
)
)
;und jetzt lediglich:
(defun getval (grp ele) (cdr (assoc grp (entget (entity ele)))))
;;; Ist Element ein ...?
;;; zB: (istypep ele "TEXT")
(defun istypep (ele typ) ;prüfe Typ
(= (gettyp ele) typ))
;;; Ist Element eines von ...?
;;; zB: (istypep ele '("TEXT" "ATTDEF"))
(defun ISTYPEP (ele typ) ;besser, akzepiert mehrere Typen
(cond
((listp typ) (member (gettyp ele) typ))
((stringp typ) (= (gettyp ele) typ)) ;Typ = großgeschrieben,
(T nil))) ; wcmatch wäere zu langsam
;;; zB: (getpt (entsel)) => ( 0.1 10.0 24)
(defun GETPT (ele) ;Rückgabe des Startpunktes jedes Elementes
(getval 10 ele)) ;Gruppe 10
;;; zB: (getflag pline) => 1 wenn geschlossen
(defun GETFLAG (ele) (getval 70 ele)) ;same with the entity flag
;;; Ist Bitwert val im Flag gesetzt?
;;; zB: (flagsetp 1 pline) => T wenn geschlossen
;;; zB: (flagsetp 16 vertex) => T wenn Spline Kontrolpunkt
(defun FLAGSETP (val ele)
(bitsetp val (getflag ele)))
;;; zB: (bitsetp 4 12) => T ;Bitwert 4 (=2.Bit) in 12 (=4+8) gesetzt
(defun BITSETP (val flag)
(= (logand val flag) val))
;;; Konvertiert Auswahlsatz zu Liste. Langsam, aber einfach zu benutzen.
;;; Beachte: Es ist gut AI_SSGET zu benutzen, wegen Elementen auf
;;; gesperrten Layern.
;;; zB: (sslist (ai_ssget (ssget)))
;;; oder (mapcar 'entupd (sslist (ssget "X" '((8 . "TEMP")))))
;;; - regeneriert alle Elemente auf Layer 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)))))
;;; 'Mappe' eine Funktion über jedes Element im Auswahlsatz, in umgekehrter
;;; Richtung. Schneller, aber schwerer zu verstehen. Siehe [22.2]
;;; [umbenannt von SSAPPLY zu SSMAP wegen der STDLIB]
;;; zB: (ssmap 'entupd (ssget)) ; regeniere einige Elemente
(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] Ersetze Texte global, mehrere Polylinien, Layer Utilities, Datumsstempel
- For globally changing text attributes use CHTEXT.LSP in your sample
directory.
For globally changing polyline attributes, freeze layers by pick
and other similar tasks search for free lisp tools at any AutoLISP site.
Siehe auch [1] and some code at [22],
[23], and [24].
For putting a datestamp and others onto your plots automatically
first check out if your plotter supports HPGL/2. Then use the
internal HPGL/2 driver and configure the datestamp in HPCONFIG.
DATESTAMP.LSP: Change the plot header attributes by yourself
as in [22.2].
A professional plotstamp routine is here:
http://ourworld.compuserve.com/homepages/tonyt/plotstmp.htm
- [21.2] Starte den Plotdialog von Lisp aus. DDE oder ActiveX
(initdia)(command "_PLOT")
- Der Aufruf der PLOT Dialoges von AutoLISP bevor R14 war nur möglich
unter Windows, z.B mit LISPPLOT für R12/13 von Mike Dickason.
Das fütterte den Tastaturbuffer mit Tasten.
http://www.cadalog.com/cadalog/files/lispd-l/lspplw.zip
oder auch ftp://ftp.mcwi.com/pub/mcwi/lisp/winplt.lsp
Oder erzeuge eine Skriptdatei und rufe sie vom Ende des Lispprogrammes
aus auf. Das zeigt aber nicht den Dialog.
Xiang Zhu: Man kann "ddelisp" unter Windows verwenden:
;;; [fixed for all releases]
(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)))
Für R12 nimm "autocad.dde" als Server Name. Dann kann man von Lisp
oder vom Skript aus einfach (ddecmd "_plot ") aufrufen.
DDECMD gibt NIL bei einem Fehler oder die Zeichenkette zurück.
The string is just like what you type under the command prompt from
keyboard, so you need put a space or a return, which is "^13" here,
to end the string.
Besides, the function is very useful in the following situation: If
within a lisp, you need to call an AutoCAD transparent command like
LAYER, normally you will use (command "_layer"), but after using this
line, the lisp own will not be transparent. Using the function, you
will solve this problem.
Beware that Acad accepts only DDE commands if the command line is
active, that means no dialogbox must be open.
With vlisp/ViLL ActiveX methods can be used:
;;; vlisp syntax:
(setq vlax:ActiveDocument (vla-get-ActiveDocument (vlax-get-Acad-Object)))
(setq plt (vla-get-plot vlax:ActiveDocument)) ;=> plot object
(vla-PlotWindow plt pt1 pt2) ; define window (pts in WCS)
(vla-PlotPreview plt 1) ; 0 for partial, 1 for full
(vla-PlotToDevice plt "Default System Printer") ; if it exists
Mit R14 wurde INITDIA eingeführt, das vor allen Dialogen angewandt werden kann.
(initdia)(command "_PLOT")
Mit A2000 geht nur mehr OLE (die VLA- Methoden), DDE wird von Microsoft nicht mehr unterstützt.
- [21.3] (entmod) und (entmake) für Layer, ohne (command "_LAYER"...)
- ENTMOD a layer
- I try to change a layer property without calling COMMAND function
inside a lisp routine.
Under r13, using the following lisp
(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.
But AutoCAD doesn't know a table entry has been changed until you
click the Layer Control on the toolbar or something similar.
Besides, you can issue 'DDLMODES to see On/OFf property of
"ANY_LAYER" changed.
Doing the same way to freeze a layer, you will still see entities on
that layer shown on screen, but you can not select them, until you do
something related to layer settings, and AutoCAD will hide those
entities.
- ENTMAKE a layer
- You must get your pattern with entget, using the table object name as
argument. This table object name can be retrieved with the TBLOBJNAME
function:
(entget (tblobjname "LAYER" "ANY_LAYER_NAME"))
;;; This routine will create a layer with any name you type:
(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] Auswahl von mehreren Dateien mit Lisp? (wie zB. in DATEIEN - Entsperren)
- At http://xarch.tu-graz.ac.at/autocad/progs/MGETFILD.ZIP
is a lisp helper routine to select multiple files with DCL.
You will also need DOSLIB from McNeel to access the dos specific
directory functions. http://www.mcneel.com/mcneel/doslib.html
-
[21.5] Ersetze mehrere Blöcke
- A search at the lisp archives yielded those hits:
Cadalyst: http://www.cadonline.com/search.phtml
=> 97code.htm and a question for your username which can be obtained free and automatically
xarch: http://xarch.tu-graz.ac.at/autocad/code and
search for "BLOCK;REPLACE"
=> http://xarch.tu-graz.ac.at/autocad/code/cadalyst/94-02/replace.lsp
also at the Cadalog:
http://www.cadalog.com/find.htm Keyword "Block Replace"
=> http://www.cadalog.com/cadalog/files/lispr-z/replace.zip
(this one is the best)
- [21.6] (vports), VIEWPORT Element, Pixel Konversion
-
Das VIEWPORT Element:
The answer to "I can do an (entget) on a VIEWPORT and get its lower
left (DXF group 10) and upper right (DXF group 11) corner. But it
appears that these coordinates are in the paper space system. What I'm
interested in finding out is what portion of the "real" drawing (the
model space drawing) are currently shown in that viewport."
is at http://xarch.tu-graz.ac.at/autocad/news/vports.lsp
[new]:
http://www.ez-sys.net/~coopfra/lisp.htm#view has also some tricks.
How to change viewports in AutoLISP?
with (setvar "CVPORT" vport-id)
siehe http://xarch.tu-graz.ac.at/autocad/news/change_vports.html
With the following functions you convert pixel<->drawing units:
;;; Conversion pixel to drawing units
(defun PIX2UNITS (pix)
(* pix (/ (getvar "VIEWSIZE") (cadr (getvar "SCREENSIZE")))))
;;; Conversion drawing units to pixel
(defun UNITS2PIX (units)
(* units (/ (cadr (getvar "SCREENSIZE"))(getvar "VIEWSIZE"))))
[new] Note also the "Pixel Off by One" Errors in AutoCAD, described by Vibrant, here:
http://xarch.tu-graz.ac.at/autocad/news/pixel-off-by-one-error.txt
-
[21.7] Auswahl aller sichtbaren Elemente: ZOOM Koordinaten
-
Beware that with (ssget) you will only get visible objects, because all
interface functions (entsel,ssget,osnap) work with pixel, only (ssget "X")
will select not visible objects.
;;; returns a list of the actual viewport corners in 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)) ;aspect ratio
(cadr screen))
size (list (* h ratio) h) ;screensize in coords
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))) ;assure 2D coords
Note: The points returned from the entity are in WCS but this is OK
because the "CP" "WP" and "P" options of ssget expect WCS
points ("W" and "C" require UCS points - why the difference I don't know)
;;; one way to define this function
(defun ssall-visible (/ l)
(ssget "C" (car (setq l (maptrans0-1 (zoompts)))) (cadr l)))
;;; or another
(defun ssall-visible-1 () ;combine "C" and (p1 p2) to one list
(apply 'ssget (append '("C") (maptrans0-1 (zoompts)))))
;;; map some pts from WCS to UCS, easier with just one argument [doc fixed]
(defun maptrans0-1 (pts)(mapcar '(lambda (pt)(trans pt 0 1)) pts))
- [21.8] Wie schreibe ich die XYZ Daten von Elementen in eine Datei?
;;; CDF - comma delimited string
(defun cdf-point (pt)
(strcat (car pt) ", " (cadr pt) ", " (caddr pt)))
;;; SDF - space delimited, may easier be read back in to AutoCAD
(defun sdf-point (pt)
(strcat (car pt) " " (cadr pt) " " (caddr pt)))
;;; convert this SDF format back to a point with
(defun str->point (s)
(eval (read (strcat "(" s ")"))))
;;; Write a XYZ file of all selected objects (SDF see below)
(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
For a ASC file (SDF-format) simply change all XYZ to ASC
and cdf-point to sdf-point above.
For the other way 'round, creating PLINES from a ascii x,y file
best convert the file to a script like:
PLINE
300.2,10
350.4,10.4
- [22.1] Zugriffsmethoden zu Block Attributen mit AutoLISP
- Prüfe alle Unterobjekte nach dem INSERT objekt bis zum richtigen Attribut.
Siehe http://xarch.tu-graz.ac.at/autocad/stdlib/STDENT.LSP
;;; gibt entget Liste des Attributes 's' (STRING) in Element ele (ENAME) zurück
;;; oder nil wenn nicht gefunden
(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
)
;;Beispiel:
(attele (entsel) "TEST") ; returns entget-list of
; attribute "TEST" if the block has it
BTW: Noch etwas trickreichere Funktionen sind GET und EDLGETENT von Vladimir Nesterowsky.
;;;Sample calls:
;;; return list of 2,1 and -1 group values
(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))))
verfügbar unter http://members.tripod.com/~vnestr/
-
[22.2] Wie ÄNDERE ich Block Attribute? DATESTAMP.LSP
-
Für ein einfache automatische Datum-Stempel Lösung rufe entmod mit der
entget-liste des DATUM Attributes in deinem PLANKOPF Block.
Verwende dazu (attele) wie unten.
;;; Ändere den Attributwert in Block ele auf 'new'.
(defun ATTCHG (ele attname new / b)
(if (setq b (attele ele attname))
(entmod (subst (cons 1 new) (getval 1 b) b))))
;;; Ändere alle DATUM Attribute in allen eingefügten PLANKOPF* Blöcken
(defun C:DATESTAMP ()
(ssmap
'(lambda (ele)
(attchg ele "DATUM" (heute))
(entupd ele)
)
(ssget "X" '((0 . "INSERT")(2 . "PLANKOPF*")))
))
;;; Rückgabe des aktuellen deutschen Datum-Strings, "31.01.99".
;;; Kann auch mit DIESEL gelöst werden.
(defun HEUTE (/ s)
(setq s (rtos (getvar "CDATE") 2)) ;julianisches Datum
(strcat (substr s 7 2) "." (substr s 5 2)"."(substr s 3 2)))
Automatische Datum Updates macht man entweder mit RTEXT
(bonus/express tools) oder HPCONFIG mit einem HPGL/2 Plotter. (<a2000i)
-
[22.3] Wie UPDATE ich Block Attribute?
-
Es gibt ein SUPPORT\ATTREDEF.LSP um Attributeigenschaften (wie Position,
Layer, Texthöhe, ...) auf bereits eingefügte Blöcke zu übertragen.
- Bei komplexen Elementen muß man entupd mit dem Hauptelement
(INSERT oder POLYLINE) ausführen, um Änderungen am Bildschirm zu sehen.
("Element REGEN").
;;; Beispiel:
(setq s (getstring "Change Attribute to: "))
(attchg (attele (setq b (entsel "of block: ")) s)))
(entupd (car b)) ; the block, not the attribute
;;; some more helper funcs to get the main entity of any attribute
;;; or vertex
(defun MAIN-ENTITY (ele)
(setq b (entity b)) ;force ENAME
(while (istypep b '("ATTRIB" "ATTDEF" "VERTEX"))
(setq b (entnext b))) ; loop until no more sub-entities
(if (istypep b '("SEQEND" "ENDBLK"))
(getval -2 b) ;complex entity -> header
b ;normal entity
)
)
-
[22.4] Wie erzeugt man mit ENTMAKE einen Block?>
-
Siehe http://xarch.tu-graz.ac.at/autocad/stdlib/ENTMAKE.LSP
Dort gibt es eine Beispiel vom Mehrfachaufrufen von (ENTMAKE) für
den Blockdefinitions HEADER, die Elemente, den Abschluss (ENDTAB) und zum Schluß
den Block als INSERT mit (ENTMAKE) einzufügen. Für anonyme Blöcke
beachte daß
(setq bn (entmake '((0 . "ENDBLK")))) gibt den erzeugten Blocknamen für
(entmake (list '(0 . "INSERT")'(70 . 1)(cons 2 bn) ...)) zurück.
Seit R14 speichert die neue LWPOLYLINE ("light weight") die Punkte nur mehr in einem
Objekt als mehrfache 10'er Gruppen. Es ist kein komplexes Objekt mehr, die (assoc) Methode funktioniert nicht mehr.
- [23.1] Wie greift man auf Polylinien Knotenpunkte (VERTEX) zu?
- Ein Polylinien VERTEX ist eine Unterelement einer POLYLINE
(wie auch ein ATTRIB ein Unterelement eines INSERT Blockes ist, oder
ATTDEF eines BLOCK).
Also können die selben Funktionen wie in [22.1]-[22.3]
benutzt werden.
;;; Rückgabe einiger assoc Gruppenwerte einer Liste (für LWPOLYLINE)
(defun group-only (grp lst)
(mapcar 'cdr (remove-if-not '(lambda(pair)(= grp (car pair))) lst)))
;;; Rückgabe der Vertex Liste einer Polylinie oder eines bel. anderen Elementes
(defun GETPTS (ele / pts)
(setq ele (entity ele)) ;=> ENAME typ
(cond
((istypep ele "POLYLINE")
(while (istypep (setq ele (entnext ele)) "VERTEX")
;; lasse Fit und Spline Punkte aus (konservativer Stil)
(if (not (or (flagsetp 1 ele) (flagsetp 8 ele))) ;bugfix!
(setq pts (cons (trans (getpt ele) ele 0) pts)))
(reverse pts)))
;; Spezialfall: Man muß mappen, assoc finded nur den ersten.
;; Fix für einen LWPOLYLINE Bug in R14: Intern nur 2D,
;; (entget) gibt Fantasie Z Werte zurück.
((istypep ele "LWPOLYLINE")
(mapcar '(lambda(pt)(trans (list (car pt)(cadr pt) 0.0) ele 0))
(group-only 10 (entget ele))))
;; Füge hier andere Elementtypen ein, sowie:
((istypep ele '("TEXT" "CIRCLE")) (list (getpt ele)))
;; Andere (Serge's Stil). Für LWPOLYLINE siehe oben.
(T (apply 'append (mapcar
'(lambda (n / p) (if (setq p (getval n ele)) (list p)))
'(10 11 12 13)))
)
;; oder so (konservativer Stil)
;;(T (foreach n '(10 11 12 13)
;; (if (setq p (getval n ele)) (setq pts (cons p pts))))
;; pts
;;)
)
)
Vorschläge von Vladimir Nesteroswky für eine andere Vertex Struktur:
Siehe [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))
=> Liste von (10 42) Paaren einer Polylinie
;;; kann dann auch so geschrieben werden:
(defun flag9p (ele) (flagsetp 9 ele))) ;Wahr für Fit oder Spline Punkte
(mapcar
'(lambda (ele)
(remove-if-not 'flag9p (cdr (edlgetent pline-entname))))
Siehe auch [23.5] für eine andere Kanten Struktur (Segmente) von Polylinien.
- [23.2] Wie VERBINDET man mehrere Linien zu Polylinien?
- Versuche einfach jedes Element mit allen ausgewählten Elementen
zu verbinden, aber beachte daß bereits verbundene Elemente können nicht
mehr mit ENTGET gefunden werden weil sie beim Verbinden gelöscht wurden.
;;; Dieses einfache Beispiel konvertiert alle gewählten Elemente zu
;;; Polylinien und versucht so viele möglich zu verbinden.
(defun C:JOINPOLY (/ ele ss)
(foreach ele (sslist (setq ss (ssget))) ;besser mit einer Liste
(if (entget ele) ;nicht bereits verbunden?
(cond ;(sonst wäre sie nil)
((istypep ele '("ARC" "LINE"))
;; Sie sollten hier noch dazu die Erhebung (Z) und das BKS beachten!
(command "_PEDIT" ele "_y" "_j" ss "" ""); Konvertiere und VERBINDE
)
((and (istypep ele '("POLYLINE" "LWPOLYLINE"))
(not (flagsetp 1 ele)) ;offen
(< (rem (getflag ele) 128) 8)) ;ignoriere Netze usw.
(command "_PEDIT" ele "_j" ss "" "");BKS Prüfung hier ausgelassen
)
)
)
)
)
- [23.3] Ändere die BREITE von mehreren Polylinien
- Mit den obigen Hilfsfunktionen ist es leicht:
(defun C:POLYWID (/ wid ele)
(initget 5)(setq wid (getdist "Neue Polylinie Breite: ")) ;nicht negativ
(foreach ele (sslist (ssget '((0 . "*POLYLINE")))) ;nur PLINE
(command "_PEDIT" ele "_W" wid "")))
- [23.4] Erzeuge Polylinie oder Spline: mit (ENTMAKE) oder (COMMAND)
-
- Du kannst eine Skriptdatei mit einem LISP Programm erzeugen
und dann aufrufen. Das erscheint für Anfänger der einfachste Weg zu sein.
Aber I/O (Ein/Ausgabe) Fehler machen das ganze unzuverlässig und
kompiliziert. Kommerzielle Programme machen das anders.
- Im zweiten Weg erzeugt man die fertige Elementliste und ruft ENTMAKE auf.
Vorteil: Schnell, im WKS, unabhängig von Objektfang.
Siehe http://xarch.tu-graz.ac.at/autocad/stdlib/ENTMAKE.LSP
- Die dritte und häufigste Möglichkeit basiert auf COMMAND. Es
funktioniert wie bei der Benutzereingabe für Polylinien, Splines oder
Linien. Nachteile: BKS, Objektfänge.
;;; Zeichnet eine POLYLINIE aus einer Punktliste (das selbe mit SPLINE,
;;; oder LINIE), im aktuellem BKS, mit der aktuellen Objektfangeinstellung.
(defun DRAW-PLINE (pts)
(command "_PLINE")
(mapcar 'command pts)
;; oder so: (foreach pt pts (command pt)) => braucht weniger Speicher
(command ""))
(defun DRAW-SPLINE (pts)
(command "_SPLINE")
(apply 'command pts) ; so geht's auch, pts = Fitpunkte
(command "" "" ""))
- [23.5] Wie messe ich die LÄNGE von Polylinien?
-
Es gibt zwei Wege:
- Die einfache, mit dem FLÄCHE (_AREA) Befehl, ist mitunter 'laut'.
(druckt das Ergebnis), aber funktioniert mit allem, auch Splines.
;;; addiere alle LÄNGEN aller gewählten Objeke, LAUT,
;;; für die Fläche ändere die letzte Zeile auf (getvar "AREA")
(defun C:LEN-OF ()
(command "_AREA" "_A" "_E") ;addiere Objekte (_E für R12+R13 Komp.)
(ssapply 'command (ssget)) ;pass all elements to AutoCAD
(command "" "") ;two returns
(getvar "PERIMETER")) ;this is the length
- Mit einiger Mathematik, aber nur für einfache Objekte.
Here is best to define some helper functions again. This is also an
introduction for the next chapter [24], some bulge trigonometry
for curved segments.
;;; Berechne Länge eine Polylinie, leise
(defun POLY-LENGTH (poly / seg)
(apply '+ ; die Summe aller Einzellängen
(mapcar
'(lambda (seg) ;Länge eines Segments
(if (zerop (car seg))
(distance (cadr seg) (caddr seg)) ;Liniensegment oder
(abs (arclen seg seg)))) ;gekrümmt: siehe [24]
(pline-segs poly))))
;;; returns all group codes of the complex element
;;; (vertices, attributes) as list, similar to (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 - Creates a segment list for the polyline pname
;;; as a list of '(bulge p1 p2). A straight line has bulge 0.0
;;; Compute pts in ECS of pname. Accepts LWPOLYLINE's
(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 ;closed
(butlast segs))) ;open: without the last segment, ->[20.1]
;;; Example: (a bit optimized for brevity :)
;;; add up all the lengths of all polylines, QUIET
;;; To accept also other entities, add those to pline-segs
(defun C:POLYLEN ()
(apply '+ (ssapply 'poly-length (ssget '((0 . "*POLYLINE"))))))
Für die Summe aller Flächen verwende entweder den lauten Befehl AREA (wie oben) oder
implementiere Heron's Formel für Polygonflächen (aber nur für einfache geschlossene Polylinien).
- [23.6] Wie drehe ich die Richtung von Polylinien um (REVPOLY.LSP)?
-
Sergei Komarov submitted a REVPOLY.LSP which takes care of
bulges and widths too.
http://xarch.tu-graz.ac.at/autocad/news/lisp_pro/revpoly.lsp
Eine kurze Stdlib Version wäre das:
;;; Ignoriere jede Breiten Information
(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 "\nDrehe Polylinie um: ")))
(std-entmake-pline (entget ele '("*")) ; behalte EED information
(poly-reverse (std-pline-segs ele)))))
-
[23.7] Wie errechnet man das Zentrum einer Polylinie? [neu]
-
Das Zentroid eines Volumenkörpers oder Region muß mit _MASSPROP extrahiert werden.
Man kann das resultat in eine Dateio schreieben und dieses dann analysieren.
Das Zentroid einer Polylinie ist verschieden vom "geometrischem Mittelpunkt",
Dieser ist einfach.
(setq n (float (length pts)))
(list (/ (apply '+ (mapcar 'car pts)) n)
(/ (apply '+ (mapcar 'cadr pts)) n))
Das echte Zentrum ist aber viel schwieriger. Die stdlib Version ist auf
http://xarch.tu-graz.ac.at/autocad/stdlib/STDPOINT.LSP STD-CENTROID-2D
Im stdlib.arx oder unter www.manusoft.com (siehe freebies) sind bessere MASSPROP Lisp funktionen für Solid's.
Man nehme also (command "_REGION" ele)(massprop entlast)(command "_UNDO" 1).
In VLA gibt es auch eine MASSPROP Objekteigenschaft für Acis Objekte.
[fixed]
Was ist BULGE, die "Krümmung" in einer Polylinie?
Die Krümmung ist der Tangens eines Viertels des inkludierten Winkels des
gekrümmten Segmentbogens. Eine Krümmung von 0.0 repräsentiert eine gerade Linie.
Zusammen mit dem Start und Endpunkt ist das genug Information um schnell alle
anderen Werte zu berechnen. Eine negative Krümmung bedeutet Drehung im Uhrzeigersinn
("mathematisch negativ").
Bogenlänge = radius * winkel
Krümmung = +/- tan( winkel/4 ) (CCW: +, CW -)
Winkel = 4 * atan( krümmung )
Krümmung = +/- ( 2 * höhe ) / stichlänge (CCW: +, CW -)
Siehe auch http://www.autodesk.com/support/techdocs/fax700/fax797.htm
für ein Beispiel oder das Buch "Maximizing AutoLISP" [2].
(Beachte: Das R10/11 Buch -Vol II- beinhaltet eine falsche Bulge Formel.)
(bugfixed, falsche Formel! Dank an Sergei Komarov)
;;; Konvertiert ein gekrümmtes Polyliniensegment (bulge pt1 pt2)
;;; in einen Kreis (ctr rad). Start- und Endpunkte sind bekannt,
;;; also die Winkel auch: (angle ctr pt1)(angle ctr pt2)
;;; Gibt NIL bei gerader Linie zurück.
(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) ; um PROGN zu vermeiden
)
)
)
;;; Inverse Konvertierung, berechne Segment (bulge p1 p2) eines Bogens
;;; mit gegebenem Kreis (ctr rad), start- und end-winkel
(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)
)
;;; Berechnet Krümmung eines Kreisbogens. Gegeben sind die Bogenpunkte
;;; und der Kreis (ctr rad) [fixed von Serge Pashkov]
(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)))
;;; Eingeschlossener Bogenwinkel des Segments (bulge p1 p2)
(defun bul2ang (seg / ctr)
(- (angle (setq ctr (car (seg2cir seg))) (cadr seg))
(angle ctr (caddr seg))))
;;; Berechnet Bogenwinkel aus der Stichlänge und dem Radius
(defun arc2ang (chord rad)
(* 2.0 (atan
(/ chord 2.0
(sqrt (- (expt rad 2)
(expt (/ chord 2.0) 2)
) ) ) ) ) ) ; eine andere Lebensform in der Klammernwelt
;;; ARCLEN - Bogenlänge = radius * winkel
;;; Beachte Vorzeichen! +/- (abs (arclen seg)) ist die reine Länge
(defun arclen (seg)
(* (cadr (seg2cir seg)) ; radius
4.0 (atan (car seg)))) ; winkel = 4*atan(bulge)
(setq *INFINITY* 1.7e308) ; größte double Zahl
(defun TAN (z / cosz)
(if (zerop (setq cosz (cos z))) *INFINITY*
(/ (sin z) cosz)))
(defun DTR (ang)(* pi (/ ang 180.0))) ; Grad in Radian
(defun RTD (ang)(/ (* ang 180.0) pi)) ; Radian in Grad
Unter Windows ist es schwierig Texte zu layouten ohne "monospaced" Schriften.
Versucher entweder das "tabs" Attribut in der list_box Komponente, so wie:
tabs = "0 20 40";
(set_tile "listbox" "Layer:\t0\tweiss")
oder verwende eine monospaced Schrift mit dem "fixed_width_font" Attribut:
: list_box {
label = "Drawing";
key = "dwglist";
width = 50;
fixed_width_font = true; // <- monotext
}
Beachte auch die DETAB Funktion (TAB -> Leerzeichen) auf
http://xarch.tu-graz.ac.at/autocad/news/detab.lsp
oder STD-DETAB in http://xarch.tu-graz.ac.at/autocad/stdlib/STDSTR.LSP
-
[26.1] Wähle Objekte über EED mit (ssget "X")
;;; Definiert den appname Header und Delimiter (4 Zeichen regapp name
;;; nach AAIG, der Autodesk Application Interoperation Guidelines)
(setq appname "HUBU-")
;;; definiert "*" für alle Untertypen
(setq allappnames (strcat appname "*"))
;;; zB: HUBU-LIST1, HUBU-LIST2
;;; Gibt EED Liste eines Elementes zurück
(defun GETEED-LST (ele)
(cdadr (assoc -3 (entget ele (list allappnames)))))
;;; Gibt alle Elemente eines bestimmten appname Typ zurück
;; (reguläre Ausdrücke erlaubt)
(defun ssget-app (typ)
(ssget "X" (list (list -3 (list typ))))
;;; Gibt alle deine privaten "HUBU-*" Elemente zurück
(defun ssget-hubu (typ)
(ssget "X" (list (list -3 (list (strcat appname typ)))))
(ssget-hubu "*") ; will get all your elements
- [26.2] Zugriff auf Objekt EED (XDATA)
Prüfe XDATA mit: (entget (car (entsel)) '("*"))
Diese Funktionen extrahieren alle XDATA passend zum regapp Namen oder
alle passenden XDATA Werte.
;;; GETXDATA - alle XDATA Listen eines Elementes
;;; zB mit den 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))))
;;; GETXDATA-ALL - alle XDATA als Listen, ohne regapp namen
;;; => ((1000 ."ASSHATCH")(1002 ."{")(1070 . 1)(1002 ."}"))
(defun getxdata-all (e apnlst)
(apply 'append (mapcar 'cdr (getxdata e apnlst))))
The regapp name is stripped here, because it's only used for fast
ssget access. The different apps are divided by different (1000 . name) groups as
it's used by Autodesk.
For storing XDATA in an element see XDATA.LSP or XED.LSP though those
examples are a bit disturbing.
For advanced EED tricks, esp. converting the "{" "}" ADS resbuf style
to Lisp lists and back see
http://xarch.tu-graz.ac.at/autocad/news/eed_retrieval.txt
Auch: "How do I press Break in AutoLISP?"
(command) ohne Argument oder mit nil als Argument funktioniert wie
Ctrl-C in R12 oder Esc danach, aber nur in der Befehlszeile, nicht in einem
Dialogfeld. Und es funktioniert auch nicht in SKRIPTs.
(command nil) ist dasselbe wie (command).
(command) bricht nur den aktuellen Befehl ab, z.B. bei
"BEM" in AutoLISP muß man (command) zweimal ausführen.
Das funktioniert aber nicht mit Lispschleifen. Hier gibt es (quit)
oder (exit) -äquivalent- um ein Lispprogramm sofort zu beenden.
Beispiel:
(while T ; do ; Endlosschleife
(princ "\nEingabe a=")
(setq a (getint))
(if (zerop a)(exit)) ; Abbruch aus Lisp
)
In diesem Beispiel würde (command) nicht die Schleife beenden.
(exit) beendet die Ausführung wie mit Control-C.
Es wird "error: quit / exit abort" ausgegeben und der Stack aller
aufgerufenen Funktionen wird ausgegeben.
Für einen unsichtbaren Abbruch muß man *error* umdefinieren:
(setq olderr *error* *error* my_error)
(defun MY_ERROR (s)
(if (not (member s ; unsichtbar
'("Funktion abgebrochen" "Tastatur-Abbruch" "quit / exit abort")))
(princ (strcat "\nFehler: " s))
)
(setq *error* olderr)
)
Für Skripts definiere einfach eine CANCEL Funktion in Lisp, wie:
(defun SCRIPT-CANCEL ()
(command)
(command "resume"))
und dann im SCRIPT.SCR:
..
[Skript Befehle]
(script-cancel)
[weitere Skript Befehle]
..
[neu]
Um den Benutzer die Möglichkeit zu überlassen jeden beliebigen Befehl mit allen
möglichen Optionen zu verwenden ohne alles auszuprogrammieren, wiederhole einfach
(command PAUSE) bis der Befehl zu Ende ist.
zB. bei den schwierigen Befehlen PLINIE oder BOGEN.
(command "_ARC")
(while (= 1 (logand (getvar "CMDACTIVE") 1)) (command PAUSE))
Alle ACIS Objekte (3DSOLID) sind dokumentiert von Spatial (SAT Format Description).
Die interne Representation mit (ENTGET) ist verschlüsselt, aber das
Verschlüsselungsschema wurde geknackt. (XOR 95)
Siehe
http://xarch.tu-graz.ac.at/autocad/stdlib/samples/ACIS-REGION.LSP
[neu]
Wenn Du glaubst nützliche Verbesserungen oder Änderungen für dieses FAQ zu wissen,
sende ein E-Mail an Reini Urban <rurban@x-ray.at> aber erwarte keine Antwort.
Dieses AutoLISP FAQ ist urheberrechtlch geschützt © 1996-2000 von Reini Urban. Alle Rechte vorbehalten.
Die Beispielfunktionen sind, wenn nicht anders beschrieben, © 1991-97
von Reini Urban und dürfen frei benützt, kopiert, verändert und verbreitet werden,
aber nur ohne Entgelt.
Die Grundfunktionen sind © 1991-97
von Reini Urban und dürfen frei benützt, kopiert, verändert und verbreitet werden.
Dieses FAQ darf frei verbreitet werden, aber nur als vollständiges Dokument
ohne Änderungen.
Es darf nicht gegen Entgelt verkauft oder in kommerziellen Dokumenten oder
Produkten verwendet werden ohne vorheriger schriftlicher Zustimmung des Rechteinhabers
(z.B. publiziert auf kommerziellen CD-ROM's, Disketten, Büchern, Zeitschriften,
oä.).
Die Erlaubnis wird explizit erteilt, dieses Dokument im freien und unbeschränkten
elektronischen Datenverkehr (FTP, WWW, ...) zugänglich zu machen und in eine
offizielles AutoCAD FAQ inkludiert zu werden.
Wenn dieses Dokument in off-line Form (z.B. CD-ROM, gedruckt) reproduziert wird,
muß eine zusätzliche Kopie an den Rechteinhaber Reini Urban, X-RAY,
Nibelungeng. 3, 8010 Graz, Austria gesandt werden.
Die Autoren und/oder der Rechteinhaber weisen ausdrücklich alle
Haftungsansprüche für etwaige Fehler oder mißverständlich
interpretierte Probleme zurück. Wir haftet nicht für Verluste oder
Schäden welcher Art auch immer. Einschließlich des Verlusts oder der
Zerstörung von Daten, entgangenen Gewinn, Versicherungskosten oder
andere spezifische, unvorhergesehene, folge- oder mittelbare Schäden,
die sich aus der Benutzung oder der Unmöglichkeit der Benutzung der
Software oder der Dokumentation ergeben, ungeachtet der Ursache und
des für die Haftung geltend gemachten Rechtsgrundes, sofern sie nicht
nach zwingenden gesetzlichen Bestimmungen haftet.
[A.1] FAQ Links
- Homepage der HTML Version:
- http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html
- Kommentierte AcadWiki version: [neu]
- http://xarch.tu-graz.ac.at/acadwiki/AutoLispFaq
- Die geposteten ASCII Versionen (und meist am letzten Stand) sind hier:
- http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.1
- http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.2
- Eine Winhelp version (gezippt mit FAQ-CODE.LSP) ist hier:
- ftp://xarch.tu-graz.ac.at/pub/autocad/news/faq/autolisp.zip
- FAQ Usenet Archiv
- http://www.faqs.org/faqs/CAD/autolisp-faq/ oder per ftp
ftp://rtfm.mit.edu/pub/usenet-by-hierarchy/comp/cad/autocad/
- Alle Lisp Funktionen aus diesem FAQ sind hier:
- ftp://xarch.tu-graz.ac.at/pub/autocad/news/faq/FAQ-CODE.LSP
- Alte Anfänge eines eigenen, neuen AutoCAD FAQ's sind hier:
- http://xarch.tu-graz.ac.at/autocad/news/faq/new-acad
- Die französische Übersetzung von Roger Rosec:
- http://www.newz.net/acadplus/page5101.htm
- Die japanische Übersetzung von MASAMI Chikahiro:
- http://www.page.sannet.ne.jp/chestnutsburr/autolisp-j.html
- Die russische Übersetzung von Igor Orellana:
- http://www.cad.dp.ua/stats/alfaq_ru.htm
- Die deutsche Übersetzung von Reini Urban:
- http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html.de
- Die spanische Übersetzung von Eduardo Magdalena: [neu]
- www.peletash.com/mecanicad/
- Wegen einer griechischen Übersetzung wurde ich kontaktiert.
- AutoDesk's FAQ's und TechSupport
- http://www.autodesk.com/support/autocad/
Suche nach AutoCAD+FAQ
Support Assistant 2000
- AutoDesk Diskussionsforen [geändert]
- news:autodesk.autocad.customization, auf
Google [neu]
oder das neue WebX interface auf Autodesk's web server.
Dieses FAQ basiert auf große Anstrengungen der gesamten comp.cad.autocad Gemeinschaft, in besonderem:
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, Eduardo Magdalena, 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 und vielen anderen.
- 3.Mar 2002
- Vladimir added a section to [11] S::STARTUP (from the wiki)
- 18.Jun 2001
- fixed deja.com to groups.google.com
- 23.Apr 2001
- fixed several links
- v2.28 4.Apr 2001
changed rurban@sbox to rurban@x-ray.at (defunct in the next year)
all parts of the faq are now in the acadwiki.
- v2.27 23.Sep 2000
- neu: [23.7] "Wie errechnet man das Zentrum einer Polylinie?"
- 15.Sep 2000
- "Stack Overflow" Kapitel [14] überarbeitet
(VL/VLIDE, A2000).
- neues englisches Buch [2]
- 1.Sep 2000
- vl-sort Warnung mit doppelten Einträgen [8]
- 18.Aug 2000
- changed Codemagic [6.1] from Freeware to Shareware, thanks to Nir Sullam
- 1.Aug 2000
- Änderung der Autodesk FAQ's auf Search URL
- v2.266.Jun 2000
- neuer LDATA bug [7],
fixed DEFUN-Q [11],
entferne die meisten farbigen [neu/geändert] Noten.
- v2.25 17.May 2000
- neu [27.1],
neu C:POLYREV [23.6]
- 25.Apr 2000
- neu Point A [1.1], DDE Beispiel gekürzt [21.2]
- 24.Apr 2000
- Vladimir fixed www.deja.com to deja.com/usenet [1.1]
- v2.24 20.Apr 2000
- renamed cadsyst.com to caddepot.com [1], added cadplugins.com [1], added rapidlisp [6.2]
- 30.Mar 2000
- renamed adesknews.autodesk.com to discussion.autodesk.com
- 9.Mar 2000
- added CodeMagic editor at [6.1], thanks to Nir Sullam
- 29.Feb 2000
- Masami Chikahiro fixed numeric ranges [7]: -32766 => -32768
- 23.Feb 2000
- Phil Kenewell updated LispLink 2000 [6.1].
- 17.Feb 2000
- Added the dotsoft biglist url [7].
Mike Tuersley fixed [11] for MNL files.
- v2.23 14.Feb 2000
- Chris Ehly fixed all broken links.
- v2.22 13.Jan 2000
- additions to numerical precision.
adesk techdocs links are broken again.
compiled S::STARTUP hooks
- v2.216.Dec 99
- adesk faq link, removed peoples urls/emails, minor fixes.
- 7.Oct 99
- wording in [0.1], german translation,
link in [28]
- v2.2 13.Jul 99
- added topics [0.1] What changed with AutoCAD 2000?,
[0.2] Why cannot I create ARX anymore?,
[5.4] Better ones: Common Lisp and Scheme.
- additions to [6.2] Analyzers, Packagers...,
[5.3] R15 VLISP info, [4] FAS Security,
[21.4],
[20.4]: renamed SSAPPLY to SSMAP
- 13.Apr 99
- fixed a link [1]
- v2.1 3.Jan 99
- fixed and added some links: [22.4], [A.1],
[B], [27], [1], [2],
[20], [22.1]
- 21.Dec 98
- found a russian translation, bob jones' and masami chikahiro's links
are broken
- 12.Jul 98
- changed posting frequency to monthly.
Some minor fixes concerning the now available Visual Lisp
and other cosmetics. cadsyst url
- 6.Jun 98
- changed Eugene's email
- 13.May 98
- added R14 plotdialog [21.2]
- 11.May 98
- bugfixes by Serge Pashkov <xrs@aha.ru> in [24] arc2bul, [20.1]
remove-if-not (but correct in faq-code.lsp), [21.7] doc of maptrans0-1,
[24] tan, [21.2] DDECMD and some vlisp beta1 fixes in faq-code.lsp
- v2.0 7.May 98
- lots of Visual Lisp based changes: [0],[4],[5],[6.1],[7]
[17] new, [2] new books, [21.2] ActiveX sample,
[A.1]better official R14 FAQ
- 27.Feb 98
- [0] Visual Lisp available.
- 24.Feb 98
- [6.1] lspedit.exe, [0] Visual Lisp news and [7] entmake vertex
- v1.12 12.Feb 98
- Eugene Tenenbaum <et119@columbia.edu> send me huge list of
corrections, mostly improving the english language. This time only up to [11].
- 15.Jan 98
- [7] HATCH added to entget problem,
[0] more specific now, [22.4] url change
[A.1] Japanese translation
- 12.Jan.98
- [2] The R13 lisp manual is in the cust. manual not only on the cd. sorry
- 8.Jan.98
- Vladimir Nesterowsky's new web url
- 24.Nov.97
- fixed some typos
- v1.11 15.Nov.97
- changed header.
Autodesk AutoCAD FAQ URL's. see [A.1]
LispLink editor. see [6.1]
Zoomer rumors: [0]
- 23.Oct.97
- Roger Rosec provided a french translation of the entire FAQ. see [A.1]
- 13.Sep 97
- Alan Williams detected a stupid error in DATESTAMP in [22.2]
but in FAQ-CODE.LSP it was okay.
- 28.Aug 97
- added the (entget) LWPLOYLINE bug to [7],
changed my mail address to rurban@xarch.tu-graz.ac.at to be prepared for
the after-student area. :)
- v1.10 22.Jul 97
- some LWPOLYLINE fixes, R14 Lisp debugger
Vital LISP 3.0 shipped,
Convert 3.3 update [4.4],
fixed cronjob for bi-weekly posting: every 2nd Monday, 11.30 MET
- 20.Jul 97
- Vital LISP 3.0 shipped
- 12.Jul 97
- Convert 3.3 update [4.4], fixed cronjob for bi-weekly posting: every 2nd
Monday, 18.00 MET
- 2.July 97
- fixed URL in [10],
- 30.June 97
- fixed (istypep) in [20.4],
changed title of [16],
light changes in (getpts) in [23.1]
- v1.9 26.June 97
-
[5.2] confirmed Vill3 release date,
added DDE sample from Xiang Zhu to [21.2],
provided detab.lsp [25]
- 17.June 97
- bugfix in [20.4]: short (getval),
[12] R14 ARX autoloading,
[23.5] (pline-segs) is now R14-save but still not compatible,
new [23.6] revpoly.lsp,
[A.1],
[5.2] Vill 3 will have reactor support.
- 9.June 97
- new symbol-string trick by Christoph Candido [20.3]
- 21.May 97
- some minor corrections.
- v1.8 15.May 97
-
added [0] Future of AutoLISP?
changed VERTECES to VERTICES, fixed mail address of af.buturovic@berwanger.com,
added SSAPPLY: [20.4], [23.5],
started to R14'ify some code for LWPOLYLINE's [23],
not finished yet, (pline-segs) is missing
- 9.May 97
- [2.1] R14 Winhelps,
[5.2]: new basis url, Vill Lite [6.1]
added [16]: Lisp over mult. dwg's
added some short comments to [6.1](ntemacs),
[14], [21.8]
- 21.April 97
- added [[28] ACIS decryption
- v1.7 9.April 97
- added [[21.8] C:XYZ,
added [[15] (command "ROTATE3D") does not work! Why?
HTML version chapter numbers match the posted version,
added [27]: (command) as ctrl-c,
Sergei Komarov improved [27],
Adi Buturovic improved [27] for scripts.
- v1.6 13.Feb 97
- moved the intro to the very beginning for the curious.
another lisp plot lisp [21.2], a third lisp debugger [3.1],
[A.1]: the gd.tuwien uunet mirror is faster than the official ones,
fixed cadence FAQ url, applied digest format partially, html will be
created automatically soon, wrong (old) chapter numbering from the v1.5 version,
[7] 64 in flag 70 in symbol tables,
- v1.5 5.Feb 97
-
added get and edlgetent samples by Vladimir, removed the sort code
instead,
changed [11] title and added string funcnames,
bugfix in getpts [23.1], basic funcs should be free [A],
added DATESTAMP to [22.2], added a "s" to [A] title,
added [20] DCL, [21] EED, [21.1-21.7] samples,
Serguei Komarov found a bug in seg2cir,arclen,arc2bul [24],
added arc2ang and (corrected) arclen,
bugfixes in sslist, getval, all predicates with "p" postfix now,
prepared a FAQ-CODE.LSP, Convert supercedes Decrypt [4.4],
added scripts and (command) to [23.4], AREA to [23.5],
- v1.4 24.Jan 97
-
important news with Decrypt [4.4],
moved [11] "bugs" to [7] "problems",
added [11] "How do I (sym, list)" instead,
added the "Approved" header for news.answers processing,
added [22]-[24]: some examples for subentities and bulge stuff,
Serge found a bug/feature in acad_strlsort [7],
added number accuracy and ss limitation to [7],
added break code and samples to [3.3],
added a short lisp style guide at [2.2], instead of [6.4]
- v1.3 17.Jan 97
-
added [16] stack overflow (thanks Serge), [4.7] Lisp2C,
updated [8] fastest sort (sample, benches),
received the news.anwsers approval
- v1.2 11.Jan 97
-
added Phoaks to news archive
fixed (break) in [3.3] (Thanks Tony),
added a sorting example to [8], improved (my-princ) in [15]
changed posting frequency from weekly to bi-weekly
- v1.1 4.Jan 97
-
R13 bugs, S::STARTUP code by Owen Wengerd,
homepages instead of e-mail adresses where appropriate,
(people get enough junk mail these days)
more links, and some bugfixes
- v1.0 22.Dec 96
-
First version, posted on 28.Dec 96
as a discussion basis