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:
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?
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)
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:
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.
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.
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!
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:
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
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.
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
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])
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.
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.