Explode Node removes properties from objects within Block References -> how to code explode yourself (properly)?

Hi!

I want to place block references that have objects inside them that have properties. Whenever I have placed the block references I want to explode them, but whenever I do that, the objects inside the block references lose their properties. Which is weird since the explode function in Civil/AutoCAD explodes the block and keeps those properties.

Now I am thinking of recoding the explode function using design script, but I am a beginner in design scripting and this seems like an advanced task.

I have found one similar post in this forum by @mjaffee72 where he explodes polylines:

https://forum.dynamobim.com/t/civil-3d-exploding-polyline-object/59166

Do you have an idea how I could start with this project?

For a start I don’t know which assemblies and namespaces I require.

Amigo @julian.dyn I’m not sure I understand what you are trying to do, personally I always try not to exploit the blocks precisely because when they are exploited they lose their individual data and are not so useful anymore, can you send me a screen shot of what you need to do to have a more clear picture?

Hi @gilberto.arechigaiba ! Thank you for your reply.

I will try to make it more clear with a simple example:

First I create a block, in which I model a solid and add a property set to them. Then I fill out the property. (In practice I would model multiple objects and add different properties on the objects inside the block, but for the example I want to keep it simple)

Later I use dynamo to place this block as a block reference, which poses no problem.

In the end I want to explode the block reference and extract the object within. If I used the basic AutoCAD function XPLODE for this, then there is no problem with the properties:

However, if I use dynamo to explode the block reference, the solid loses its property:

image

In practice I would place multiple block references and I want to explode them automatically via dynamo and not manually via the AutoCAD function explode.

I hope this makes the issue more clear.

Now I want to find out if there is a way to maybe access the original AutoCAD explode function inside a python design script or maybe re-code the explode function.

Have you thought about extracting the data from the block prior to exploding them, then re-applying the data on the exploded elements.

2 Likes

@Brendan_Cassidy

Yes!

But the issue is, if there are multiple objects inside the block reference, after exploding I won’t know, which object had which property. Also I don’t think there is a node that can extract properties.

However I will check this out inside design script. Maybe I can figure something out.

I found out that there is a way to extract properties from objects inside a block using the C3D Toolkit!

To know which object has which property I simply add the property ‘object ID’.

Amigo @julian.dyn I still don’t understand why you don’t want to continue working with blocks, it is much more practical, I really feel that you are complicating unnecessarily, but well there are several ways to make Querys of the properties using Packages Civil3DToolKit and the other is with AECTech if you like programming AECTech has curious things, I hope it helps you!

1 Like

Hi
Attached example drawing for better

Extracting the properties from the block before exploding is no issue. The re-applying part is a problem since I do not know which object gets which properties.

Earlier I had the idea of referencing the Object ID, but I didn’t realize that the Object ID changes after exploding and I again have no reference on which object I need to apply the data.

Hola!
Thank you for bringing my attention to these packages!

There are 2 reasons why I cannot simply use blocks:

  • my deliverable is a open BIM model (e.g. IFC model) containing solids and not block references.
    → an argument could be to just apply the properties after exploding the block references, but there is reason number 2.
  • there are two kinds of properties that I apply:
    1. Properties inside the block (manually) applied to the individual geometry. Those are the properties that get lost when using the explode node in dynamo.
    In practice these properties are simply identifiers for the objects inside the block reference. For example I would create a block and model a signpost with a foundation. For the foundation I would use the identifier “foundation”, for the signpost “signpost”.
    2. Properties outside (automatically) applied after the block reference has been placed using dynamo. Those properties are dependent on where I placed the block.
    In practice I would for example place the signpost multiple times along an alignment at specific stations. Exactly this station would become the value of one of the placement dependent properties.

The workflow I planned to execute this was to explode the block references and then apply the “placement dependent properties” on the exploded solids. But then the “identifying properties” get lost in the process.

I didn’t want to mention all this since it is pretty complicated but I guess it’s necessary to understand the issue at hand.

Hoo, i see very particular workflow, may be you can explore other options, I’ll give you some ideas, maybe some of them will work for you:

  1. The package Camber has several nodes of type external documents, so you can do the query in a document where the blocks are and insert solids with their information in another, although honestly I’m not sure if in C3D there is an easy way to export to IFC formats especially because what you are trying to do is of the bim methodology maybe someone else in the forum knows, besides maybe that’s the right question to ask.
    Camber Feedback Thread
  2. The package Civil Conection works for revit and allows you to connect Civil and Autocad files and do Querys in real time let’s say directly in Dynamo for Revit (it is difficult to install this package and you have to use the same year version of Revit and C3D) and maybe in revit there is an efficient way to export to IFC files, revit is a product of methodology BIM.
    GitHub - Autodesk/civilconnection: CivilConnection enables the exchange of information between Civil 3D, Dynamo and Revit.
  3. The package Genius Locky has some nodes that allow to read the information inside .dwg files inserted in the revit file although frankly I have not explored much this last one.
    Buena suerte Amigo @julian.dyn

