Some time ago I posted about how to use Entity.Explode() to do something similar to AutoCAD’s EXPLODE command. At the time it was mentioned in the comments that BlockReference.ExplodeToOwnerSpace() had some relative benefits, but it’s taken me some time to code up a simple sample to show how you might use it (Patrick’s recent comment reminded me I ought to, though).
Anyway, to end the week I thought I’d throw together a quick sample. BlockReference.ExplodeToOwnerSpace() doesn’t return a list of created objects, so I opted to capture this using a Database.ObjectAppended event handler and then recursively call our custom ExplodeBlock() function for any nested blocks that get created. We also then erase the originating entity (or entities, if called recursively), just as the EXPLODE command might.
Here’s the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace Explosions
{
public class Commands
{
[CommandMethod("EB")]
public void ExplodeBock()
{
var doc = Application.DocumentManager.MdiActiveDocument;
if (doc == null)
return;
var ed = doc.Editor;
var db = doc.Database;
// Ask the user to select the block
var peo = new PromptEntityOptions("\nSelect block to explode");
peo.SetRejectMessage("Must be a block.");
peo.AddAllowedClass(typeof(BlockReference), false);
var per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
using (var tr = db.TransactionManager.StartTransaction())
{
// Call our explode function recursively, starting
// with the top-level block reference
// (you can pass false as a 4th parameter if you
// don't want originating entities erased)
ExplodeBlock(tr, db, per.ObjectId);
tr.Commit();
}
}
private void ExplodeBlock(
Transaction tr, Database db, ObjectId id, bool erase = true
)
{
// Open out block reference - only needs to be readable
// for the explode operation, as it's non-destructive
var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
// We'll collect the BlockReferences created in a collection
var toExplode = new ObjectIdCollection();
// Define our handler to capture the nested block references
ObjectEventHandler handler =
(s, e) =>
{
if (e.DBObject is BlockReference)
{
toExplode.Add(e.DBObject.ObjectId);
}
};
// Add our handler around the explode call, removing it
// directly afterwards
db.ObjectAppended += handler;
br.ExplodeToOwnerSpace();
db.ObjectAppended -= handler;
// Go through the results and recurse, exploding the
// contents
foreach (ObjectId bid in toExplode)
{
ExplodeBlock(tr, db, bid, erase);
}
// We might also just let it drop out of scope
toExplode.Clear();
// To replicate the explode command, we're delete the
// original entity
if (erase)
{
br.UpgradeOpen();
br.Erase();
br.DowngradeOpen();
}
}
}
}
That’s it for this week. Monday is a holiday in Neuchatel, so I’ll be back online on Tuesday. And then on Wednesday I’m heading to TEDxCERN – which promises to be really cool. Can’t wait!