T
by theoryshaw on 17 May 2023, edited 17 Aug 2023
#
I'm trying to remove..
#259822=IFCPRODUCTDEFINITIONSHAPE($,$,(#259820,#259821));
and everything it's attached to,
from the attached file, since it doesn't seem to be attached to an IfcElement or type.
I'm using the following, but it doesn't remove the associated IFCINDEXEDPOLYGONALFACE and IFCPOLYGONALFACESET.
Any clues on how to remove even deeper? :)
import bpy
import ifcopenshell
import blenderbim.bim.import_ifc
from blenderbim.bim.ifc import IfcStore
import ifcopenshell.util.element
ifc_file = ifcopenshell.open(IfcStore.path)
for product_definition_shape in ifc_file.by_type("IfcProductDefinitionShape"):
if len(product_definition_shape.ShapeOfProduct) == 0:
print(product_definition_shape)
ifcopenshell.util.element.remove_deep2(ifc_file, product_definition_shape)
ifc_file.write("C:/Users/Owner/Desktop/testy/testymod.ifc")
B
by bruno_perdigao on 17 May 2023
#
+4 votes
I wrote two scripts that worked for this file, maybe they are useful for others. Any comments on how to improve them are welcome.
This script looks for orphaned "IfcProductDefinitionShape", deletes them and its representations:
import ifcopenshell
import ifcopenshell.api
ifc = ifcopenshell.open('/path/file.ifc')
products = ifc.by_type('IfcProductDefinitionShape')
orphan_products = []
for p in products:
if ifc.get_total_inverses(p) == 0:
orphan_products.append(p)
representations = []
for op in orphan_products:
for rep in op.Representations:
representations.append(rep)
ifc.remove(op)
for rep in representations:
ifcopenshell.api.run("geometry.remove_representation", ifc, representation=rep)
ifc.write('/path/file.ifc')
This one looks for orphaned "IfcShapeRepresentation" and deletes them:
import ifcopenshell
import ifcopenshell.api
ifc = ifcopenshell.open('/path/file.ifc')
representations = ifc.by_type('IfcShapeRepresentation')
orphan_representations = []
for rep in representations:
if ifc.get_total_inverses(rep) == 0:
orphan_representations.append(rep)
for rep in orphan_representations:
ifcopenshell.api.run("geometry.remove_representation", ifc, representation=rep)
ifc.write('/path/file.ifc')
T
by theoryshaw on 23 May 2023
#
Used the following as well.
Will delete an entity's graph based on element_id
import ifcopenshell
import ifcopenshell.api
ifc_file_path = 'D:/Dropbox/GitLab/Highland_Haven/Models_and_CAD/test.ifc'
ifc_file = ifcopenshell.open(ifc_file_path)
element_id = 267212
element = ifc_file.by_id(element_id)
ifcopenshell.api.run("root.remove_product", ifc_file, product=element)
ifc_file.write('D:/Dropbox/GitLab/Highland_Haven/Models_and_CAD/test.ifc')
G
by Gorgious on 23 May 2023
#
Thank you for the snippets ! How would one batch remove IfcElementTypes with 0 associated instances ?
T
by theoryshaw on 23 May 2023
#
Good question. Related: https://community.osarch.org/discussion/comment/15386/#Comment_15386
M
by Moult on 31 May 2023
#
+3 votes
@Gorgious something like:
element_types = (
self.file.by_type("IfcElementType")
+ self.file.by_type("IfcDoorStyle")
+ self.file.by_type("IfcWindowStyle")
)
for element_type in element_types:
if not ifcopenshell.util.element.get_types(element_type):
ifcopenshell.api.run("root.remove_product", ifc_file, product=element_type)
G
by Gorgious on 31 May 2023
#
@Moult Thank you ! How would I remove profiles which are not used in the file ? I've had a bug when creating a profile and one of my profiles got duplicated many times in the profile editor in the scene properties.

AFAIK it's not possible with this interface to know which profiles are used by a IfcMaterialProfileSetUsage, and profile names are not uniquely defined so I don't know which profile I want to keep and which ones I want to remove.

M
by Moult on 1 Jun 2023, edited 1 Jun 2023
#
+3 votes
Ah you're right, we don't expose the number of users of the profile in the UI. It would be nice to do so, in module/profile/operator.py
you can do tool.Ifc.get().get_total_inverses(profile)
to get the number of users (I think that should be OK for now), and anything with a 0 you can safely delete (either run the operator, or if you want more speed run ifcopenshell.api.run("profile.remove_profile", tool.Ifc.get(), profile=tool.Ifc.get().by_id(self.profile))
directly to avoid UI refreshes).
PR very welcome to add a button to purge unused :)
G
by Gorgious on 17 Aug 2023, edited 17 Aug 2023
#
https://github.com/IfcOpenShell/IfcOpenShell/commit/90e640011524a51fc59c22cf96a2a1435518a0a2
Part one done


Not sold on the display but it can always be re-arranged. A nice QOL would be to be able to select all objects that use the profile in one of their material layer sets. It might be a bit harder than a simple "select all inverse relationships" since as I understand elements are not directly tied to the profiles, but rather indirectly tied via the material layer set.
Now on to the purge operator.
edit : https://github.com/IfcOpenShell/IfcOpenShell/issues/3225#issuecomment-1682389888