You can send the regular explode command to the command line if that helps: How to use civil 3D commands in a Python Script? - #3 by mzjensen

Here is an example: Issue with SendCommand and MapImport - #5 by WrightEngineering

1 Like

Hi @julian.dyn,

I tested this and got the same behavior as you, so unfortunately I think it’s a shortcoming of the Object.Explode node.

Yes, although I would maybe state this a little differently. It’s not that the Object IDs of the objects within the block definition are changing after you explode, it’s that they are entirely different objects. When the block reference is exploded, the original elements within the block definition still need to be there, so what is really happening is that entirely new objects are being created. In other words, you haven’t changed the block definition by exploding one of its block references, you’ve basically just duplicated it’s contents into model space.

Here’s some Python code you can use as a workaround to the Object.Explode node. This will just select the objects and run the normal EXPLODE command at the command line.

import clr

from Autodesk.AutoCAD.ApplicationServices import *

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

def explode(objs):
    global adoc
    global editor
    oids = []
    if objs is None:
        return False
    for obj in objs:
        oids.append(obj.InternalObjectId)
    editor.SetImpliedSelection(oids)
    adoc.SendStringToExecute("EXPLODE ", True, False, False)
    return True

OUT = explode(IN[0])
2 Likes

Hi! Wow. Thank you so much!! :exploding_head:

This is almost the solution I need. For the output, I need the code to work like the Object.Explode node, containing a list of lists, in which every sub-list contains the newly created objects of the former block references.

That is going to be a bit more work. You’ll have to dive deep into the AutoCAD and AutoCAD Architecture APIs in order to explode the objects, obtain pointers to the new objects, and map the property sets over to the new objects. Unfortunately I don’t have time to help further.

2 Likes

I thought I figured out a workaround, but there is an issue.

My idea for the workaround was that I:

  • iterate over the block references
  • add the location-dependent properties (for example the alignment station) to the objects inside the block
  • explode the block reference → the resulting objects now have the corresponding alignment station
  • for the next block reference I simply repeat this process and update the properties

… BUT the SendStringToExecute function for the EXPLODE command can not be iterated over. It can only be executed once. So it will only explode the Block Reference of the last iteration.

Code looks like this:

def add_properties(ref, PSet, prop, prop_val):
    bl_objs = ref.Block.Objects  # objects inside the block
    
    if len(bl_objs) > 1:
        for obj in bl_objs:
            obj.AddPropertySet(PSet)
            obj.UpdateProperty(PSet, prop, str(prop_val))
            
    else:  # only 1 object in block
        bl_objs.AddPropertySet(PSet)
        bl_objs.UpdateProperty(PSet, prop, str(prop_val))


stats = IN[1]

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

def explode(refs):
    global adoc
    global editor
    oids = []
    
    if refs is None or len(refs) == 0:
        return False
        
    if len(refs) == 1:
        PSet = stats[0]
        prop = stats[1]
        prop_val = stats[2][0]
        add_properties(refs[0], PSet, prop, prop_val)
        
        oid = []
        oid.append(refs[0].InternalObjectId)
        editor.SetImpliedSelection(oid)
        adoc.SendStringToExecute("EXPLODE ", True, False, False)
        
    else:  # len() > 1
        for i in range(len(refs)):
            PSet = stats[0]
            prop = stats[1]
            prop_val = stats[2][i]
            add_properties(refs[i], PSet, prop, prop_val)
            
            oid = []
            oid.append(refs[i].InternalObjectId)
            editor.SetImpliedSelection(oid)
            adoc.SendStringToExecute("EXPLODE ", True, False, False)
    
    return True

OUT = explode(IN[0])

I haven’t examined your code closely, but I can say this: sending commands to the command line as part of a larger piece of logic is generally a bad practice. Once a command is sent, the rest of the execution will operate asynchronously from the rest of your application, so you open up the door for unexpected results from race conditions. In other words, you have no way of ensuring that the EXPLODE command actually completes before moving to the next operation unless you write an event handler. It would be much more robust to call the Entity.Explode() method from the API so that you ensure that everything stays in sync.

This isn’t to say that sending commands is a complete no-no, it’s just something that should be used with care and ideally at the very end of a sequence versus in the middle.

1 Like