Exploding a block with a nested dynamic block

Exploding a block with a nested dynamic block

Paulio
Advocate Advocate
2,325 Views
9 Replies
Message 1 of 10

Exploding a block with a nested dynamic block

Paulio
Advocate
Advocate

Let's say I have a block called "Car" and a block called "Caravan". The car is a standard block and the caravan is dynamic with options to change the length.

I want my users to be able to insert the car/caravan combination in one go so I combine both blocks into one "Car+Caravan" block but then I explode that block when they insert it. This then means that they have access to the dynamics of the caravan as well as being abe to move the car around independantly of the caravan.

BUT

I want to put the car and caravan in a group so that they will move together if required.

 

So, I've tried the two explode options so far - BlockReference.Explode(idCollection) and BlockReference.ExplodeToOwnerSpace.

 

Method 1: BlockReference.Explode 

 

 

public static ObjectIdCollection ExplodeBlockInsertComponentsAndReturnIdsToGroup(BlockReference blkRef, ref Transaction trans)
{
	Database db = HostApplicationServices.WorkingDatabase;
	BlockTableRecord btr = trans.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
	DBObjectCollection objColl = new DBObjectCollection();
	blkRef.Explode(objColl);
	ObjectIdCollection idsToGroup = new ObjectIdCollection();
	foreach (DBObject obj in objColl) {
		if ((obj) is Entity) {
			ObjectId objId = btr.AppendEntity(obj);
			trans.AddNewlyCreatedDBObject(obj, true);
			idsToGroup.Add(objId);
		}
	}
	return idsToGroup;
}

I then create a group using the returned ids.

 

This almost works but the dynaimcs of the Caravan are lost. It doesn't even seem to realise that it's still a block even though all of the entities of the caravan highlight when I select a bit of it.

 

