Ein paar Worte vorabHome   Letzte MeldungenNews   Index der Kapitel und der besprochenen FunktionenIndex   Wer ich bin, warum ich diese Seiten mache, KontaktImpressum   Ich freue mich über jeden Eintrag im Gästebuch!Gästebuch   Einige Links zu anderen AutoLisp-SeitenLinks   Copyrights und DisclaimerRechts
Hier können die kompletten Seiten als ZIP-File heruntergeladen werden!

Berechnen von arithmetischen Ausdrücken in der Kommandozeile Sitz!Platz!Fass!
Das Verschachteln von Ausdrücken Alte Schachtel!
Das Speichern von Werten in Variablen Gebunkert
Verhindern der Evaluation mit Quote Bergbäche
Erzeugen von einfachen Listen in AutoLisp Brot,Eier,Käse
Einfache Funktionen zur Listenbearbeitung ...um die Wurst
Funktionen für den Zugriff auf Listenelemente Was ein Salat!
Über Haupt- und Nebeneffekte von Funktionen Schwer schuften
Das Definieren von eigenen Funktionen in AutoLisp Ostfriesischer...
Lokale Variablen und Funktionsargumente in AutoLisp Kondome!
Das Laden von Programmdateien in AutoLisp Banküberfall
Verzweigung in Funktionen aufgrund von Entscheidungen Wenn das Wort...
Zusammenfassen von Entscheidungen mit den Logik-Funktionen Ins Schweinderl
Mehrfach-Verzweigungen in AutoLisp mit Cond 3. Strasse links
Schleifen zum Steuern des Ablaufs in AutoLisp-Funktionen Wie im Fernsehen
Testfunktionen zum Steuern von Schleifen in AutoLisp Schwanger?
Gleichheitstests als Schleifenkriterium in AutoLisp Noch gleicher?
Zeichneketten-Bearbeitung in AutoLisp Rauchzeichen
Funktionen zur Konvertierung von Datentypen in AutoLisp Wasser zu Wein
Komplexere Funktionen für die Bearbeitung von Listen in AutoLisp Nicht arbeiten...
Das Erzeugen von anonymen Funktionen mit lambda Schwarze Kutte
Das Bearbeiten von Listenelementen mit foreach Jedem das Seine
Erzeugen und Verwenden von Assoziationslisten in AutoLisp Beim Psychiater
Zugriff auf Geometriedaten und Erzeugen von Geometrieelementen Ententanz
Der Umgang mit Auswahlsätzen in AutoLisp Jung gefreit...
Auswahl von AutoCAD-Zeichnungsgeometrie mit ssget Raffgierig!
Verändern von Zeichnungs-Geometrie mit entmod Flickschusterei
Das Erzeugen von Geometrie mit entmake Houdini
Über Programmierstile in AutoLisp, Teil 1 Emma
Über Programmierstile in AutoLisp, Teil 2 Sti(e)lblüten
Über Programmierstile in AutoLisp, Teil 3 Eingewickelt
Über Programmierstile in AutoLisp, Teil 4 Doofe Frisur?


Zum den Seiten für Fortgeschrittene

Zu den ActiveX-Seiten

Meine Private HP mit Fotos, Gedichten, Musik und Postkartenversand

Mein Online-Lexikon der Fotografie

Mein völlig abgedrehtes Reisebüro










Nachdem nun in den bisherigen Kapiteln die notwendigen Grundlagen geklärt wurden, können wir uns nun dem zuwenden, worum es ja eigentlich geht: AutoCAD-Programmierung mit AutoLisp. In diesem Kapitel werden wir uns mit der Geometrie-Datenbank von AutoCAD befassen und dabei einige neue Funktionen kennenlernen, die uns den Zugriff auf die Datenbank bzw. auf Zeichnungselemente ermöglichen.

Probieren wir doch gleich mal die erste dieser Funktionen aus! Sie heisst (entlast), bekommt keine Argumente und gibt uns den Entity-Namen des letzten Elementes in der Zeichnung zurück:
(entlast) => <Objektname: 400acee8>

; oder, wenn die Zeichnung leer ist

(entlast) => nil
                  
