Walkthrough: Arbeiten mit AutoCAD- und AS-API

Die Advance Steel-API kann mit der AutoCAD-API verwendet werden.

Da Advance Steel auf AutoCAD aufsetzt, kann die AutoCAD-API zusammen mit der Advance Steel-API in einem Advance Steel-Plugin verwendet werden. Häufige Verwendungen der AutoCAD-API aus einem Advance Steel Plugin:

In dieser Übungslektion werden verschiedene Beispiele aufgeführt. Weitere Informationen zur AutoCAD-API finden Sie in der Online-Hilfe für die AutoCAD Managed .NET API.

Verwenden von Transaktionen mit AutoCAD- und AS-API

Arbeiten mit der AutoCAD-API

Erstellen Sie ein neues Advance Steel-Plugin wie in früheren Lernprogrammen beschrieben. Neben den zu referenzierenden Advance Steel-Baugruppen müssen auch mehrere AutoCAD-Baugruppen aus dem Projekt referenziert werden:
  • AcCoreMgd
  • AcDbMgd
  • AcMgd

Erstellen Sie eine neue Klasse namens WorkingWithAutoCADAPI und fügen Sie den folgenden Code hinzu:

Code-Region: Befehlsklasse WorkingWithAutoCADAPI

using Autodesk.AdvanceSteel.CADAccess;
using Autodesk.AdvanceSteel.DocumentManagement;
using Autodesk.AdvanceSteel.Modelling;
using Autodesk.AdvanceSteel.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System.Windows.Forms;

