Interaktive Befehle mit Jigs in AutoCAD .NET

CAD-Oberfläche mit 3D-Hausmodell, Menüband und Layerliste

CAD

Ein Befehl fragt „Mittelpunkt:“ und „Radius:“, der Anwender tippt Zahlen und sieht das Ergebnis erst ganz am Schluss. Das funktioniert, fühlt sich aber an wie 1995. AutoCAD zeigt beim Befehl KREIS, wie es besser geht: Der Kreis hängt an der Maus und wächst mit. Diese Vorschau heißt Jig – und mit der .NET-API bauen Sie sie in Ihre eigenen Befehle ein.

Was ein Jig ist

In der Werkstatt ist ein Jig eine Vorrichtung, die das Werkzeug führt, etwa eine Bohrschablone. In AutoCAD führt der Jig nicht den Bohrer, sondern die Maus: Er zeigt ein Element so, wie es aussehen wird, wenn der Anwender jetzt klickt. Der Namensraum Autodesk.AutoCAD.EditorInput bietet zwei Klassen dafür. Ein EntityJig zieht genau ein Element, AutoCAD zeichnet es selbst. Ein DrawJig zeichnet beliebig viel Grafik, muss sich dafür aber um alles selbst kümmern. Gestartet werden beide mit editor.Drag(jig).

Wer ruft wen?

Mit Drag gibt Ihr Befehl die Kontrolle an AutoCAD ab. Ab jetzt ruft AutoCAD Sie: Bei jeder Mausbewegung und jeder Eingabe kommt die Methode Sampler. Meldet sie einen neuen Wert, folgt Update, und AutoCAD zeichnet das Element neu. Das geht so lange, bis der Anwender klickt, einen Wert tippt, ein Schlüsselwort eingibt oder abbricht. Erst dann kehrt Drag mit einem PromptResult zurück.

Ein Kreis-Jig in zwei Schritten

public class KreisJig : EntityJig
{
    private Point3d _mittelpunkt;
    private double _radius = double.NaN;

    public KreisJig() : base(new Circle(Point3d.Origin, Vector3d.ZAxis, 10.0)) { }

    public Circle Kreis => (Circle)Entity;
    public bool RadiusSchritt { get; set; }

    // AutoCAD ruft das bei jeder Mausbewegung auf
    protected override SamplerStatus Sampler(JigPrompts prompts)
    {
        var status = SamplerStatus.Cancel;
        if (!RadiusSchritt)
        {
            var ergebnis = prompts.AcquirePoint(new JigPromptPointOptions("\nMittelpunkt: "));
            if (ergebnis.Status == PromptStatus.OK)
            {
                // Keine Bewegung, kein Neuzeichnen
                status = ergebnis.Value.IsEqualTo(_mittelpunkt)
                    ? SamplerStatus.NoChange : SamplerStatus.OK;
                _mittelpunkt = ergebnis.Value;
            }
        }
        else
        {
            var optionen = new JigPromptDistanceOptions("\nRadius: ")
            {
                BasePoint = _mittelpunkt,
                UseBasePoint = true,
                UserInputControls = UserInputControls.NoZeroResponseAccepted
                    | UserInputControls.NoNegativeResponseAccepted
            };
            var ergebnis = prompts.AcquireDistance(optionen);
            if (ergebnis.Status == PromptStatus.OK)
            {
                status = Math.Abs(ergebnis.Value - _radius) < 1e-9
                    ? SamplerStatus.NoChange : SamplerStatus.OK;
                _radius = ergebnis.Value;
            }
        }
        return status;
    }

    // Überträgt die Werte auf den Kreis, danach zeichnet AutoCAD neu
    protected override bool Update()
    {
        Kreis.Center = _mittelpunkt;
        if (RadiusSchritt)
        {
            Kreis.Radius = _radius;
        }
        return true;
    }
}

Sampler holt die Eingabe über JigPrompts: AcquirePoint für Punkte, AcquireDistance für Abstände, dazu AcquireAngle und AcquireString. Mit BasePoint und UseBasePoint misst AutoCAD den Radius vom Mittelpunkt aus und zeigt eine Gummibandlinie. Die UserInputControls verbieten null und negative Werte. Eine getippte -5 weist AutoCAD dann selbst zurück, ohne eine Zeile eigenen Code. Update überträgt die Werte und gibt true zurück, wenn das Element gültig ist. Der Befehl ruft Drag für jeden Schritt einmal auf:

