Removing with ifcopenshell.util.element.remove_deep2

edited May 17 in General

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 =

for product_definition_shape in ifc_file.by_type("IfcProductDefinitionShape"):
    if len(product_definition_shape.ShapeOfProduct) == 0:
        ifcopenshell.util.element.remove_deep2(ifc_file, product_definition_shape)



  • 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 ='/path/file.ifc')
    products = ifc.by_type('IfcProductDefinitionShape')
    orphan_products = []
    for p in products:
        if ifc.get_total_inverses(p) == 0:
    representations = []
    for op in orphan_products:
        for rep in op.Representations:
    for rep in representations:"geometry.remove_representation", ifc, representation=rep)

    This one looks for orphaned "IfcShapeRepresentation" and deletes them:

    import ifcopenshell
    import ifcopenshell.api
    ifc ='/path/file.ifc')
    representations = ifc.by_type('IfcShapeRepresentation')
    orphan_representations = []
    for rep in representations:
        if ifc.get_total_inverses(rep) == 0:
    for rep in orphan_representations:"geometry.remove_representation", ifc, representation=rep)
  • 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 =
    element_id = 267212
    element = ifc_file.by_id(element_id)"root.remove_product", ifc_file, product=element)
  • Thank you for the snippets ! How would one batch remove IfcElementTypes with 0 associated instances ?

  • @Gorgious something like:

            element_types = (
                + 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):
          "root.remove_product", ifc_file, product=element_type)
  • @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.

  • edited June 1

    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/ 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"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 :)

  • edited August 17

    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 :

Sign In or Register to comment.