.NET

Reply
Contributor
autogis
Posts: 14
Registered: ‎11-13-2013
Message 1 of 6 (173 Views)
Accepted Solution

Retrieving all objects by layer

173 Views, 5 Replies
05-07-2014 07:48 AM

Folks this is my first autocad development project.  I am trying to retrieve all the leaders from a specific layer.  This is what I have so far:

 

static public void ExtractObjectsFromFileByLayer(string fileName)
        {

            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            string objectFilter = "LEADER";
            string layerFilter = "HOMES";

            // Create a database and try to load the file
            Database db = new Database(false, true);
            using (db)
            {
                try
                {
                    db.ReadDwgFile(
                                   fileName,
                                   System.IO.FileShare.Read,
                                   false,
                                   ""
                                  );
                }
                catch (System.Exception)
                {
                    ed.WriteMessage("\nUnable to read drawing file.");
                    return;
                }
            }

            // Create a TypedValue array to define the filter
            // by object types (dxf code 0) and layers (dxf code 8)
            TypedValue[] tvs = new TypedValue[] {
	                                             new TypedValue(0, objectFilter),
	                                             new TypedValue(8, layerFilter)
                                                };

            // Assign the filter criteria to a SelectionFilter object
            SelectionFilter filter = new SelectionFilter(tvs);

            // Setup a Prompt Selection Result object with the SelectionFilter criteria
            PromptSelectionResult res = ed.SelectAll(filter);

            if (res.Status == PromptStatus.OK)
            {

               Transaction tr = db.TransactionManager.StartTransaction();
               using (tr)
               {

                   foreach (ObjectId objId in res.Value.GetObjectIds())
                   {

                       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()
                       );

                   }

               }

            }

        }

 

I am getting an error in the following line:  if (res.Status == PromptStatus.OK)   

 

If anyone can provide me some assistance it would be much appreciated.

 

Thanks before hand.

*Expert Elite*
_gile
Posts: 2,077
Registered: ‎04-29-2006
Message 2 of 6 (162 Views)

Re : Retrieving all objects by layer

05-07-2014 08:44 AM in reply to: autogis

Hi,

 

On one hand, you're using a side Database and on the other you're making a selection set in the current document.

Then you start a Transaction with the side Database TransactionManager to open ObjectId from the current Database...

This won't work.

 

What do you want to achieve ?

 

If you want to get all "LEADER" objects on "HOMES" layer from the side Database (as suggested by the method name) you have to keep in mind you haven't access to the Editor of the side Database document.

You may have to iterate the model space BlockTableRecord entities (and possibly paper spaces) to achieve this.

 

Gilles Chanteau
Contributor
autogis
Posts: 14
Registered: ‎11-13-2013
Message 3 of 6 (160 Views)

Re : Retrieving all objects by layer

05-07-2014 08:57 AM in reply to: _gile

gile, thank you for your help.  Basically this is what I would like to do:  I would like to load an "existing" dwg file (readonly) and then loop through all the leaders for the "HOMES" layer.

*Expert Elite*
_gile
Posts: 2,077
Registered: ‎04-29-2006
Message 4 of 6 (155 Views)

Re : Retrieving all objects by layer

05-07-2014 09:57 AM in reply to: autogis

Try this:

 

        static public void ExtractObjectsFromFileByLayer(string fileName)
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            using (Database db = new Database(false, true))
            {
                try
                {
                    db.ReadDwgFile(fileName, System.IO.FileShare.Read, false, null);
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("\nError: {0}", ex.Message);
                    return;
                }
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(
                        SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                    foreach (ObjectId id in modelSpace)
                    {
                        if (id.ObjectClass.DxfName == "LEADER")
                        {
                            Leader leader = (Leader)tr.GetObject(id, OpenMode.ForRead);
                            if (leader.Layer == "HOMES")
                            {
                                ed.WriteMessage(
                                    "\nEntity {0} of type {1} found on layer {2} with color {3}",
                                    id, leader.GetType().Name, leader.Layer, leader.Color);
                            }
                        }
                    }
                    tr.Commit();
                }
            }
        }

 

Gilles Chanteau
Contributor
autogis
Posts: 14
Registered: ‎11-13-2013
Message 5 of 6 (150 Views)

Re : Retrieving all objects by layer

05-07-2014 10:28 AM in reply to: _gile

Thank you gile that worked great!   I have a question for you.  I did notice it took a long time (the foreach) since it is searching through all object types and all layers (100+ layers in that file).   Is there a way to use some type of filter like I was attempting before it goes into the foreach?  Learning something new every day. :smileyhappy:

*Expert Elite*
_gile
Posts: 2,077
Registered: ‎04-29-2006
Message 6 of 6 (129 Views)

Re : Retrieving all objects by layer

05-07-2014 02:21 PM in reply to: autogis

The number of layers isn't taken in account.

The foreach loop checks every object in the model space (as a Selectall does).

The code is quite opitmized as ObjectIdS are filtered using their ObjectClass property so that only Leader entities are opened to check their Layer property.

Try this LISP expression, which uses a filtered selection, in the file, it may take a long time too...

(sssetfirst nil (ssget "_X" '((0 . "LEADER") (8 . "HOMES"))))

 

Perhaps directly checking the RXClass object of objectIdS is cheaper than checking the RXClass.DxfName, but I'm not certain it's noticeable (I used the DxfName to make the code more readable).

 

Another performance improvement shoud be use an OpenCloseTransaction instead of a simple Transaction as there's no need for an Undo group.

 

        static public void ExtractObjectsFromFileByLayer(string fileName)
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            using (Database db = new Database(false, true))
            {
                try
                {
                    db.ReadDwgFile(fileName, System.IO.FileShare.Read, false, null);
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("\nError: {0}", ex.Message);
                    return;
                }
                using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
                {
                    BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(
                        SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                    RXClass leaderClass = RXClass.GetClass(typeof(Leader));
                    foreach (ObjectId id in modelSpace)
                    {
                        if (id.ObjectClass == leaderClass)
                        {
                            Leader leader = (Leader)tr.GetObject(id, OpenMode.ForRead);
                            if (leader.Layer == "HOMES")
                            {
                                ed.WriteMessage(
                                    "\nEntity {0} of type {1} found on layer {2} with color {3}",
                                    id, leader.GetType().Name, leader.Layer, leader.Color);
                            }
                        }
                    }
                    tr.Commit();
                }
            }
        }

 

Gilles Chanteau

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community