Autocad .net API combine blocks into one

113 views Asked by At

I currently have imported a dxf file into Autocad and I’m wanting to use the .net API using C# to combine the existing blocks (in the original dxf) into one block with the original blocks and entities all nested within this “outer block”.

I currently have the below code which puts all of the entities into one outer block but the original blocks and entity colours no longer exist.

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace CombineBlockTableRecords
{
    public class Commands
    {
        [CommandMethod("CombineBlocks")]
        public void CombineBlocks()
        {
            // Get the current document and database
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            // Start a transaction
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                // Open the Block table for read
                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

                // Create a new block definition
                BlockTableRecord newBlockDef = new BlockTableRecord();
                newBlockDef.Name = "CombinedBlock";

                // Add the new block definition to the block table
                bt.UpgradeOpen();
                ObjectId newBlockDefId = bt.Add(newBlockDef);
                tr.AddNewlyCreatedDBObject(newBlockDef, true);

                // Iterate through all block table records in the drawing
                foreach (ObjectId btrId in bt)
                {
                    if (btrId != newBlockDefId) // Exclude the new block definition itself
                    {
                        // Open each BlockTableRecord for read
                        BlockTableRecord btr = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;

                        // Iterate through each entity in the BlockTableRecord and add a copy to the new block definition
                        foreach (ObjectId entityId in btr)
                        {
                            Entity ent = tr.GetObject(entityId, OpenMode.ForRead) as Entity;
                            Entity entCopy = ent.Clone() as Entity;
                            newBlockDef.AppendEntity(entCopy);
                            tr.AddNewlyCreatedDBObject(entCopy, true);
                        }
                    }
                }

                // Commit the transaction
                tr.Commit();
            }
        }
    }
}

Any help would be greatly appreciated!

1

There are 1 answers

0
hkm On

In the code above it appears you're only copying the entities from the existing blocks into the new blocks. If you want to go a level deeper and preserve the original blocks, you would have to handle BlockReference entities in a special way.

Also, when cloning the entities, the colors are not being transferred from the original entities to its clones. To do this you will need to set the Color property of your cloned entity to match the original. Here's how you can handle blocks

// Iterate through each entity in the BlockTableRecord

foreach (ObjectId entityId in btr)
 {
// Open the entity for read
Entity ent = tr.GetObject(entityId, OpenMode.ForRead) as Entity;

// If the entity is a block, add a reference to the block to the new block definition
if (ent is BlockReference blockRef)
{
    // New block reference with the same block table record
    BlockReference newBlockRef = new BlockReference(blockRef.Position, blockRef.BlockTableRecord);

    // Copy properties
    newBlockRef.Color = blockRef.Color;

    // Add block reference to the new block definition
    newBlockDef.AppendEntity(newBlockRef);
    tr.AddNewlyCreatedDBObject(newBlockRef, true);
}
else // Clone the entity if it's not a block
{
    Entity entCopy = ent.Clone() as Entity;

    // Copy properties
    entCopy.Color = ent.Color;

    // Append the copy to the new block definition
    newBlockDef.AppendEntity(entCopy);
    tr.AddNewlyCreatedDBObject(entCopy, true);
   

 }
   }