131 lines
4.8 KiB
Python
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()
|