namespace WorkingWithAutoCADandASAPI
{
    class WorkingWithAutoCADAPI
    {
        [CommandMethodAttribute("TEST_GROUP", "WorkingWithAutoCADAPI", "WorkingWithAutoCADAPI",
                                                       CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
        public void Create()
        {
            using (DocumentAccess da = new DocumentAccess(null, false))
            {
               da.Commit();
            }
        }
    }
}

Beachten Sie, dass für diese Übungslektion vier using-Anweisungen für AutoCAD-API-Namensbereiche erforderlich sind. Die AutoCAD-API und Advance Steel haben einige gemeinsame Klassennamen, beispielsweise ObjectId. Dadurch wird eine Unterscheidung im Code erforderlich. Anstatt den Namensbereich vor dem Klassennamen einzufügen, können Sie eine Richtlinie zur Verwendung eines Alias am Anfang der Datei verwenden, um einen kürzeren Namen für die Klassen zu erstellen. In dieser Übungslektion verwenden wir drei Richtlinien zur Verwendung eines Alias, wie im umgeschriebenen Code unten dargestellt.

Code-Region: Klassennamen eindeutig machen

using Autodesk.AdvanceSteel.CADAccess;
using Autodesk.AdvanceSteel.DocumentManagement;
using Autodesk.AdvanceSteel.Modelling;
using Autodesk.AdvanceSteel.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using System.Windows.Forms;
using ACTransaction = Autodesk.AutoCAD.DatabaseServices.Transaction;
using ASObjectId = Autodesk.AdvanceSteel.CADLink.Database.ObjectId;
using ACDocument = Autodesk.AutoCAD.ApplicationServices.Document;
using Autodesk.AutoCAD.Geometry;

namespace WorkingWithAutoCADandASAPI
{
    class WorkingWithAutoCADAPI
    {
        [CommandMethodAttribute("TEST_GROUP", "WorkingWithAutoCADAPI", "WorkingWithAutoCADAPI",
                                                       CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
        public void Create()
        {
            using (DocumentAccess da = new DocumentAccess(null, false))
            {
               da.Commit();
            }
        }
    }
}

Die anderen Richtlinien zum Verwenden eines Alias werden später im Lernprogramm verwendet.

Verwenden der Bereichsauswahl in AutoCAD

In der Übungslektion Walkthrough: Erstellen Sie Träger und Blechbearbeitungen wurde die Verwendung der UserInteraction-Klasse erläutert, damit der Benutzer ein Objekt auswählen kann, das bearbeitet werden soll. In dieser Übungslektion wird beschrieben, wie das Auswahlfenster in AutoCAD verwendet wird, um Objekte basierend auf dem Standort automatisch auszuwählen.

Fügen Sie die Methode unterhalb der WorkingWithAutoCADAPI-Klasse ein. In dieser Methode wird ein kreuzendes Fenster verwendet, um Objekte innerhalb eines rechteckigen Bereichs zu finden. Dann wird überprüft, ob es sich dabei um gerade Träger handelt und es wird der erste gerade Träger angezeigt, der gefunden wird.

Code-Region: Auswählen eines Trägers

private StraightBeam GetStraightBeam()
{
    StraightBeam beam = null;
    //Try to get a beam repr using AutoCad selection window
    PromptSelectionResult acSSPrompt;
    Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
    acSSPrompt = ed.SelectCrossingWindow(new Point3d(0, 0, 0), new Point3d(1000, 0, 0));

    if (acSSPrompt.Status == PromptStatus.OK)
    {
        SelectionSet acSSet = acSSPrompt.Value;
        ObjectId[] ids = acSSet.GetObjectIds();

        //Iterate through the selected objects, and check if we have a straight beam
        foreach (ObjectId id in ids)
        {
            //Get the beam filer object
            ASObjectId idDbObject =
                DatabaseManager.GetFilerObjectId(new ASObjectId(id.OldIdPtr), false);
            FilerObject obj = DatabaseManager.Open(idDbObject);

            //If we have a straight beam
            if (obj.Type() == FilerObject.eObjectType.kStraightBeam)
            {
                beam = obj as StraightBeam;
                break;
            }
        }
    }

    return beam;
}

Dualität von Advance Steel-Objekten

Beachten Sie im Beispielcode oben, dass Autodesk.AutoCAD.DatabaseServices.ObjectId nach dem Abrufen in ein Autodesk.AdvanceSteel.CADLink.Database.ObjectId konvertiert wird, bevor überprüft wird, ob es sich um ein StraightBeam handelt. Das liegt an der Dualität von Advance Steel-Objekten. Advance Steel-Objekte bestehen allgemein aus zwei AutoCAD-Objekten: dem „internen“ Objekt und dem Darstellungsobjekt. Normalerweise kann ein Advance Steel-Benutzer nur auf das Darstellungsobjekt zugreifen. Das heißt, wenn ein Benutzer einen Träger in Advance Steel auswählt, wählt er die Darstellung des Trägers aus.

Um erfolgreich mit Advance Steel- und AutoCAD-API zu arbeiten, kommt es darauf an zu verstehen, welches Objekt erforderlich ist. Sie müssen bei AutoCAD-Aktionen für ein Objekt die „Darstellungs“-ID, für Aktionen der AdvanceSteel-API mit demselben Objekt hingegen die interne ID verwenden. Wenn Objekt-IDs durch Aufrufen von Methoden abgerufen werden, geben Advance Steel-Methoden immer IDs der internen Objekte zurück, während AutoCAD API-Aufrufe immer die IDs der Darstellungsobjekte zurückgeben. Die Advance Steel-API bietet Methoden zum Wechseln von einem ID-Typ zum anderen.

Auflösen eines Advance Steel-Objekts

Als Nächstes wird beschrieben, wie die AutoCAD-API zum Auflösen eines Advance Steel-Objekts verwendet wird. Dies funktioniert ähnlich wie die Auswahl eines Advance Steel-Trägers und der Aufruf des Befehls „Auflösen“. So werden aufgelöste Linien zurückgegeben, aber dies wirkt sich nicht auf das Modell aus. Die resultierenden einfacheren Objekte können exportiert oder für Berechnungen oder andere Zwecke verwendet werden.

Code-Region: Auflösen eines Trägers

private int ExplodeBeam(StraightBeam beam)
{
    int nExplodedEnts = 0;
    // get the "representation" id - the id that AutoCAD understands as being the object drawn on the screen
    ASObjectId reprId = DatabaseManager.GetReprId(beam);

    // convert this id from "AdvanceSteel" id to "Acad" id
    ObjectId acadIdBeam = new ObjectId(reprId.AsOldId());

    // start an AutoCAD transaction
    DocumentCollection docs = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager;
    ACDocument currDoc = docs.CurrentDocument;
    Autodesk.AutoCAD.DatabaseServices.Transaction trans = currDoc.TransactionManager.StartTransaction();

    // use the transaction to gain access to the beam representation as an AutoCAD entity
    DBObject objBeam = trans.GetObject(acadIdBeam, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite);
    if (objBeam is Autodesk.AutoCAD.DatabaseServices.Entity)
    {
        Entity ent = (Entity)objBeam;

        // ask autoCAD to "explode" this beam - equivalent of selecting an advance steel beam from the screen and calling "explode" command
        DBObjectCollection explodedEnts = new DBObjectCollection();
        ent.Explode(explodedEnts);
        nExplodedEnts = explodedEnts.Count;

        trans.Commit();
    }

    return nExplodedEnts;
}

Beachten Sie, dass die oben beschriebene Methode zuerst die Advance Steel-ID in eine AutoCAD-ID umwandelt, da die AutoCAD-Methode zum Auflösen auf das Objekt angewendet werden soll.

Kehren Sie jetzt zur ursprünglichen Create()-Methode für WorkingWithAutoCADAPI zurück und rufen Sie beide Methoden auf – eine zum Abrufen eines geraden Trägers in Advance Steel und eine, um diesen aufzulösen.

Code-Region: Zusammensetzen

public void Create()
{
    using (DocumentAccess da = new DocumentAccess(null, true))
    {
        StraightBeam beam = GetStraightBeam();
        if (beam != null)
        {
             ExplodeBeam(beam);
        }
    }
}

Erstellen eines Advance Steel-Sonderteils aus einem AutoCAD-Volumenkörper

Sonderteile in Advance Steel sind generische 3D-Objekte, die zu einem Advance Steel-Modell hinzugefügt werden können, um Standardbauelemente zu ergänzen. Sonderteile können genau wie Blockreferenzen aus externen dwg-Dateien erstellt werden, die gültige AutoCAD-Objekte einschließlich Advance Steel-Objekte enthalten. Es wird zuerst ein Volumenkörper erstellt und dann dem Sonderteil zugewiesen.

In diesem Beispiel wird der AutoCAD-3D-Volumenkörper über Programmiercode erstellt; Sie können ihn aber auch manuell erstellen. Fügen Sie die folgende Methode der Klassendatei hinzu, um einen Keil zu erstellen.

Code-Region: Erstellen eines AutoCAD 3D-Volumenkörpers

private ObjectId CreateAutoCADWedge()
{
    ObjectId ret;
    // Get the current document and database, and start an AutoCAD transaction
    ACDocument acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
    Database acCurDb = acDoc.Database;

    using (ACTransaction acTrans = acCurDb.TransactionManager.StartTransaction())
    {
        // Open the Block table record for read
        BlockTable acBlkTbl;
        acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForWrite) as BlockTable;

        // Open the Block table record Model space for write
        BlockTableRecord acBlkTblRec = new BlockTableRecord();

        acBlkTblRec.Name = "wedge";

        // Create a 3D solid wedge
        Solid3d acSol3D = new Solid3d();
        acSol3D.SetDatabaseDefaults();
        acSol3D.CreateWedge(10, 15, 20);

        // Position the center of the 3D solid at (5,5,0) 
        acSol3D.TransformBy(Matrix3d.Displacement(new Point3d(5, 5, 0) - Point3d.Origin));

        // Add the new object to the block table record and the transaction
        acBlkTblRec.AppendEntity(acSol3D);
        acBlkTbl.Add(acBlkTblRec);
        acTrans.AddNewlyCreatedDBObject(acBlkTblRec, true);

        // Save the new objects to the database
        acTrans.Commit();

        ret = acBlkTblRec.Id;
    }

