Utility_Apps/Blender/simple scripts/Selects only those instances that are instantiated once.py
2025-09-10 09:31:12 -05:00

131 lines
4.8 KiB
Python

import bpy
import bonsai.tool as tool
import ifcopenshell
def select_elements_with_types():
"""
Select only elements that have types and are instantiated only once.
Works with Bonsai add-on in Blender.
"""
# Get the current IFC file from Bonsai
ifc_file = tool.Ifc.get()
if not ifc_file:
print("No IFC file is currently loaded in Bonsai")
return
# Clear current selection
bpy.ops.object.select_all(action='DESELECT')
selected_count = 0
# First, count how many instances each type has
type_instance_count = {}
# Get all elements that can have types
elements_with_possible_types = ifc_file.by_type("IfcElement") + \
ifc_file.by_type("IfcSpatialElement") + \
ifc_file.by_type("IfcDistributionElement")
# Count instances per type
for element in elements_with_possible_types:
element_type = None
# Get the type element
if hasattr(element, 'IsTypedBy') and element.IsTypedBy:
for rel in element.IsTypedBy:
if rel.is_a('IfcRelDefinesByType'):
element_type = rel.RelatingType
break
if element_type:
type_id = element_type.id()
if type_id not in type_instance_count:
type_instance_count[type_id] = []
type_instance_count[type_id].append(element)
# Select only elements whose type is instantiated exactly once
for type_id, instances in type_instance_count.items():
if len(instances) == 1: # Only one instance of this type
element = instances[0]
obj = tool.Ifc.get_object(element)
if obj:
obj.select_set(True)
selected_count += 1
element_name = getattr(element, 'Name', 'Unnamed')
type_element = ifc_file.by_id(type_id)
type_name = getattr(type_element, 'Name', 'Unnamed Type')
print(f"Selected: {element.is_a()} '{element_name}' -> Type: {type_element.is_a()} '{type_name}' (Single instance)")
print(f"\nTotal elements with single-instance types selected: {selected_count}")
# Update the viewport
bpy.context.view_layer.update()
# Alternative version that also shows the type information for single instances
def select_elements_with_types_detailed():
"""
Select all elements with single-instance types and print detailed type information.
"""
ifc_file = tool.Ifc.get()
if not ifc_file:
print("No IFC file is currently loaded in Bonsai")
return
bpy.ops.object.select_all(action='DESELECT')
selected_count = 0
# Count instances per type
type_instance_count = {}
elements_with_possible_types = ifc_file.by_type("IfcElement") + \
ifc_file.by_type("IfcSpatialElement") + \
ifc_file.by_type("IfcDistributionElement")
for element in elements_with_possible_types:
element_type = None
# Get the type element
if hasattr(element, 'IsTypedBy') and element.IsTypedBy:
for rel in element.IsTypedBy:
if rel.is_a('IfcRelDefinesByType'):
element_type = rel.RelatingType
break
if element_type:
type_id = element_type.id()
if type_id not in type_instance_count:
type_instance_count[type_id] = []
type_instance_count[type_id].append(element)
# Show statistics and select single instances
print("=== Type Instance Analysis ===")
single_instance_count = 0
multi_instance_count = 0
for type_id, instances in type_instance_count.items():
type_element = ifc_file.by_id(type_id)
type_name = getattr(type_element, 'Name', 'Unnamed Type')
if len(instances) == 1:
single_instance_count += 1
element = instances[0]
obj = tool.Ifc.get_object(element)
if obj:
obj.select_set(True)
selected_count += 1
element_name = getattr(element, 'Name', 'Unnamed')
print(f"✓ SELECTED: {element.is_a()} '{element_name}' -> Type: '{type_name}' (1 instance)")
else:
multi_instance_count += 1
print(f" SKIPPED: Type '{type_name}' ({len(instances)} instances)")
print(f"\n=== Summary ===")
print(f"Single-instance types: {single_instance_count} (selected)")
print(f"Multi-instance types: {multi_instance_count} (skipped)")
print(f"Total elements selected: {selected_count}")
bpy.context.view_layer.update()
select_elements_with_types()