Getting the type of an AutoCAD solid using .NET

Now this may seem like a very trivial post, but this was actually a significant problem for my team when preparing the material for the Autodesk Component Technologies presentation we delivered at last year's DevDays tour.

Basically the "type" (or really "sub-type") of a Solid3d (an AcDb3DSolid in ObjectARX) is not exposed through ObjectARX and therefore neither is it exposed through the managed interface. It is possible to get at the information from C++ using the Brep API, but this is currently not available from .NET (and yes, we are aware that many of you would like to see this point addressed, although I can't commit to when it will happen).

But there is some good news: the property is exposed through COM, so we can simply get a COM interface for our solid and query the data through that. Thanks again for Fenton Webb, a member of DevTech Americas, for the tip of using COM rather than worrying about the Brep API.

Here's some C# code demonstrating the technique:

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Interop.Common;

namespace SolidTest

{

  public class Cmds

  {

    [CommandMethod("GST")]

    static public void GetSolidType()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

      Database db = doc.Database;

      PromptEntityResult per =

        ed.GetEntity("\nSelect a 3D solid: ");

      if (per.Status == PromptStatus.OK)

      {

        Transaction tr =

          db.TransactionManager.StartTransaction();

        using (tr)

        {

          DBObject obj =

            tr.GetObject(per.ObjectId, OpenMode.ForRead);

          Solid3d sol = obj as Solid3d;

          if (sol != null)

          {

            Acad3DSolid oSol =

              (Acad3DSolid)sol.AcadObject;

            ed.WriteMessage(

              "\nSolid is of type \"{0}\"",

              oSol.SolidType

            );

          }

          tr.Commit();

        }

      }

    }

  }

}

And here's what we see when we run the GST command, selecting a number of Solid3d objects, one by one:

Command: GST

Select a 3D solid:

Solid is of type "Box"

Command:  GST

Select a 3D solid:

Solid is of type "Sphere"

Command:  GST

Select a 3D solid:

Solid is of type "Wedge"

Command:  GST

Select a 3D solid:

Solid is of type "Cylinder"

Command:  GST

Select a 3D solid:

Solid is of type "Cone"

Command:  GST

Select a 3D solid:

Solid is of type "Torus"

One response to “Getting the type of an AutoCAD solid using .NET”

  1. Larry Burnett Avatar

    Hello Kean,

    I have been studying your great articles. They have been very helpful in getting me up to speed with AutoCAD 2008 .NET. I was wondering if you might know how to go about aligning 3d objects? For example you have two cylinders in your drawing and they are perpendicular in relation to each other and you want to get them where they are collinear so they would share the same axis and their faces would be facing each other.
    I know there has to be a TransformBy applied to on of the objects, but setting up the matrix correctly is where I am stumped. I still can't grasp the Matrix3d.

    Thanks Kean!
    Larry

  2. Hi Larry,

    That's an interesting question... I imagine that you'd need to get the solid's faces and the planes of those faces, and then use the geometry libary to calculate the transformation(s) needed to make them co-planar. The bad news is that the BRep API (which would be needed to traverse the solid's faces) is not currently available in .NET (so you'd need to use at least some C++, for now).

    Sorry not to have better news for you,

    Kean

  3. David Wishengrad Avatar
    David Wishengrad

    Hi Larry,
    I realize I am pretty late on this post, but here it goes:

    My programmers created an API, in C++ ARX, that traverses the 3D Solids Exterior Loops,
    Interior Loops, and Edges, and then returns:
    The number of faces
    The vertexes of each face
    The area of each face
    The normal and inverse normal of the faces
    The radius values of planer 3d curves
    The cylinder holes
    and a few others

    The API can be accessed from Visual Basic 6, VB.NET, C# and Lisp.

    I am not sure how many programmers would want this API, but I know we really needed it. If the demand is there I would consider making it available.

    David Wishengrad
    President and CTO
    MillLister, Inc.

  4. And just to add something from my side: we exposed the BRep API to be usable from .NET with AutoCAD 2009, in case this helps.

    Regards,

    Kean

  5. Hi Kean,

    Are there any options to write/edit eg. Cylinder properties?

    I managed to get more specific Cylinder properties by using the Cylinder.Create() Method. This way I can get/set the Radius property, but the Height property throws an AccessViolationException.

    I must be doing something wrong, but what would be the correct way?

    (more info at discussion.autodesk.... )

  6. Hi Bert,

    Sorry - I'm just getting ready for a trip (I leave for China tomorrow morning), so don't have time to look at this.

    Hopefully you'll get a response via the discussion group.

    Regards,

    Kean

  7. Hello Kean,

    Can you give some advices how to get dimension geometry of selected entities. Also interesting how get dimensions in format which needed for creating this type of entities e.g. (For sphere get point and radius , for cylinder get point, radius and height).

    Thank you,
    Volodymyr

    1. Kean Walmsley Avatar

      Hi Volodymyr,

      This seems a bit off topic: could you please post it to the AutoCAD .NET Discussion Group? I assume you're looking for help defining a jig to let the user create solid geometry, but I'm not completely sure.

      Regards,

      Kean

      1. Hello Kean,

        You almost guessed. I will explain by example. Imagine that we have the drawing file which contains different entities e.g. (solids and also simple geometry like line, rectangle, circle). I need select one of this entities and get it type (you showed how to get type in that topic ) and also get dimensions that later I could convert in format that I need.

        AutoCAD .NET Discussion Group It's a disqus.com ?

        Thank you,
        Volodymyr

        1. Kean Walmsley Avatar

          Hi Volodymyr,

          Here's the link to the discussion group:

          forums.autodesk.com/

          Regards,

          Kean

  8. Hello!
    And if the object is not a basic Acad primitive (Box, Sphere,...), for example, the box was converted by the subtraction command, then there will be a fatal error in the line:
    oSol.SolidType;

    after:
    Acad3DSolid oSol = (Acad3DSolid)sol.AcadObject;

    The most interesting thing is that other properties, for example, oSol.Volume, do not cause a fatal error.

Leave a Reply to Larry Burnett Cancel reply

Your email address will not be published. Required fields are marked *