December 2014

Sun Mon Tue Wed Thu Fri Sat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      










« Using a palette from .NET to display properties of multiple AutoCAD objects | Main | Coming in September: Autodesk DevCamps - Customization and Application Development Conferences »

July 18, 2007

Accessing DWG files not open in the AutoCAD editor using .NET

This topic was briefly introduced almost a year ago, in this post. I then looked into the code a little further in a follow-up post. But at the time this topic wasn't the main thrust of the post, it was really more of an implementation detail.

So now it's time to do the topic a little more justice. :-)

Let's start with some terminology. What we're talking about today are often referred to as "side databases" or "external databases". Basically they're DWG files that are not open in the AutoCAD editor, but ones we want to access programmatically to load geometry or settings. You may also hear the term "lazy loaded" - these DWG files are not loaded completely into memory (unless you choose to access all the data stored in them), they are brought in, as needed, making the access very efficient.

Side databases have been available through ObjectARX since it was introduced in R13, but were introduced more recently in COM (the AxDb implementation was introduced several releases back, although I can't remember exactly when... perhaps it was in AutoCAD 2000 but it might have been later) and .NET (when we introduced the managed layer in 2005, I believe). One interesting point to note, is that any code you write using ObjectARX or .NET to access side databases can be used with almost no modification on top of RealDWG to access the same data outside AutoCAD. Although any code that's intermingled which accesses AutoCAD-resident functionality will not work, of course.

The basic technique is to create a Database object, and read a DWG file into it. Please remember to use the appropriate constructor: the standard constructor without arguments creates a Database object that cannot be used in this manner (it creates one that you would typically use to create a new DWG file). When reading a DWG you will need to pass False as the first argument - what you pass as the second depends on your need.

From there you work with the Database object, accessing the header variables and the objects stored in the various dictionaries and symbol tables, just as you would inside AutoCAD.

Let's take a very simple example, where we open a particular file on disk, and iterate through the model-space, listing a little bit of data about each object:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;


namespace ExtractObjects

{

  public class Commands

  {

    [CommandMethod("EOF")]

    static public void ExtractObjectsFromFile()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;


      // Ask the user to select a file

      PromptResult res =

        ed.GetString(

          "\nEnter the path of a DWG or DXF file: "

        );


      if (res.Status == PromptStatus.OK)

      {

        // Create a database and try to load the file

        Database db = new Database(false, true);

        using (db)

        {

          try

          {

            db.ReadDwgFile(

              res.StringResult,

              System.IO.FileShare.Read,

              false,

              ""

            );

          }

          catch (System.Exception)

          {

            ed.WriteMessage(

              "\nUnable to read drawing file."

            );

            return;

          }


          Transaction tr =

            db.TransactionManager.StartTransaction();

          using (tr)

          {

            // Open the blocktable, get the modelspace

            BlockTable bt =

              (BlockTable)tr.GetObject(

                db.BlockTableId,

                OpenMode.ForRead

              );


            BlockTableRecord btr =

              (BlockTableRecord)tr.GetObject(

                bt[BlockTableRecord.ModelSpace],

                OpenMode.ForRead

              );



            // Iterate through it, dumping objects

            foreach (ObjectId objId in btr)

            {

              Entity ent =

                (Entity)tr.GetObject(

                  objId,

                  OpenMode.ForRead

                );


              // Let's get rid of the standard namespace

              const string prefix =

                "Autodesk.AutoCAD.DatabaseServices.";

              string typeString =

                ent.GetType().ToString();

              if (typeString.Contains(prefix))

                typeString =

                  typeString.Substring(prefix.Length);


              ed.WriteMessage(

                "\nEntity " +

                ent.ObjectId.ToString() +

                " of type " +

                typeString +

                " found on layer " +

                ent.Layer +

                " with colour " +

                ent.Color.ToString()

              );

            }

          }

        }

      }

    }

  }

}

Here's what happens when you run the code:

Command: EOF


Enter the path of a DWG or DXF file: "C:\Program Files\Autodesk\AutoCAD

2007\Sample\Sheet Sets\Architectural\S-03.dwg"


Entity (2127693096) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693104) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693112) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693120) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693128) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693224) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693232) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693368) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693376) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693384) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693392) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693400) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693408) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693416) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693424) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127695000) of type Line found on layer 2_Arch_Plan_Dim with colour

BYLAYER

Entity (2127695448) of type BlockReference found on layer 0 with colour BYLAYER

Entity (2127624240) of type BlockReference found on layer Building Section (2)

with colour BYLAYER

Entity (2127656048) of type BlockReference found on layer Structrual Base2 with

colour BYLAYER

Entity (2127656304) of type BlockReference found on layer grid plan with colour

BYLAYER

Entity (2127656560) of type BlockReference found on layer Stair 2 with colour

BYLAYER

I'm interested in looking at more complex scenarios where people might need to access side databases from their code. Please post any suggestions you might have as a comment (or just drop me an email).

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83452464869e200e008da8ba58834

Listed below are links to weblogs that reference Accessing DWG files not open in the AutoCAD editor using .NET:

blog comments powered by Disqus

Feed/Share

10 Random Posts