Updating/inserting new parameters inside IFC files using belnderBIM
I have started using BlenderBIM Bonsai since a week ago. I wanted to update IFC files data parameters. I have succeeded in updating the parameters inside the IFC file and then save the IFC file with the new parameters using python scripts. That process will take between 10 seconds and a couple of minutes based on the file size. I found that the more objects are available, the longer it will take to complete the task ( the time of competition of each object will elongate with the increase in object quantity).
Ex :
1. File with 100 objects, then each object to be updated will require something around 0.02 seconds.
2: File with 2000 objects, then each object to be updated will require something around 1.3 seconds.
However, when I tried to do so with files that contain huge number of objects ( more than 10 k) , each object will require more than 5 seconds. For a file the contains 23 k objects each object will require around 14.6 seconds, so that to update the file I do need 4.2 days :).
If someone can support/advise me about the optimum way to update the data using BlenderBIM/Bonsai regardless of the file size or number of objects.
Below is the code I am using:
Get all the from the SQL Server
query = ("""SELECT '0, ' + LEFT([filename],23) + '.dgn, Design Model:' + cast(cast([Id] as bigint) as varchar(100)) as FileID,
[Trade],[Sub Trade],[Construction Zone Number],[Room Number],[Level 1],[Level 2],[Level 3],[Level 4],[Level 6],[BIM Code],
[BIM Description],[CSI Code],[Unit],cast(cast([Quantity] as bigint) as varchar(100)) as Quantity,[Electrical Zone],[HVAC Zone],[Fire Fighting Zone],[Fire Evacuation Zone],[Nominal Size],
[Asset Code],[Function],[Circuit Number],[Equipment Mechanical Interface],[Equipment Electrical Interface],[Equipment Parent],[Fire Resistance Rating],
[Control Circuit Number],[Asset Code 2],[Asset Code 3] FROM [Tandem].[dbo].[myTable] where [filename] like '%"""+ Modlenamex + "%'")
df = pd.read_sql(query, cnxn)
if df.empty:
print('The selected file has no records in the MTO database table or you have not selected all items!')
bpy.ops.bim.save_project(filepath="C:\Users\far\Desktop\BIM\Blender IFC\" + Modlenamex + ".ifc", should_save_as=True, save_as_invoked=True)
print ('Finiiiiiiiiished Running the Code')
else:
for obj in selection:
obj.select_set(True)
# some exporters only use the active object
view_layer.objects.active = obj
name = bpy.path.clean_name(obj.name)
bpy.ops.bim.enable_editing_attributes(obj=obj.name)
ModelObjectId = bpy.data.objects[obj.name].BIMAttributeProperties.attributes[2].string_value
myidDF = df.query('FileID == @ModelObjectId')
if myidDF.empty:
print('The selected object ', ModelObjectId,' has no records in the MTO Database File!')
else:
##### Add the header Paramter #####
bpy.ops.bim.add_pset(obj=obj.name, obj_type="Object")
bpy.data.objects[obj.name].PsetProperties.active_pset_name = "Graphical_Parameter"
bpy.ops.bim.disable_pset_editing(obj=obj.name, obj_type="Object")
# print (bpy.data.objects[obj.name].PsetProperties.active_pset_name)
# print(bpy.data.objects[obj.name].PsetProperties.active_pset_id)
bpy.ops.bim.enable_pset_editing(pset_id=0, pset_name="Graphical_Parameter", pset_type="PSET", obj=obj.name, obj_type="Object")
# Loop to add the Graphical Data related to each object ID
for column in myidDF:
# print (column.count)
bpy.data.objects[obj.name].PsetProperties.prop_name = column
if myidDF.iloc[0][column] is None:
bpy.data.objects[obj.name].PsetProperties.prop_value = "-"
bpy.ops.bim.add_proposed_prop(obj=obj.name, obj_type="Object", prop_name=column, prop_value="-")
else:
bpy.data.objects[obj.name].PsetProperties.prop_value = myidDF.iloc[0][column]
bpy.ops.bim.add_proposed_prop(obj=obj.name, obj_type="Object", prop_name=column, prop_value=myidDF.iloc[0][column])
#Save the add grpahical data to the object
bpy.ops.bim.edit_pset(obj=obj.name, obj_type="Object", pset_id=0)
obj.select_set(False)
#bpy.ops.bim.save_project(filepath="C:\Users\far\Desktop\BIM\Blender IFC\", Modlenamex,".ifc", should_save_as=True, save_as_invoked=True)
bpy.ops.bim.save_project(filepath="C:\Users\far\Desktop\BIM\Blender IFC\" + Modlenamex + ".ifc",should_save_as=True, save_as_invoked=True)
print ('This is the total selected object: ', len(bpy.context.selected_objects))
print ('Finiiiiiiiiished Running the Code')
Comments
Somthing I encountered as well and have it on my ToDo for years.
Double the elements in a file to add new pset.properties too results in much much more than double the time it takes. For small modells (less than 1k elements) it does not matter, but as soon as there are more than 5k elements we are no longer talking about minutes but hours ...
ATM I am still happy because the biggest model I need to add pset.attributes too is 3.5k elements. It takes around 45 minutes to add all the pset.properties.
I do not use any sql, just pure python and ifcopenshell. Parse the model, add one pset.attribute with a value to any IfcBuildingElement, write the model to a new file name.
Hi @FirasAr
if you like you can use the code view in Markdown, just start the first line with ```(backtick) python and close it in the same way, like this:
cheers
I haven't looked at your code too hard but likely the issue is that you're trying to work on the IFC using the bpy.ops methods.
If you want to do things quickly to IFC with code, you're much better off using the IfcOpenShell library directly:
https://docs.ifcopenshell.org/ifcopenshell-python.html
I also started with bpy.ops methods as it's quite intuitive when you first begin, but in the long run it's not feasible for a lot of stuff.
Indeed, for this type of thing, just use IfcOpenShell directly - it'll be much, much faster. Here's a code example on how to add/edit a pset. https://docs.ifcopenshell.org/autoapi/ifcopenshell/api/pset/index.html#ifcopenshell.api.pset.edit_pset
Well, as an IfcOpenShell newbie, I was querying the property names. For some models properties are applied per element type and the query is quite fast (as I know it now), but for some models properties are applied per element, and, oh boy, it almost takes ages to process the file.
So, if it is possible to apply the type value - do it. And yes, use IfcOpenShell directly, it saves a lot of machine cycles.
Thank you so much; that was so helpful. Now with the new script the models that required hours can be updated in less than 15 seconds :)
Thank you for your comment, I would advise you to refer to the below anwers