.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to keep track of block components after the block is exploded?

4 REPLIES 4
Reply
Message 1 of 5
jz5902
460 Views, 4 Replies

How to keep track of block components after the block is exploded?

Is there any way to keep track of the contents of a block after the block is exploded, so they can be manipulated later?  I tried getting a list of ObjectIds from the BlockTableRecord, but any attempt to change the objects associated with them fails.

 

The method below is called while handling an ObjectModified event.  It uses the block reference to open the block table record and stores all the object ids in a list called blockContents.

 

private static void getBlockContents(BlockReference reference, Transaction transaction)
{
    BlockTableRecord _record = (BlockTableRecord)transaction.GetObject(reference.BlockTableRecord, OpenMode.ForRead);
    foreach (ObjectId _id in _record)
    {
        blockContents.Add(_id);
    }
}

However, if I try to use these ids later, they don't do anything.  For example, in a different method I try to do this:

DBObject _temp;
foreach (ObjectId _id in blockContents)
{
    _temp = _transaction.GetObject(_id, OpenMode.ForWrite);
    _temp.Erase();
}

This doesn't throw any errors.  It sets the object's IsErased property to true, but it doesn't actually erase anything.  All the objects are still sitting in the drawing.

 

So what's wrong here?  Am I on the completely wrong path?  I'll be the first to admit that my understanding of BlockReferences/BlockTableRecords/etc. is shaky.

 

4 REPLIES 4
Message 2 of 5
norman.yuan
in reply to: jz5902

It is not very clear what you want to do. As programmer, term "block" is quite ambiguous: is it BlockReference, or BlockTableRecord?

 

Is your Database.ObjectModified intended to monitor/handle the result of "EXPLODE" command? or the exploding is done by your code? The two approaches of exploding (built-in command and API's Explode() method) lead to quite differnt result:

 

Built-in Command: it first generate individual entities based on the block definition and BlockRefernce's Transform; and add these entities into database, and finally delete the block reference. during this process, many Database events could be raised (ObjectAppended, ObjectModified and ObjectErased...)

 

API's Explode() method: it only generate a DBCollection of entities, cloned from the block definition and the block refernce's transform. It is up to the programmer to decide if this new entities to be added to the database, or to be disposed, and the block reference remains unchanged and the programmer can choose erase it or not.

 

So, you'd need better explain what you really want to do.

 

Also, from your code, you actually is trying to erase everything in the block definition (BlockTableRecord), which has nothign to do with the effect of exploding. The end result, if your code succeed, it you are left a blank block defintion. I am not sure what you want to achieve here.

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 5
jz5902
in reply to: norman.yuan

As I said above, I don't really understand blocks very well.  However, you've helped me more than you realize.

 

I'm trying to handle the results of the built-in EXPLODE command.  I want to create a list of the ObjectIDs that are left over after the block explodes.  From what you said, it sounds like I was on the completely wrong track.  Should I watch the ObjectAppended event for any new entities being added to the database during the command?  Would that get me the list of the new entities?

 

This at least gives me some ideas about how to proceed, so thanks.

Message 4 of 5
arcticad
in reply to: jz5902

You have to add an event to track the explode

 

        static ObjectIdCollection ids = new ObjectIdCollection();

        internal List<ObjectId> ExplodeToOwnerSpace(ObjectId blkRecId, Transaction acTrans, Database acDb)
        {
            ids.Clear();
            BlockReference acBlkRef = acTrans.GetObject(blkRecId, OpenMode.ForWrite) as BlockReference;

            //add event
            ids.Clear();
            acDb.ObjectAppended += new ObjectEventHandler(db_ObjectAppended);
            acBlkRef.ExplodeToOwnerSpace();
            //remove event
            acDb.ObjectAppended -= new ObjectEventHandler(db_ObjectAppended);

            List<ObjectId> rtnValue = new List<ObjectId>();
            foreach (ObjectId id in ids)
            {
                Entity acEnt = acTrans.GetObject(id, OpenMode.ForWrite) as Entity;
                if (acEnt is BlockReference)
                    rtnValue.Add(id);
            }

            return rtnValue;
        }

        static void db_ObjectAppended(object sender, ObjectEventArgs e)
        {
            //add the object id
            ids.Add(e.DBObject.ObjectId);
        }

---------------------------



(defun botsbuildbots() (botsbuildbots))
Message 5 of 5
norman.yuan
in reply to: arcticad

articad, the OP does not watch API's Explode()/ExplodeToOwnerSpace(). Rather the OP want to wach the biult-in command, thus, the situation is a bit complicated.

 

To OP:

 

You probably need to handle Document.CommandWillStart/CommandEnded events.

 

In CommandWillStart, test if the command name is "EXPLODE", if yes, add event handler to Database.ObjectAppended, so that you have save the newly created entities' Id in a collection.

 

In CommandEnded handler, if the command name is "EXPLODE", you remove Database.ObjectAppended handler, then examine the saved entity id collection, and do something with these entities as you needed.

Norman Yuan

Drive CAD With Code

EESignature

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost