Modifying Entities Inside of a cloned BlockReference also changes the original.

Modifying Entities Inside of a cloned BlockReference also changes the original.

gotMorris
Enthusiast Enthusiast
602 Views
3 Replies
Message 1 of 4

Modifying Entities Inside of a cloned BlockReference also changes the original.

gotMorris
Enthusiast
Enthusiast

 I am trying to edit the Entities inside of a cloned block without changing the entities of the original. Any help would be appreciated.

 

var acBlkTbl = tr.GetObject(Active.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
var acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
BlockReference blockCopy = block.Clone() as BlockReference; BlockTableRecord selectedBlockBTR = blockCopy.BlockTableRecord.GetObject(OpenMode.ForWrite) as BlockTableRecord; foreach (ObjectId innerObjectId in selectedBlockBTR) { Entity ent = (Entity)tr.GetObject(innerObjectId, OpenMode.ForWrite); ent.Color = Color.FromColorIndex(ColorMethod.ByPen, 5); }
acBlkTblRec.AppendEntity(blockCopy);
tr.AddNewlyCreatedDBObject(blockCopy, true);

 

0 Likes
Accepted solutions (1)
603 Views
3 Replies
Replies (3)
Message 2 of 4

norman.yuan
Mentor
Mentor

The help you need is not how to modify your code. It is your understanding of block concept: You cannot modify entities inside a BlockReference (actually there is no entities inside a BlockReference, except for AtttibuteReference). A block reference is, well, a reference of a block definition (BlockTableRecord) with some geometric transforms, much like a instant image of a block definition placed in different size (scale), location. You can only chane its definition to change the blockreference's look. It is what your code actually does correctly, but not what you want, because if you change a block definition, all its references also change accordingly, as you have found out.

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 4

ActivistInvestor
Mentor
Mentor

Cloning a block reference only creates another reference to the same BlockTableRecord, just as if you had used the COPY command to copy a block reference.

 

You must clone the BlockTableRecord and then modify the entities in the cloned BlockTableRecord.

 

Then you can clone the BlockReference, and set it's BlockTableRecord property to the ObjectId of the clone of the BlockTableRecord.

 

Lastly, you cannot use Clone() to clone most objects. You must use the Database's DeepCloneObjects() method, or for entities (but not BlockTableRecords) you can take a shortcut and invoke the ActiveX Copy() method:

 

   public static ObjectId Copy(this ObjectId source)
   {
      if(source.IsNull)
         throw new ArgumentException("source");
      dynamic acadObject;
      using(DBObject obj = source.Open(OpenMode.ForRead))
         acadObject = obj.AcadObject;
      return DBObject.FromAcadObject(acadObject.Copy());
   }

 

 The above method can't be used to clone a BlockTableRecord, only a BlockReference or other Entity-based type.

 

For the BlockTableRecord, you have to use DeepCloneObjects.

 

 

 

Message 4 of 4

Anonymous
Not applicable
Accepted solution

Hi, IMO you can explode the blockreference. Then you have all the contents of the blockreference as separate entities.

Then you can do whatever you like with them.

 

From Through-the-interface (http://through-the-interface.typepad.com/through_the_interface/2011/02/exploding-autocad-objects-usi...😞

Entity.Explode() is one of those tricky methods: it’s actually a faux-ami with the AutoCAD command of the same name, in a very similar way to Database.Purge(). The way in which Explode() and Purge() differ from their “equivalent” commands is that they’re non-destructive: they don’t actually result in a change to the AutoCAD drawing database. Explode() populates a DBObjectCollection with the results of the explode operation, and it’s then up to the caller of the function to add them to the appropriate location (typically the current – i.e. model- or paper- – space). Purge() checks a list of objects for ones that can safely be erased, and then it’s up to the caller of the function to do so.

 

So using

DBObjectCollection objs = new DBObjectCollection();

entity.Explode(objs);

foreach (DBObject obj in objs)

{

          Entity ent = (Entity)obj;

// Modify to your wishes

          btr.AppendEntity(ent);

          tr.AddNewlyCreatedDBObject(ent, true);

}

You'll have the blockreference (ent) still in your drawing, but also have all objects from within the block added to the drawing.

 

HTH,

Sietse Wijnker