.NET

Reply
Distinguished Contributor
alex_b
Posts: 396
Registered: ‎08-15-2003
Message 1 of 12 (492 Views)

Find nested blocks in XREFs

492 Views, 11 Replies
02-23-2014 06:20 AM

Hi,

 

Please consider this scenario:

 

Current Database curDb;

|--containing one or more XREF references

|----some of them containing one or more XREF references

|--

|--

|------some of them containig exactly one BlockReference;

 

The only thing known at runtime is the BlockReference name, call it blName.

Now I need to find all instances of blName, retrieve each instance's insert point and transform it to the curDb World UCS.

And I need it in C#.

 

One thing is certain: As the nesting level is not known in advance, one must use recursion.

I was able to find the BlockDefinition of blName and I'm stuck here.

I confess I am completely lost, even after reading the - not so rich - info I was able to find here and elsewhere.

 

Any pointers would be much apreciated.

 

alex

ADN Support Specialist
philippe.leefsma
Posts: 631
Registered: ‎06-02-2009
Message 2 of 12 (446 Views)

Re: Find nested blocks in XREFs

02-25-2014 03:14 PM in reply to: alex_b

We have several samples about reading the xrefs on our blog, I doubt you took a look up there:

 

http://adndevblog.typepad.com/autocad/2012/06/finding-all-xrefs-in-the-current-database-using-cnet.h...

 

I would also be very surprised you cannot find any .Net xref sample on Kean's blog:

 

hhttp://through-the-interface.typepad.com/through_the_interface/

 

Based on the first sample and as you mentioned, recursion, you should be able to achieve that task.

 

Regards,

Philippe.

 

 



Philippe Leefsma
Developer Technical Services
Autodesk Developer Network

Distinguished Contributor
alex_b
Posts: 396
Registered: ‎08-15-2003
Message 3 of 12 (426 Views)

Re: Find nested blocks in XREFs

02-26-2014 01:23 PM in reply to: philippe.leefsma

Philippe,

 

Thank you for pointing Stephen's article to me. I must've missed it.

It, of course, works in its scope.

What I need though, and can't make it work, is to find each instance (BlockReference) of a particular block (name known), embedded in some of the xrefs.

And to complicate it even more, for each instance of the block, I need to transform its local coordinates to the parent drawing, so I have to return transform matrices all the way back the recursion.

An additional problem is that the parent xref may be itself referred multiple times in its parent.

Now, from one of Balaj's posts: "AcDbXrefGraph maps singular parent-child linkages, even for xrefs that are multiply referenced in the current drawing".

If I understand this correctly, what I need to do is impossible using this approach (of traversing the XrefGraph), but it's my first time with XrefGraph, so..

Please correct me if I'm wrong. Am I missing something?

 

Regards,

 

alex

ADN Support Specialist
philippe.leefsma
Posts: 631
Registered: ‎06-02-2009
Message 4 of 12 (418 Views)

Re: Find nested blocks in XREFs

02-26-2014 03:12 PM in reply to: alex_b

The task seems easier to me than what you suggest. The xref graph allows you to list all the xrefs in a drawing, once you get the name of the BlockTableRecord you are interested in, you can access it from the BlockTable, then you can use BlockTableRecord.GetBlockReferenceIds to retrieve all references of that block in a specific database. As you mentionned, you would need to propagate the bref transformation in your recursive call, so at each level you will be able to compute the total transformation, simply by multiplying matrices, this seems rather straighforward to do, but you may struggle a bit with the details, I don't have a sample that does exactly this to provide unfortunately.

 

Regards,

Philippe.



Philippe Leefsma
Developer Technical Services
Autodesk Developer Network

Distinguished Contributor
alex_b
Posts: 396
Registered: ‎08-15-2003
Message 5 of 12 (407 Views)

Re: Find nested blocks in XREFs

02-26-2014 09:09 PM in reply to: philippe.leefsma

Philippe,

 

The problem is with the regular block embedded in some of the xrefs, at some level, which is what I'm looking for.

I need to locate all its instances visible in the document.

I can't seem to be able to find it (either its BlockTableRecord, nor any references to it).

 

Thank you,

 

alex

Valued Mentor
jeff
Posts: 330
Registered: ‎05-12-2009
Message 6 of 12 (403 Views)

Re: Find nested blocks in XREFs

02-26-2014 09:35 PM in reply to: alex_b

