Get all entities inside a blockreference

Get all entities inside a blockreference

哀家爆
Enthusiast Enthusiast
5,313 Views
15 Replies
Message 1 of 16

Get all entities inside a blockreference

哀家爆
Enthusiast
Enthusiast

Hi, I've had some problems trying to get all entities inside a blockreference. As the following pic, there are 4 lines and another blockreference inside a blockreference.

niaxiapiaF4Z8Y_0-1637495933716.png

var entities = new List<Entity>();
var objects = new DBObjectCollection();
block.Explode(objects);

the objects returns me only 4 lines but no blockreference.

What is amazing is that when I mirror the whole blockreference and execute the code again, I can get 4 lines and a blockreference from the mirrored blockreference.

Is there sth wrong with my code, or is there a better way to get all entities inside a blockreference.

Thanks.

0 Likes
Accepted solutions (2)
5,314 Views
15 Replies
Replies (15)
Message 2 of 16

_gile
Consultant
Consultant

Hi,

A block reference (BlockReference) does not contain entities, it is just a reference to a block definition (BlockTableRecord) which does contain entities.

You can get the ObjectId of the block definition using the BlockReference.BlockTableRecord property, open the BlockTablerecord for read and iterate through its contents.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 16

哀家爆
Enthusiast
Enthusiast

Thanks for your answer. 

How am I supposed to understand that we can obtain the DBObjectCollection by using :

blockReference.Explode();

And I did get what I wanted by using the 'Explode()' method in most cases.

In the example above, the blockReference consists of four lines and another blockReference. In general, I can get what I want. Just this time I do not know what reason cause the 'Explode()' method to lose a blockReference.

0 Likes
Message 4 of 16

hosneyalaa
Advisor
Advisor

Hi

Please look at this is

https://forums.autodesk.com/t5/net/how-to-get-poin-center-of-circle-in-block/m-p/10354555

 

Change this 

 

id.ObjectClass.DxfName.ToUpper() == "CIRCLE")

 

To

 

id.ObjectClass.DxfName.ToUpper() == "line")
0 Likes
Message 5 of 16

哀家爆
Enthusiast
Enthusiast

Hi, _gile

var blockTableRecordId = block.BlockTableRecord;
BlockTableRecord blockTableRecord = null;
using (var ts = block.Database.TransactionManager.StartTransaction())
{
    blockTableRecord = ts.GetObject(blockTableRecordId, OpenMode.ForRead) as BlockTableRecord;
    foreach (var id in blockTableRecord)
    {
        var ent = (Entity)ts.GetObject(id, OpenMode.ForRead);
        ent.TransformBy(block.BlockTransform);
        entities.Add(ent);
     }
}

Now I use your way to get all entities from a blockreference (throuth the blocktablerecord), and get the correct result.

But the following statement :

ent.TransformBy(block.BlockTransform);

throw a exception :

Autodesk.AutoCAD.Runtime.Exception:“eMissingSymbolTableRec”

What is wrong with this?

Best regards!~

0 Likes
Message 6 of 16

哀家爆
Enthusiast
Enthusiast

Hi, _gile

Now I use your way to get all entities from a blockreference (throuth the blocktablerecord), and get the correct result.

var blockTableRecordId = block.BlockTableRecord;
BlockTableRecord blockTableRecord = null;
using (var ts = block.Database.TransactionManager.StartTransaction())
{
    blockTableRecord = ts.GetObject(blockTableRecordId, OpenMode.ForRead) as BlockTableRecord;
    foreach (var id in blockTableRecord)
    {
        var ent = (Entity)ts.GetObject(id, OpenMode.ForRead);
        ent.TransformBy(block.BlockTransform);
        entities.Add(ent);
     }
}

But the following statement :

 ent.TransformBy(block.BlockTransform); 

throw a exception : Autodesk.AutoCAD.Runtime.Exception:“eMissingSymbolTableRec”

What is wrong with this? Best regards!~

0 Likes
Message 7 of 16

_gile
Consultant
Consultant

I was just trying to reply to your question : "is there a better way to get all entities inside a blockreference."

 

        private static IEnumerable<Entity> GetEntitiesWithinBlock(BlockReference br) =>
            ((BlockTableRecord)br.BlockTableRecord.GetObject(OpenMode.ForRead))
            .Cast<ObjectId>()
            .Select(id => (Entity)id.GetObject(OpenMode.ForRead));


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 8 of 16

_gile
Consultant
Consultant
Accepted solution

