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










Wir kennen Auswahlsätze aus der Zeichenarbeit mit AutoCAD - jede Objektwahl (ausser dann, wenn es um eine Einzelwahl geht, z.B. bei PEDIT) wird in einem Auswahlsatz zwischengespeichert. Auch in AutoLisp können wir mit Auswahlsätzen arbeiten - es handelt sich aber nicht um Lisp-Listen, sondern um einen eigenen Datentyp ((type ...) gibt das Symbol PICKSET für einen Auswahlsatz zurück).

Wir können also nicht mit den Listenfunktionen auf Auswahlsätze zugreifen. Lisp stellt für das Arbeiten mit Auswahlsätzen die folgenden Funktionen bereit:
  • (ssget ...) zum Auswählen von Objekten
  • (sslength ...) Länge eines Auswahlsatzes
  • (ssname ...) Zugriff auf ein Entity
  • (ssadd ...) Hinzufügen eines Entity
  • (ssdel ...) Entfernen eines Entity
  • (ssmemb ...) Testfunktion für Entity
Diese Liste ist nicht vollständig, es gibt noch drei weitere Funktionen, auf die ich hier nicht eingehe, um die Sache halbwegs übersichtlich zu halten.

(ssget ...) ist die komplexeste Funktion in AutoLisp, deshalb gibt es zu diesem Thema ein eigenes Kapitel. Wir werden uns hier darauf beschränken, (ssget) ohne Argumente aufzurufen. In diesem Fall hat der Benutzer die freie Wahl, wie und welche Objekte er auswählt. Diese Objekte bekommen wir dann in Form eines Auswahlsatzes zurück, den wir anschliessend mit den anderen oben erwähnten Funktionen untersuchen und bearbeiten können.

Die Standard-Vorgehensweise beim Auswerten von Auswahlsätzen ist die, dass in einer (while)-Schleife der Satz durchgegangen wird und über (ssname) sukzessive auf die darin enthaltenen Entitynamen zugegriffen wird. Dazu ein kleines Beispiel, das aber einen kleinen Schönheitsfehler hat:
(defun info-test( / ss i entdata)
  (setq ss(ssget))
  (setq i 0)
  (princ"Gewählte Objekte: \n")
  (while(setq entdata(entget(ssname ss i)))
    (princ(strcat(cdr(assoc 0 entdata))"\n"))
    (setq i(1+ i))
  )
)
                  
Dieses Beispiel erfüllt seinen Zweck ja schon ganz gut, aber es bricht am Ende mit einer Fehlermeldung ab! Die Fehlerstelle ist schnell ermittelt: (entget(ssname ss i)) verursacht den Fehler, wenn wir über das Ende des Auswahlsatzes hinaus zugreifen wollen - (ssname) gibt dann nil zurück, was der Funktion (entget) sauer aufstösst. Wir müssen also noch eine weitere Variable dazwischensetzen:
(defun info-test( / ss i ent data)
  (setq ss(ssget))
  (setq i 0)
  (while(setq ent(ssname ss i))
    (setq data(entget ent))
    (princ(strcat(cdr(assoc 0 data))"\n"))
    (setq i(1+ i))
  )
)
                  
Dieses Beispiel hat gezeigt, wie man einen Auswahlsatz auswertet. Kommen wir nun dazu, wie man einen Auswahlsatz erzeugt - auch das nächste Beispiel ist noch nicht sehr praxisorientiert, aber es demonstriert die Vorgehensweise:
(defun erzeugen-beispiel( / ss ents)
  (setq ss(ssadd))
  (while(setq ent(car(entsel)))
    (ssadd ent ss)
  )
  ss
)
                  
Der Auswahlsatz muss zuerst durch einen Aufruf von (ssadd) ohne Argumente erzeugt werden. Anschliessend kann der Benutzer - jeweils einzeln - so viele Elemente wählen, wie er möchte. Sie werden dem Auswahlsatz hinzugefügt. Wenn der Benutzer kein weiteres Objekt mehr wählt, sondern einfach die Return-Taste drückt, wird die Schleife beendet und der Auswahlsatz zurückgegeben.

Auf eine Eigenheit der (ssadd)-Funktion möchte ich noch hinweisen: Es handelt sich um eine Seiteneffekt-Funktion! Wir sind es ja z.B. von den Listenfunktionen gewohnt, den Haupteffekt aufzufangen und einer Variablen zuzuweisen bzw. ihn an die nächste Funktion weiterzuleiten. Bei (ssadd) ist dies nicht notwendig - ausser beim ersten Aufruf ohne Argumente natürlich. Da muss einer Variablen zugewiesen werden, sonst erzeugen wir zwar einen Auswahlsatz, können dann aber mangels eines Namens nicht darauf zugreifen.