As Philippe mentioned just look in the BlockTable

 

The name will be

blName

if brought in from xref the name will be

xrefName|blName

 

the xref can be nested 17,345,678 times deep but the block name will be XrefName|BlockName

Just like layer names from xrefs in the layer palette

You can also find your answers @ TheSwamp
Distinguished Contributor
alex_b
Posts: 396
Registered: ‎08-15-2003
Message 7 of 12 (396 Views)

Re: Find nested blocks in XREFs

02-26-2014 11:29 PM in reply to: jeff

Jeff,

 

I am aware of that, but this is just the block definition.

I just don't succeed finding the BlockReferences for xrefName|blName.

Obviously I'm missing something.

 

Thanks,

 

alex

 

 

Valued Mentor
jeff
Posts: 330
Registered: ‎05-12-2009
Message 8 of 12 (378 Views)

Re: Find nested blocks in XREFs

02-28-2014 10:05 AM in reply to: alex_b

As Philippe mentioned once you have the BlockTableRecord use GetBlockReferenceIds

You can also find your answers @ TheSwamp
Distinguished Contributor
alex_b
Posts: 396
Registered: ‎08-15-2003
Message 9 of 12 (361 Views)

Re: Find nested blocks in XREFs

03-01-2014 11:53 AM in reply to: jeff

Jeff,

 

I already got that.

Now I'm struggling with the recursion.

To ilustrate the problem I attach DAG.png, with the XrefGraph on the left and the actual objects in dwg on the right.

Please observe tha XR1 is inserted in XRC 3 times.

The regular block blName is inserted in XR3 at position X,Y in local WCS.

What I need to do is find all blName instances in dwg (there are 5) and find each's location in dwg WCS.

And I can't seem to solve the recursion.

Any ideas will be welcome.

 

alex

*Expert Elite*
_gile
Posts: 2,084
Registered: ‎04-29-2006
Message 10 of 12 (347 Views)

Re: Find nested blocks in XREFs

03-02-2014 10:57 AM in reply to: alex_b

Hi,

 

If I don't misunderstand the task, this seems to work.

 

using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

[assembly: CommandClass(typeof(FindBlocksInXref.CommandMethods))]

namespace FindBlocksInXref
{
    public class CommandMethods
    {
        [CommandMethod("Test")]
        public void Test()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                db.ResolveXrefs(true, false);
                BlockTableRecord mspace =
                    (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
                List<Point3d> insPts = new List<Point3d>();
                GetInsertPositions(db, "", Matrix3d.Identity, insPts);
                foreach (Point3d pt in insPts)
                {
                    DBPoint dbPt = new DBPoint(pt);
                    mspace.AppendEntity(dbPt);
                    tr.AddNewlyCreatedDBObject(dbPt, true);
                }
                tr.Commit();
            }
        }

        private void GetInsertPositions(Database db, string prefix, Matrix3d xform, List<Point3d> insPoints)
        {
            Transaction tr = db.TransactionManager.TopTransaction;
            BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
            string blkName = prefix + "blName";
            if (bt.Has(blkName))
            {
                BlockTableRecord btr =
                    (BlockTableRecord)tr.GetObject(bt[blkName], OpenMode.ForRead);
                foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                {
                    BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                    insPoints.Add(br.Position.TransformBy(xform));
                }
            }
            XrefGraph graph = db.GetHostDwgXrefGraph(true);
            GraphNode root = graph.RootNode;
            for (int i = 0; i < root.NumOut; i++)
            {
                XrefGraphNode node = (XrefGraphNode)root.Out(i);
                if (node.XrefStatus == XrefStatus.Resolved)
                {
                    BlockTableRecord xrBtr =
                        (BlockTableRecord)tr.GetObject(node.BlockTableRecordId, OpenMode.ForRead);
                    foreach (ObjectId id in xrBtr.GetBlockReferenceIds(true, false))
                    {
                        BlockReference xref = (BlockReference)tr.GetObject(id, OpenMode.ForRead); ;
                        if (xref.OwnerId == SymbolUtilityServices.GetBlockModelSpaceId(db))
                            GetInsertPositions(node.Database, node.Name + "|", xform * xref.BlockTransform, insPoints);
                    }
                }
            }
        }
    }
}

 

Gilles Chanteau
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 or visit the Installation and Licensing Forum to get help installing your software.