Method 2: Using ExplodeToOwnerSpace with a Database ObjectAppended handler (like in Kean's post here:http://through-the-interface.typepad.com/through_the_interface/2014/09/exploding-nested-autocad-bloc...)

 

 

        public static ObjectIdCollection idsToGroup;

        public static void ExplodeBlockInsertComponentsAndReturnIdsToGroup(BlockReference blkRef)
        {
            Database db = HostApplicationServices.WorkingDatabase;
            idsToGroup = new ObjectIdCollection();
            db.ObjectAppended += ObjectAppended;
            blkRef.ExplodeToOwnerSpace();
            db.ObjectAppended -= ObjectAppended;
        }

        public static void ObjectAppended(Object sender, ObjectEventArgs e)
        {
            idsToGroup.Add(e.DBObject.ObjectId);
        }

 

 

Again, the returned ids are used to create a group.

I thought I'd cracked it with this as the blocks are grouped and the caravan has the dynamic properties - BUT - as soon as I try to move the group AutoCAD crashes.

 

So, in method 1 I think I'm missing something when I loop through the ObjectIdCollection adding them to the transaction - maybe something to do with the DynamicBlockTableRecord?

 

Method 2 is much closer but the group appears to be corrupt.

 

I'm not doing anything fancy in the grouping code (it works for the ExplodeToOwnerSpace fine) but here's the code for that anyway...

 

 

public static bool CreateGroupFromIds(ObjectIdCollection objCol, string blockName, ref Transaction trans)
{
	try {
		Database db = HostApplicationServices.WorkingDatabase;
		string groupName = GroupHelper.GetNextGroupNameForBlock(blockName); // This just gets the next group name for the block 
		Group grp = new Group(groupName, true);
		DBDictionary gd = trans.GetObject(db.GroupDictionaryId, OpenMode.ForWrite);
		gd.SetAt(groupName, grp);
		trans.AddNewlyCreatedDBObject(grp, true);
		grp.InsertAt(0, objCol);
		return true;
	} catch (Exception ex) {
		throw ex;
	}
}

I also tried doing the grouping inside a different transaction after the ExplodeToOwnerSpace function, just to make sure that the objects were actually properly in the database but no joy.

 

Thanks in advance for any assistance.

 

P

 

0 Likes
Accepted solutions (1)
2,326 Views
9 Replies
Replies (9)
Message 2 of 10

Paulio
Advocate
Advocate

Attached is a drawing containing a sample block which contains a Car block and a dynamic Caravan block.

 

I don't actually want to insert car and caravan blocks - just using that to illustrate the point.

 

I know it's a bit of a long post but any help would be very gratefully received.

 

Thanks

 

P

0 Likes
Message 3 of 10

BKSpurgeon
Collaborator
Collaborator

Hi Paulio i'm still learning and there's a lot i don't understand, so I cannot tackle your problem head on - but if you hear me out, might I suggest a novel solution:

 

(i) you have the insertion point of the car.

(ii) use the insertioin point of the car to insert the caravan as well in a nearby location. offsert the caravan insertion point by a small amount.

(iii) then group them together.

 

in other words, use one insertion point to insert both the car and caravan - not as one individual block - but as two separate blocks. you can group these blocks together as well. 

 

That way you solve your problem of having them inserted together, without the difficulty of exploding them and trying to retain the dynamic block, while also grouping them as well.

 

Hope this helps?

 

 

0 Likes
Message 4 of 10

Paulio
Advocate
Advocate

My problem is that I'm not actually inserting just a car and a caravan block. The real world scenario is a lot more complex where my "combined" block may consist of between 5 and 15 separate blocks that are laid out in a specific configuration at specific spacings etc.

I could try to fully explain the reason I'm trying to do what I'm doing but you'd probably be asleep before I got halfway through!

 

So in short, what you've suggested won't work for me but I appreciate you taking the time to suggest something.

 

P

0 Likes
Message 5 of 10

augusto.goncalves
Alumni
Alumni
Accepted solution
At the ObjectAppended, can you check the types and ensure the collection contains only BlockReference?

From your description and by looking at the drawings, it may be missing the fact that DynamicBlocks do create some anonymous blocks (BlockTableRecords) and, maybe, your group is collecting them.

A simple check should work

public static void ObjectAppended(Object sender, ObjectEventArgs e)
{
if (!(e is BlockReference)) return;
idsToGroup.Add(e.DBObject.ObjectId);
}
Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
0 Likes
Message 6 of 10

Paulio
Advocate
Advocate

Hi Augusto,

 

That has indeed solved the problem, thank you.

 

Just for completeness though and for the purposes of future proofing, could you tell me what kinds of objects I should be filtering out rather than specifically allowing through? What I mean is that if I ever have something other than a block reference inside my "blockToExplode" (e.g. linework or text) then those will also get filtered out (and not grouped) using your method.

 

Is it possible to switch your solution around and say something like:

 

if (!(e.dbObject is BlockTableRecord???))

{

  idsToGroup.Add(e.DBObject.ObjectId);

}

 

Thanks 

0 Likes
Message 7 of 10

augusto.goncalves
Alumni
Alumni
The Database.ObjectAppended event will trigger for everything on the database, from lines, to block markers (begin/end), linetypes, etc... As in your case you want to create a block, you must filter for entities that fit this condition, in your case, ONLY BlockReference

The BlockTableRecord is actually the block definition and contains the entities. The DynamicBlock will create anonymous blocks (BlockTableRecord), but these are not used on the model space (only the BlockReference is used on model space)

So it's best to filter by what you want (and ignore the rest)
Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
0 Likes
Message 8 of 10

Paulio
Advocate
Advocate

Ok, that makes sense. I'll just need to add those other object types to my "allowed" list if it becomes necessary then.

 

Thanks for your help.

0 Likes
Message 9 of 10

2020mme013
Enthusiast
Enthusiast

Hi Augusto,

I have created template of drawing using line, circle, text etc lot of objects are there now I want all that to in one block so that I can able to scale that block. Please help me in this create any two objects and add them in block by using that object name. I am confused with how to set the block size so that all objects will include in that.

0 Likes
Message 10 of 10

paul_mace
Contributor
Contributor

That seems like a different question to this one so you're probably best posting a new topic for the best chance of getting a reply.
Not sure if this will help but have a look at this post:
https://www.keanw.com/2010/01/creating-an-autocad-block-using-net.html 

0 Likes