Was ist, wenn der Benutzer ein Element mehrfach wählt? Dann wird es dem Auswahlsatz doch doppelt eingefügt! - Nein, es ist nicht so. (ssadd) prüft ohne unser Zutun, ob ein Element schon darin vorhanden ist und fügt es nur hinzu, wenn dies nicht der Fall ist. Daher ist es nicht notwendig, vor jedem Aufruf von (ssadd) jedesmal mit (ssmemb) zu testen, ob ein Entity schon eingefügt wurde.

(ssmemb) bleibt also den Fällen vorbehalten, wo ein Test unumgänglich wird, z.B. wenn mit zwei Auswahlsätzen gearbeitet werden soll und sichergestellt sein soll, dass ein Element nicht gleichzeitig in beiden Sätzen enthalten sein darf. (ssmemb) und (ssdel), das ein Entity aus einem Auswahlsatz entfernt, sind übrigens so einfach in der Anwendung, dass ich hier auf weitere Beispiele verzichten möchte.

Wesentlicher ist ein anderer Gedanke: Das Durcharbeiten eines Auswahlsatzes in der oben beschrieben Form ist mühsam. Listen bearbeiten wir mit (foreach) oder (mapcar), wir brauchen dafür nicht jedesmal eine Schleifenkonstruktion zu bauen und einen Zähler anzulegen. Wenn es um Auswahlsätze geht, ist allerdings in AutoLisp kein Komfort zu finden - da müssen wir selbst Hand anlegen.

Auf meinen Fortgeschrittenen-Seiten ist die Definition zu einer Funktion (ss-foreach ...) zu finden. Ich stelle sie hier kurz vor:
(defun ss-foreach(ss expr / i)
  (if ss
    (repeat(setq i(sslength ss))
      ((eval expr)(ssname ss(setq i(1- i))))
    )
  )
)
                  
Die Funktion erwartet einen Auswahlsatz als Argument sowie einen (lambda)-Ausdruck, der auf die im Auswahlsatz enthaltenen Entities angewendet wird. Das umgebende (if ...) ist übrigens notwendig, da Funktionen wie (ssget) schlicht und einfach nil zurückgeben, wenn nichts gewählt wurde. (sslength nil) gibt dann also nicht 0 zurück (wie man es eigentlich erwarten könnte), sondern verursacht einen Fehler.

Unser erstes Beispiel von oben noch einmal im neuen Gewand:
(defun info-test( / ss i ent data)
  (ss-foreach(ssget)
   '(lambda(ent / )
      (princ
        (strcat(cdr(assoc 0(entget ent))"\n")
      )
    )
  )
)
                  
Die Arbeit mit (ssname) ist eigentlich unter dem Niveau, das die Sprache Lisp hat. Wie man sieht, kann man diese in Erdbodennähe stattfindenden Dinge sehr schön in einer Bibliotheksfunktion kapseln und sich mit Dingen in Kopfhöhe befassen. Ich habe in vielen Jahren des Programmierens mit AutoLisp die Funktion (ssname) jedenfalls nie wieder benötigt (und die anderen sowieso nicht).


Übungsaufgaben

  1. Kann man mit (ssadd) - ähnlich wie man mit (append) zwei Listen zusammenfügt - auch zwei Auswahlsätze zusammenfügen? Bitte ausprobieren!

  2. Welche der folgenden Aussagen sind richtig?
    • Wenn man nur (ssadd ent ss) schreibt, verpufft die Rückgabe, man muss also die Rückgabe mit setq wieder zuweisen: (setq ss(ssadd ent ss))

    • Wenn man einem Auswahlsatz Entities hinzufügt, muss man vorher mit (ssmemb) testen, ob das Entity nicht bereits enthalten ist.

    • Ein Auswahlsatz kann maximal so lang sein, wie es Elemente in der Zeichnung gibt.

    • (sslength) gibt bei einem leeren Auswahlsatz 0 zurück.

    • Bei (ssname) beginnt die Zählung genau wie bei (nth) und (substr) bei 0, d.h. das erste Element eines Auswahlsatzes erhalten wir mit (ssname 0 ss).

  3. Schreiben Sie eine Funktion, die den Benutzer auffordert, einige Entities zu wählen. Den Auswahlsatz legen Sie in einer globalen Variablen namens *ss* ab. Probieren Sie aus, ob Sie dann in AutoCAD innerhalb eines Befehls mit !*ss* den Auswahlsatz in eine Objektwahl (z.B. bei LÖSCHEN) 'einfüttern' können.

Lösungen