[CommandMethod("MeinKreisJig")]
public void MeinKreisJig()
{
    var dokument = Application.DocumentManager.MdiActiveDocument;
    var jig = new KreisJig();
    var ergebnis = dokument.Editor.Drag(jig);          // Schritt 1: Mittelpunkt
    if (ergebnis.Status == PromptStatus.OK)
    {
        jig.RadiusSchritt = true;
        ergebnis = dokument.Editor.Drag(jig);          // Schritt 2: Radius
    }
    if (ergebnis.Status == PromptStatus.OK)
    {
        FuegeEin(dokument.Database, jig.Kreis);        // AppendEntity, AddNewlyCreatedDBObject, Commit
        dokument.Editor.WriteMessage(
            $"\nKreis mit Radius {jig.Kreis.Radius} bei {jig.Kreis.Center} gezeichnet.");
    }
    else
    {
        jig.Kreis.Dispose();                           // nie in der Datenbank: selbst entsorgen
    }
}

NoChange: der unscheinbare Rückgabewert

AutoCAD ruft Sampler sehr oft auf, nicht nur, wenn sich wirklich etwas geändert hat. Liefert der Sampler jedes Mal OK, folgt jedes Mal Update samt Neuzeichnen. Die Vorschau flackert, und der Rechner hat gut zu tun. Deshalb vergleicht der Sampler den neuen Wert mit dem alten und meldet bei Gleichheit NoChange. Punkte vergleicht IsEqualTo mit der Toleranz von AutoCAD, Zahlen eine kleine eigene Toleranz.

Schlüsselwörter und dynamische Bemaßung

Wie bei KREIS kann ein Jig Optionen anbieten. Die Schlüsselwörter hängen an den Optionen der Abfrage, etwa mit optionen.Keywords.Add("Durchmesser"). Die Liste in eckigen Klammern schreibt AutoCAD selbst hinter den Text. Tippt der Anwender das Wort, kehrt Drag mit PromptStatus.Keyword zurück. Der Befehl schaltet um und ruft Drag erneut auf – umschalten ist Sache des Befehls, nicht des Samplers.

Eine Bemaßung am Kreis liefert der Jig über die Methode GetDynamicDimensionData. Sie gibt eine DynamicDimensionDataCollection zurück, etwa mit einer AlignedDimension, deren DynamicDimension auf true steht. Der Text "Ø <>" setzt ein Durchmesserzeichen vor den Messwert. Wo die Bemaßung sitzt, legt Update fest.

Mehr als ein Element: DrawJig

Soll der Anwender eine Torte mit fehlendem Stück aufziehen – einen Bogen und eine Polylinie –, reicht ein EntityJig nicht. Der DrawJig überschreibt statt Update die Methode WorldDraw und zeichnet dort mit draw.Geometry.Draw beliebige Elemente, die noch nicht in der Datenbank sind.

Testen ohne Maus

In der AutoCAD-Konsole gibt es keine Maus. Getippte Werte kommen dort aber über dieselben Acquire-Methoden an. Die Logik eines Jig lässt sich deshalb automatisch prüfen:

Befehl: MeinKreisJig
Mittelpunkt: 50,50
Radius: 20
Kreis mit Radius 20 bei (50,50,0) gezeichnet.

Wie die Vorschau aussieht und wie oft der Sampler beim Bewegen der Maus läuft, zeigt dagegen nur das echte AutoCAD.

Typische Fehler

  • Kein NoChange: Die Vorschau flackert, und der Rechner rechnet sich warm.
  • Den Wert benutzen, bevor der Status geprüft ist. Bei Cancel oder Keyword steht dort nichts Brauchbares.
  • Nach einem Abbruch nicht aufräumen. Das Element des Jig kommt nur bei Erfolg in die Datenbank, sonst gehört es entsorgt.
  • Die Schlüsselwörter selbst in den Text schreiben. AutoCAD hängt die Liste ohnehin an.
  • Ungültige Werte in Update per catch abfangen, statt sie vorher auszuschließen.
  • Erwarten, dass das gezogene Element schon eine ObjectId, ein Handle oder Xdata hat.
  • Polyline ist mehrdeutig, sobald GraphicsInterface eingebunden ist. Ein Alias schafft Klarheit.
  • Einen Jig nur zum Anzeigen nutzen. Dafür sind vorübergehende Grafik oder ein Overrule besser.

So helfen wir

  • Schulung: Eigene Befehle, Eingaben und Jigs sind Teil der Schulung „AutoCAD .NET API mit C#“.
  • Projekt: Wir entwickeln Add-ins mit Befehlen, die sich anfühlen wie AutoCAD selbst, oder machen Ihre bestehenden komfortabler. Vereinbaren Sie ein Erstgespräch.
  • Das Buch: Den Kreis-Jig mit Durchmesser-Option, die Torte als DrawJig und eine Übung mit Ellipse zeigt Ebi F. Eilbers Fachbuch „AutoCAD .NET API“, das voraussichtlich 2027 erscheint.

Quelle: Ebi F. Eilber, AutoCAD .NET API (Fachbuch, erscheint voraussichtlich 2027), Kapitel „Jig“

KONTAKT

Sprache auswählen

ErstgesprächvereinbarenErstgesprächvereinbaren