    return ret;
}

Beachten Sie, dass die Methode eine ObjektId für BlockTableRecord zurückgibt. Diese wird zuerst in eine Advance Steel-ObjectId umgewandelt und dann für das Sonderteil verwendet. Fügen Sie die folgende Methode hinzu, um ein Sonderteil zu erstellen.

Code-Region: Erstellen eines Sonderteils

private void CreateSpecialPart()
{
    SpecialPart specialPart = new SpecialPart(new Autodesk.AdvanceSteel.Geometry.Matrix3d());
    specialPart.WriteToDb();

    ObjectId newBlock = CreateAutoCADWedge();
    specialPart.SetBlock(new ASObjectId(newBlock.OldIdPtr), 1.0);
}
Fügen Sie jetzt einen Aufruf dieser Methode der Create()-Methode hinzu.

Code-Region: Zusammensetzen

public void Create()
{
    using (DocumentAccess da = new DocumentAccess(null, false))
    {
        StraightBeam beam = GetStraightBeam();
        if (beam != null)
        {
            ExplodeBeam(beam);
        }

        CreateSpecialPart();
        da.Commit();
    }
}

Befehlsreaktoren

Manchmal ist es hilfreich, auf einen Befehl in AutoCAD zu reagieren. Ein Advance Steel-Plugin kann ein CommandEnded-Ereignis abonnieren, sodass es benachrichtigt wird, wenn ein Befehl ausgeführt wurde und weitere Schritte erforderlich sind. In diesem Beispiel erstellen wir eine Methode, in der bei neuen Trägern, die zu einem Advance Steel-Modell hinzugefügt wurden, geprüft wird, ob alle Träger (einschließlich des neuen Trägers) die Mindestlänge für Träger aufweisen. (Ist dies nicht der Fall, wird eine Warnung ausgegeben).

Code-Region: CommandEnded-Reaktor

void CurrentDocument_CommandEnded(object sender, Autodesk.AutoCAD.ApplicationServices.CommandEventArgs e)
{
    // If a beam has just been created
    if (e.GlobalCommandName == "ASTM4CRBEAMBYCLASS")
    {
        using (DocumentAccess da = new DocumentAccess(null, true))
        {
           try
           {
               ASObjectId[] ids;
               ClassTypeFilter filter = new ClassTypeFilter();
               filter.AppendAcceptedClass(FilerObject.eObjectType.kStraightBeam);

               //Get all the beams from the database
               DatabaseManager.GetModelObjectIds(out ids, filter);

               foreach (ASObjectId id in ids)
               {
                   FilerObject obj = DatabaseManager.Open(id);

                   if (obj != null)
                   {
                       StraightBeam sb = obj as StraightBeam;
   
                       // check that beam meets minimum length for project
                       double length = sb.GetLength();
                       if (length < 305)
                       {
                           MessageBox.Show("Minimum beam length is 305 mm. Please adjust beam.");
                       }
                   }
               }
            }
            catch(System.Exception ex)
            {
               MessageBox.Show(ex.Message);
            }
        }
    }
}

Beachten Sie bei dieser Methode, dass GlobalCommandName geprüft wird, um sicherzustellen, dass es sich um ASTM4CRBEAMBYCLASS handelt, den Befehl, der angibt, dass ein neuer Advance Steel-Träger erstellt wurde. Der Befehlsname kann von einem anderen Plugin, zum Beispiel CREATEFEATURES, oder einem anderen integrierten Befehl aus Advance Steel oder AutoCAD erstellt worden sein. Wenn Sie den Namen des Befehls nicht kennen, für den Sie den Reaktor erstellen möchten, dann erstellen Sie einfach eine Befehlsreaktormethode wie oben und setzen Sie einen Haltepunkt in der Methode, um den Wert von e.GlobalCommandName zu prüfen, wenn der Befehl am Ende des gewünschten Befehls ausgelöst wird.

Da diese Methode aufgerufen wird, wenn ein Befehl beendet ist und sie sich nicht innerhalb des Umfangs der in der Create()-Methode gestarteten Transaktion befindet, muss CurrentDocument_CommandEnded eine eigene Transaktion sowie Aufrufe zum Sperren und Freigeben des aktuellen Dokuments aufweisen.

Damit Ihr Befehlsreaktor abgerufen wird, muss er innerhalb des aktuellen Dokuments registriert sein. Fügen Sie den folgenden Code zur WorkingWithAutoCADAPI-Klasse hinzu, um die Methode CurrentDocument_CommandEnded zu registrieren.

Code-Region: Registrieren eines Befehlsreaktors

private void AddCommandEndedReactor()
{
    DocumentCollection docs = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager;
    ACDocument currDoc = docs.CurrentDocument;
    currDoc.CommandEnded += CurrentDocument_CommandEnded;
}
Fügen Sie jetzt einen Aufruf dieser Methode der Create()-Methode hinzu.

Code-Region: Zusammensetzen

public void Create()
{
    using (DocumentAccess da = new DocumentAccess(null, false))
    {

        StraightBeam beam = GetStraightBeam();
        if (beam != null)
        {
           ExplodeBeam(beam);
        }

        CreateSpecialPart();

        AddCommandEndedReactor();
    }
}

Nach dem Abrufen der WorkingWithAutoCADAPI-Methode in Advance Steel wird die Methode CurrentDocument_CommandEnded aufgerufen, wann immer ein Befehl in AutoCAD oder Advance Steel endet.