.NET

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

Find nested blocks in XREFs

578 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: 662
Registered: ‎06-02-2009
Message 2 of 12 (532 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: 405
Registered: ‎08-15-2003
Message 3 of 12 (513 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: 662
Registered: ‎06-02-2009
Message 4 of 12 (505 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: 405
Registered: ‎08-15-2003
Message 5 of 12 (494 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: 338
Registered: ‎05-12-2009
Message 6 of 12 (490 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: 405
Registered: ‎08-15-2003
Message 7 of 12 (483 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: 338
Registered: ‎05-12-2009
Message 8 of 12 (465 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: 405
Registered: ‎08-15-2003
Message 9 of 12 (448 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,129
Registered: ‎04-29-2006
Message 10 of 12 (434 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
Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Do you have 60 seconds to spare? The Autodesk Community Team is revamping our site ranking system and we want your feedback! Please click here to launch the 5 question survey. As always your input is greatly appreciated.