You should not tranform the entity within the block definition, you should clone it and transform the clone.

        private static IEnumerable<Entity> GetEntitiesWithinBlock(BlockReference br)
        {
            var btr = (BlockTableRecord)br.BlockTableRecord.GetObject(OpenMode.ForRead);
            var ids = new ObjectIdCollection(btr.Cast<ObjectId>().ToArray());
            var mapping = new IdMapping();
            br.Database.DeepCloneObjects(ids, br.OwnerId, mapping, false);
            foreach (IdPair pair in mapping)
            {
                if (pair.IsCloned && pair.IsPrimary)
                {
                    var entity = (Entity)pair.Value.GetObject(OpenMode.ForWrite);
                    entity.TransformBy(br.BlockTransform);
                    yield return entity;
                }
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 9 of 16

哀家爆
Enthusiast
Enthusiast

thanks a lot,I will try again.

0 Likes
Message 10 of 16

哀家爆
Enthusiast
Enthusiast

What if I want to get all entities recursively?

 

public static void GetEntitiesWithinBlock(BlockReference br, Document doc, ref List<Entity> entities)
        {
            using (var ts = doc.Database.TransactionManager.StartTransaction())
            {
                var btr = (BlockTableRecord)br.BlockTableRecord.GetObject(OpenMode.ForRead);
                var ids = new ObjectIdCollection(btr.Cast<ObjectId>().ToArray());
                var mapping = new IdMapping();
                br.Database.DeepCloneObjects(ids, br.OwnerId, mapping, false);
                var asd = br.BlockTransform;
                foreach (IdPair pair in mapping)
                {
                    if (pair.IsCloned && pair.IsPrimary)
                    {
                        var entity = (Entity)ts.GetObject(pair.Value, OpenMode.ForWrite);
                        if (entity is BlockReference blockReference)
                        {
                            GetEntitiesWithinBlock(blockReference, doc, ref entities);
                        }
                        else
                        {
                            entity.TransformBy(br.BlockTransform);
                            entities.Add(entity);
                        }
                    }
                }
            }
        }

 

And the statement: entity.TransformBy(br.BlockTransform); throw a new exception: eCannotScaleNonUniformly.

Thanks a lot!

0 Likes
Message 11 of 16

_gile
Consultant
Consultant
        private static IEnumerable<Entity> GetEntitiesWithinBlock(BlockReference br)
        {
            var btr = (BlockTableRecord)br.BlockTableRecord.GetObject(OpenMode.ForRead);
            var ids = new ObjectIdCollection(btr.Cast<ObjectId>().ToArray());
            var mapping = new IdMapping();
            br.Database.DeepCloneObjects(ids, br.OwnerId, mapping, false);
            foreach (IdPair pair in mapping)
            {
                if (pair.IsCloned && pair.IsPrimary)
                {
                    var entity = (Entity)pair.Value.GetObject(OpenMode.ForWrite);
                    if (entity is BlockReference)
                    {
                        entity.TransformBy(br.BlockTransform);
                        foreach (var ent in GetEntitiesWithinBlock((BlockReference)entity))
                        {
                            yield return ent;
                        }
                        entity.Erase();
                    }
                    else
                    {
                        entity.TransformBy(br.BlockTransform);
                        yield return entity;
                    }
                }
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 12 of 16

哀家爆
Enthusiast
Enthusiast

When the entity is BlockReference, 

entity.TransformBy(br.BlockTransform);

throw the exception: eMissingSymbolTableRec.

It seems that AutoCAD doesn't allow us to transform a blockReference which is within another blockReference .

0 Likes
Message 13 of 16

_gile
Consultant
Consultant

@哀家爆  a écrit :

When the entity is BlockReference, 

entity.TransformBy(br.BlockTransform);

throw the exception: eMissingSymbolTableRec.

It seems that AutoCAD doesn't allow us to transform a blockReference which is within another blockReference .


We do not transform the block reference which is within the block definition, we transform the clone.

The upper code works for me.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 14 of 16

哀家爆
Enthusiast
Enthusiast

Could you please help me to test the attached dwg file.

I've no idea why the exception happens in my test.

Thank you very much !

0 Likes
Message 15 of 16

_gile
Consultant
Consultant
Accepted solution

In the "blocktest"drawing, the block is not uniformy scaled.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 16 of 16

NSJamieLiu
Community Visitor
Community Visitor

hi there: I am facing the same problem. I want to transform inner objects within a non uniformy scaled blockrefernce. So what should I do if the blockrefernce is not uniform scaled?

 

all the best

 

0 Likes