Nun, mit diesem Entity-Namen selbst können wir gar nichts anfangen. Es ist nichts weiter als ein Identifikator für ein Zeichnungselement, und das Gemisch aus Ziffern und Buchstaben (nur a-f) ist nichts weiter als eine Speicheradresse in hexadezimaler Schreibweise.

Allerdings gibt es Funktionen, die einen solchen Entity-Namen (das Symbol, dass uns die Funktion (type ...) für diesen Datentyp zurückgibt, heisst übrigens ENAME) als Argument erwarten. Wir leiten daher einfach mal die Rückgabe von (entlast) an (entget) weiter, aber zuvor zeichnen wir schnell mit AutoCAD einen Kreis mit Mittelpunkt bei 12.2,23.4 und Radius 44.3. Dann untersuchen wir, was nun in Lisp passiert:
(entget(entlast)) =>
((-1 . <Objektname: 40505d58>) (0 . "CIRCLE")
(330 . <Objektname: 40505cf8>) (5 . "2B") (100 . "AcDbEntity")
(67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbCircle")
(10 12.2 23.4 0.0) (40 . 44.3) (210 0.0 0.0 1.0))
                  
Zunächst eines vorweg: Diese Liste kann bei Ihnen ganz anders aussehen. Je nach AutoCAD-Version können einige Dinge fehlen, und natürlich werden einige Elemente der Liste auch andere Werte haben. Die hexadezimalen Zahlen des Eintity-Namens werden sicher anders sein, aber damit müssen Sie sich sowieso nie befassen. Eines ist aber sicher: Wenn Ihre Liste nicht den Eintrag (0 . "CIRCLE") hat, dann haben Sie nicht als letztes einen Kreis gezeichnet!

Manche Dinge sind recht offensichtlich: (0 . "CIRCLE") kennzeichnet die Tatsache, dass es sich um einen Kreis handelt, (10 12.2 23.4 0.0) müssen die Koordinaten des Mittelpunkts sein, und (40 . 44.3) stellt wohl den Radius dar. Und insgesamt handelt es sich klar erkennbar um eine Assoziationsliste, denn es gibt keine Einzelelemente, sondern Unterlisten, die als erstes Element eine Zahl haben, die wie ein Assoziationsschlüssel aussieht.

Versuchen wir doch einmal, unser Wissen aus dem Kapitel über Assoziationslisten anzuwenden:
(cdr(assoc 0(entget(entlast))))
    => "CIRCLE"

(cdr(assoc 10(entget(entlast))))
    => (12.2 23.4 0.0)

(cdr(assoc 10(entget(entlast))))
    => 44.3
                  
Wir sehen, dass die dotted pairs doch gar nicht so schlimm sind - ganz im Gegenteil: Hier erweisen sie sich plötzlich als sehr praktisch! Da, wo ein einzelner Wert vorliegt (bei "CIRCLE" und dem Radius, gibt uns (cdr(assoc ...)) ein Atom zurück, und da, wo es um eine Liste geht, nämlich beim Mittelpunkt, bekommen wir mit dem gleichen Ausdruck auch eine Liste. Wir sollten also spätestens jetzt unsere Einstellung zu den gepunkteten Paaren doch ein wenig revidieren und uns mit ihnen anfreunden.

Was sind das für Ziffern, die wir hier als Assoziationschlüssel verwenden? Es handelt sich um die berühmt-berüchtigten DXF-Gruppencodes von AutoCAD, die auch (daher der Name) in DXF-Dateien (= Drawing eXchange Format) verwendet werden. Eine komplette Auflistung aller Gruppencodes findet man in der Online-Hilfe zu AutoLisp, aber Achtung: Zum Einen sind es sehr viele, zum Anderen sind manche recht schwer zu verstehen.

Wir wissen bisher Folgendes: Der Gruppencode 0 regelt den Typ des Geometrie-Elementes, 10 den Mittelpunkt und 40 den Radius. Wird das bei einer Linie auch so sein? Wohl kaum: Eine Linie hat keinen Mittelpunkt und keinen Radius. Vergleichen wir doch einfach und ziehen dann unsere Schlüsse. Wir zeichnen schnell eine Linie von (6.2 5.7 0.0) nach (12.7 9.9 0.0) und rufen dann noch einmal (entget(entlast ...)) auf. Halt! Nicht gleich loslegen! Diesmal zeichnen wir die Linie nicht mit AutoCAD, sondern aus Lisp heraus. Kopieren Sie den (command ...)-Aufruf einfach in die Kommandozeile!
(command "_line" '(6.2 5.7 0.0) '(12.7 9.9 0.0) "")
                  
(command ...) ist nichts weiter als eine Funktion, die Befehle von Lisp an AutoCAD weiterleitet. Mit der Schreibweise an einigen Stellen müssen wir uns aber kurz befassen: Die Koordinaten für Anfangs- und Endpunkt haben wir hier als Lisp-Listen formuliert - (command ...) sorgt automatisch dafür, dass sie bei AutoCAD richtig ankommen. Natürlich müssen diese Punktlisten quotiert werden, sonst gibt's eine Fehlermeldung. (command) quotiert übrigens keines seiner Argumente automatisch.

Der Leerstring am Ende des Aufrufs ist ein <Return>, nichts weiter. Es wird gebraucht, da der Linie-Befehl anders als der Kreis-Befehl ja einer dieser Endlos-Befehle in AutoCAD ist, die erst mit einer Leereingabe beendet sind. Bleibt noch das Kommando selber: "_line" ist die internationale Version des Linie-Befehls. Einer Frage möchte ich gleich vorbeugen: Wo ist der Punkt?

Wer schon ein bisschen Erfahrung mit (command ...) hat, weiss, dass man in fast allen Lisp-Programmen die Schreibweise "_.line" findet. Der Punkt sorgt dafür, dass der originale Linie-Befehl, so wie er in AutoCAD eingebaut ist, zur Anwendung kommt. Ohne den Punkt wird der Linie-Befehl so ausgeführt, wie er in diesem Augenblick definiert ist. Im Augenblick? Ja, man kann sämtliche AutoCAD-Befehle mit Hilfe von Lisp umfunktionieren!

Ich will hier nicht lange darauf eingehen - es gibt gute Gründe für den Punkt, aber es gibt genauso gute Gründe dagegen. Jedenfalls werde ich ihn diesem Tutorial nicht verwenden. Evtl. werde ich diesem Thema irgendwann auch noch ein Kapitel widmen.

Zurück zur Sache! Wir haben nun eine Linie aus Lisp heraus erzeugt, und jetzt werfen wir doch mal einen etwas tieferen Blick auf das, was dabei herausgekommen ist - den (entget)-Blick natürlich:
(entget(entlast)) =>
((-1 . <Objektname: 40505d68>) (0 . "LINE")
(330 . <Objektname: 40505cf8>) (5 . "2D")
(100 . "AcDbEntity") (67 . 0) (410 . "Model")
(8 . "0") (100 . "AcDbLine") (10 6.2 5.7 0.0)
(11 12.7 9.9 0.0) (210 0.0 0.0 1.0))
                  
Wir werden uns sicherlich nicht über (0 . "LINE") wundern, und dass Anfangs- und Endpunkt unter den Gruppencodes 10 und 11 verbucht wurden. Sicherlich handelt es sich um eine 2D-Linie, aber der Kreis war auch zweidimensional, und der hatte den Eintrag "2B" unter Gruppencode 5! Code 5 zeigt uns also nicht an, ob irgendetwas 2D oder 3D ist - es handelt sich um die Referenz!

Die Referenzen sind - hatten wir das nicht schon ein bisschen weiter oben? - hexadezimale Kennungen, die jedem Zeichnungselement zugeordnet sind. Das sind die Entity-Namen auch, aber mit einem wesentlichen Unterschied: Die Objektreferenzen, neudeutsch auch Handles genannt, sind konstant, d.h. sie bleiben für die zugeordneten Zeichnungselemente immer gleich, auch über Arbeitssitzungen hinweg. Die Entity-Namen sind aus den derzeitigen Speicheradressen abgeleitet und ändern sich bei jeder Arbeitssitzung. Daher darf man Entity-Namen nie abspeichern und später wiederverwenden!

Der Entity-Name, den wir von (entlast) an (entget) übergeben haben, ist übrigens unter Gruppencode -1 zu finden. Der zweite Entity-Name, der unter Code 330 verbucht ist, spielt im Moment noch keine Rolle für uns. Es macht auch gar nichts, wenn der 330er Code auf ihrem Rechner gar nicht erscheint.

Vielleicht haben Sie auch schon gemerkt, dass sich hinter dem Gruppencode 8 der Layer des Geometrie-Elements verbirgt. Damit haben wir die wichtigsten Daten für unsere Beispiele erst einmal besprochen - alles andere lassen wir jetzt einfach stehen und versuchen ein kleines Experiment: Mit (entmake ...) kann man Geometrie erzeugen - ein völlig anderer Weg wie über einen (command)-Aufruf, aber mit dem gleichen Resultat. Wir 'basteln' uns ein paar Daten für eine Linie:
(setq hausmacher-linie
  (list
    (cons 0 "LINE")
    (cons 8 "0")
    (cons 10 '(0 0))
    (cons 11 '(25 35))
  )
)
                  
Natürlich sind da einige Dinge weniger drin, als in den Listen, die uns (entget) zurückgibt, aber es ist auf jeden Fall das enthalten, was die Linie wirklich ausmacht - und dazu sogar noch eine Layerangabe. Versuchen wir's einfach:
(entmake hausmacher-linie) =>
((0 . "LINE") (8 . "0") (10 0 0) (11 25 35))
                  
Wir sehen: Die Linie erscheint augenblicklich auf dem Bildschirm, und (entmake) gibt uns die eingefütterten Daten unverändert zurück.

Fassen wir zusammen, was wir in diesem Kapitel gelernt haben:
  • (entlast) gibt uns den Eintity-Namen des zuletzt erzeugten Geometrie-Elements zurück

  • Mit (entget ...) erhalten wir die Liste mit den Geometriedaten zu einem eingegebenen Entity-Namen

  • Mit (command ...) und (entmake ...) stehen uns zwei vom Ansatz her völlig unterschiedliche Wege zur Erzeugung von Geometrie zur Verfügung

  • Die Entity-Datenlisten sind Assoziationslisten, in denen DXF-Gruppencodes als Schlüssel verwendet werden

  • Die 'Zauberformel' für den Zugriff auf Geometriedaten im Einzelnen lautet (cdr(assoc <gruppencode>(entget ...)))


Übungsaufgaben

  1. Erläutern Sie noch einmal den Unterschied zwischen Entity-Namen (Gruppencode -1)und den Objektreferenzen (Gruppencode 5)

  2. Welches sind die Gruppencodes für Layer und Kreisradius?

  3. Was wird unter dem Gruppencode 0 verbucht?

  4. Welche der folgenden Aussagen sind richtig?
    • (entget ...) gibt einen Entity-Namen zurück

    • (entlast ...) gibt die Objektreferenz des zuletzt erzeugten Geometrie-Elementes zurück

    • Mit (command ...) kann man AutoCAD-Befehle aus Lisp heraus ausführen

    • Einen (command ...)-Aufruf muss man immer mit einem Leerstring beenden

    • (entmake ...) gibt die eingegebene Datenliste zurück, ohne sie zu verändern, wenn der Aufruf erfolgreich war

    • Keines der Argumente für (command) wird automatisch quotiert

    • (entmake) und (entget) sind Funktionen mit ausgeprägtem Seiteneffekt

  5. Was gibt (entlast) zurück, wenn das zuletzt erzeugte Geometrieelement inzwischen wieder gelöscht wurde?

  6. In den(entget)-Beispielen auf dieser Seite kam ein Gruppencode 330 vor, der einen Entity-Namen enthielt. Wie kann man mit (entget) darauf zugreifen, und was für ein Entity-Typ ist das?

  7. Erzeugen Sie einen Kreis (MP: 64.3,-25.8 R:28.24) mit (command) und anschliessend mit (entmake). Prüfen Sie nach, ob beide Kreise deckungsgleich aufeinander liegen.

  8. Haben Sie in unseren Beispielen eigentlich die Gruppencodes entdeckt, die Farbe und Linientyp des Kreises bzw. der Linie enthalten?

  9. Was passiert, wenn Sie in unserem (entmake)-Test einen Layer (Gruppencode 8) angeben, der gar nicht existiert?

  10. Was passiert, wenn Sie in unserem (entmake)-Test gar keinen Layer angeben, d.h. Gruppencode 8 wird weggelassen?

Lösungen