mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Print unused elements stats / purge unused elements
Added to Purge Data section in Quality Control some tools - https://i.imgur.com/Nz3YoiH.png 1) Print unused elements - useful to investigate how much unused data you have in IFC file. https://i.imgur.com/9Fkn0JD.png 2) purge unused elements by ifc class, it's doing it in pretty naive way and can be dangerous, so maybe it should be moved to debug section.
This commit is contained in:
@@ -38,6 +38,8 @@ classes = (
|
||||
operator.SelectHighPolygonMeshes,
|
||||
operator.SelectHighestPolygonMeshes,
|
||||
operator.ValidateIfcFile,
|
||||
operator.PrintUnusedElementStats,
|
||||
operator.PurgeUnusedElementsByClass,
|
||||
prop.BIMDebugProperties,
|
||||
ui.BIM_PT_debug,
|
||||
)
|
||||
|
||||
@@ -454,3 +454,44 @@ class OverrideDisplayType(bpy.types.Operator):
|
||||
for obj in context.selected_objects:
|
||||
obj.display_type = self.display
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class PrintUnusedElementStats(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.print_unused_elements_stats"
|
||||
bl_label = "Purge Unused Elements Stats"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = (
|
||||
"Print all unused elements in current IFC project in system console, not limited to the selected class"
|
||||
)
|
||||
|
||||
ignore_contexts: bpy.props.BoolProperty(name="Ignore Contexts", default=True)
|
||||
ignore_relationships: bpy.props.BoolProperty(name="Ignore Relationships", default=True)
|
||||
ignore_types: bpy.props.BoolProperty(name="Ignore Types", default=True)
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMDebugProperties
|
||||
# ignore some classes that could have zero 0 inverse references by their nature
|
||||
ignore_classes = []
|
||||
if self.ignore_contexts:
|
||||
ignore_classes += ["IfcRepresentationContext"]
|
||||
if self.ignore_relationships:
|
||||
ignore_classes += ["IfcRelationship"]
|
||||
if self.ignore_types:
|
||||
ignore_classes += ["IfcTypeProduct"]
|
||||
|
||||
unused_elements = tool.Debug.print_unused_elements_stats(props.ifc_class_purge, ignore_classes)
|
||||
self.report({"INFO"}, f"{unused_elements} unused elements found, check the system console for the details.")
|
||||
|
||||
|
||||
class PurgeUnusedElementsByClass(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.purge_unused_elements_by_class"
|
||||
bl_label = "Purge Unused Elements By Class"
|
||||
bl_description = (
|
||||
"Will find all elements of class that have no inverse refernces and will remove them, use very carefully."
|
||||
)
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMDebugProperties
|
||||
purged_elements = core.purge_unused_elements(tool.Ifc, tool.Debug, props.ifc_class_purge)
|
||||
self.report({"INFO"}, f"{purged_elements} unused elements found and removed.")
|
||||
|
||||
@@ -50,3 +50,4 @@ class BIMDebugProperties(PropertyGroup):
|
||||
name="Display Type",
|
||||
default="BOUNDS",
|
||||
)
|
||||
ifc_class_purge: StringProperty(name="Unused Elements IFC Class", default="")
|
||||
|
||||
@@ -398,3 +398,10 @@ class BIM_PT_purge(Panel):
|
||||
layout.operator("bim.purge_unused_profiles")
|
||||
layout.operator("bim.purge_unused_types")
|
||||
layout.operator("bim.purge_unused_representations")
|
||||
layout.separator()
|
||||
|
||||
layout.label(text="Purge unused elements by class:")
|
||||
row = layout.row(align=True)
|
||||
row.prop(context.scene.BIMDebugProperties, "ifc_class_purge", text="")
|
||||
row.operator("bim.purge_unused_elements_by_class", text="", icon="TRASH")
|
||||
row.operator("bim.print_unused_elements_stats", text="", icon="INFO")
|
||||
|
||||
@@ -23,3 +23,11 @@ def parse_express(debug, filename):
|
||||
|
||||
def purge_hdf5_cache(debug):
|
||||
debug.purge_hdf5_cache()
|
||||
|
||||
|
||||
def purge_unused_elements(ifc, debug, ifc_class):
|
||||
ifc_file = ifc.get()
|
||||
unused_elements = [i for i in ifc_file.by_type(ifc_class) if ifc_file.get_total_inverses(i) == 0]
|
||||
unused_elements_amount = len(unused_elements)
|
||||
debug.remove_unused_elements(unused_elements)
|
||||
return unused_elements_amount
|
||||
|
||||
@@ -20,6 +20,7 @@ import os
|
||||
import bpy
|
||||
import ifcopenshell.express
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
@@ -48,3 +49,42 @@ class Debug(blenderbim.core.tool.Debug):
|
||||
obj = bpy.data.objects.new(name, mesh)
|
||||
bpy.context.scene.collection.objects.link(obj)
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def remove_unused_elements(cls, elements):
|
||||
ifc_file = tool.Ifc.get()
|
||||
for element in elements:
|
||||
ifcopenshell.util.element.remove_deep2(ifc_file, element)
|
||||
|
||||
@classmethod
|
||||
def print_unused_elements_stats(cls, requested_ifc_class="", ignore_classes=tuple()):
|
||||
ifc_file = tool.Ifc.get()
|
||||
|
||||
# get list of ifc classes used in model
|
||||
classes = set()
|
||||
requested_ifc_classes = set()
|
||||
for el in ifc_file:
|
||||
if any(el.is_a(i) for i in ignore_classes):
|
||||
continue
|
||||
classes.add(el.is_a())
|
||||
if requested_ifc_class and el.is_a(requested_ifc_class):
|
||||
requested_ifc_classes.add(el.is_a())
|
||||
|
||||
# count unused elements for each class
|
||||
unused = dict()
|
||||
for c in classes:
|
||||
uses = [i for i in ifc_file.by_type(c) if ifc_file.get_total_inverses(i) == 0]
|
||||
if not uses:
|
||||
continue
|
||||
unused[c] = len(uses)
|
||||
|
||||
# print classes and their unsued elements in ascending order
|
||||
if unused:
|
||||
print("Unused elements by classes:")
|
||||
for ifc_class in sorted(unused.keys(), key=lambda x: unused[x]):
|
||||
class_string = ifc_class
|
||||
if ifc_class in requested_ifc_classes:
|
||||
class_string = "---> " + class_string
|
||||
print(f"{class_string: <50} {unused[ifc_class]: >5}")
|
||||
|
||||
return sum(unused.values())
|
||||
|
||||
Reference in New Issue
Block a user