2021-01-04 11:08:15 +11:00
|
|
|
import bpy
|
|
|
|
|
import numpy as np
|
|
|
|
|
import ifcopenshell
|
2021-01-06 15:19:55 +11:00
|
|
|
import ifcopenshell.util.schema
|
2021-01-04 13:07:29 +11:00
|
|
|
import blenderbim.bim.module.root.create_product as create_product
|
|
|
|
|
import blenderbim.bim.module.root.remove_product as remove_product
|
|
|
|
|
import blenderbim.bim.module.root.reassign_class as reassign_class
|
2021-01-26 13:56:38 +11:00
|
|
|
from blenderbim.bim.module.owner.api import create_owner_history
|
2021-01-04 11:08:15 +11:00
|
|
|
from blenderbim.bim.ifc import IfcStore
|
|
|
|
|
|
|
|
|
|
|
2021-01-04 13:07:29 +11:00
|
|
|
class EnableReassignClass(bpy.types.Operator):
|
|
|
|
|
bl_idname = "bim.enable_reassign_class"
|
|
|
|
|
bl_label = "Enable Reassign IFC Class"
|
2021-01-04 11:08:15 +11:00
|
|
|
|
|
|
|
|
def execute(self, context):
|
|
|
|
|
obj = bpy.context.active_object
|
2021-01-23 12:54:27 +11:00
|
|
|
self.file = IfcStore.get_file()
|
2021-01-04 11:08:15 +11:00
|
|
|
ifc_class = obj.name.split("/")[0]
|
|
|
|
|
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = True
|
|
|
|
|
ifc_products = [
|
|
|
|
|
"IfcElement",
|
|
|
|
|
"IfcElementType",
|
|
|
|
|
"IfcSpatialElement",
|
|
|
|
|
"IfcGroup",
|
|
|
|
|
"IfcStructural",
|
|
|
|
|
"IfcPositioningElement",
|
|
|
|
|
"IfcContext",
|
|
|
|
|
"IfcAnnotation",
|
|
|
|
|
]
|
|
|
|
|
for ifc_product in ifc_products:
|
2021-01-07 10:47:50 +11:00
|
|
|
if ifcopenshell.util.schema.is_a(IfcStore.get_schema().declaration_by_name(ifc_class), ifc_product):
|
2021-01-23 12:54:27 +11:00
|
|
|
bpy.context.scene.BIMRootProperties.ifc_product = ifc_product
|
|
|
|
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
|
|
|
|
bpy.context.scene.BIMRootProperties.ifc_class = element.is_a()
|
|
|
|
|
if hasattr(element, "PredefinedType") and element.PredefinedType:
|
|
|
|
|
bpy.context.scene.BIMRootProperties.ifc_predefined_type = element.PredefinedType
|
2021-01-04 11:08:15 +11:00
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
|
|
2021-01-04 13:07:29 +11:00
|
|
|
class DisableReassignClass(bpy.types.Operator):
|
|
|
|
|
bl_idname = "bim.disable_reassign_class"
|
|
|
|
|
bl_label = "Disable Reassign IFC Class"
|
|
|
|
|
|
|
|
|
|
def execute(self, context):
|
|
|
|
|
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = False
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReassignClass(bpy.types.Operator):
|
|
|
|
|
bl_idname = "bim.reassign_class"
|
|
|
|
|
bl_label = "Reassign IFC Class"
|
|
|
|
|
|
|
|
|
|
def execute(self, context):
|
|
|
|
|
obj = bpy.context.active_object
|
|
|
|
|
self.file = IfcStore.get_file()
|
2021-01-23 12:54:27 +11:00
|
|
|
predefined_type = bpy.context.scene.BIMRootProperties.ifc_predefined_type
|
2021-01-04 13:07:29 +11:00
|
|
|
if predefined_type == "USERDEFINED":
|
2021-01-23 12:54:27 +11:00
|
|
|
predefined_type = bpy.context.scene.BIMRootProperties.ifc_userdefined_type
|
2021-01-05 21:15:52 +11:00
|
|
|
product = reassign_class.Usecase(
|
2021-01-04 13:07:29 +11:00
|
|
|
self.file,
|
|
|
|
|
{
|
|
|
|
|
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
|
2021-01-23 12:54:27 +11:00
|
|
|
"ifc_class": bpy.context.scene.BIMRootProperties.ifc_class,
|
2021-01-04 13:07:29 +11:00
|
|
|
"predefined_type": predefined_type,
|
|
|
|
|
},
|
2021-01-05 21:15:52 +11:00
|
|
|
).execute()
|
2021-01-04 13:07:29 +11:00
|
|
|
obj.name = "{}/{}".format(product.is_a(), "/".join(obj.name.split("/")[1:]))
|
|
|
|
|
obj.BIMObjectProperties.ifc_definition_id = int(product.id())
|
|
|
|
|
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = False
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
|
|
2021-01-04 11:08:15 +11:00
|
|
|
class AssignClass(bpy.types.Operator):
|
|
|
|
|
bl_idname = "bim.assign_class"
|
|
|
|
|
bl_label = "Assign IFC Class"
|
2021-01-05 21:15:52 +11:00
|
|
|
obj: bpy.props.StringProperty()
|
|
|
|
|
ifc_class: bpy.props.StringProperty()
|
|
|
|
|
predefined_type: bpy.props.StringProperty()
|
|
|
|
|
userdefined_type: bpy.props.StringProperty()
|
2021-01-12 15:12:53 +11:00
|
|
|
context_id: bpy.props.IntProperty()
|
2021-01-04 11:08:15 +11:00
|
|
|
|
|
|
|
|
def execute(self, context):
|
2021-01-05 21:15:52 +11:00
|
|
|
objects = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects
|
2021-01-04 11:08:15 +11:00
|
|
|
self.file = IfcStore.get_file()
|
2021-01-07 10:47:50 +11:00
|
|
|
self.declaration = IfcStore.get_schema().declaration_by_name(self.ifc_class)
|
2021-01-06 15:19:55 +11:00
|
|
|
if self.predefined_type == "USERDEFINED":
|
|
|
|
|
self.predefined_type = self.ifc_userdefined_type
|
|
|
|
|
elif self.predefined_type == "":
|
|
|
|
|
predefined_type = None
|
2021-01-04 11:08:15 +11:00
|
|
|
for obj in objects:
|
2021-01-08 16:27:19 +11:00
|
|
|
if obj.data:
|
|
|
|
|
for material in obj.data.materials:
|
|
|
|
|
if not material.BIMMaterialProperties.ifc_style_id:
|
|
|
|
|
bpy.ops.bim.add_style(material=material.name)
|
2021-01-06 15:19:55 +11:00
|
|
|
self.assign_class(obj)
|
2021-01-04 11:08:15 +11:00
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
2021-01-06 15:19:55 +11:00
|
|
|
def assign_class(self, obj):
|
|
|
|
|
if obj.BIMObjectProperties.ifc_definition_id:
|
|
|
|
|
return
|
|
|
|
|
product = create_product.Usecase(
|
|
|
|
|
self.file,
|
|
|
|
|
{
|
|
|
|
|
"ifc_class": self.ifc_class,
|
|
|
|
|
"predefined_type": self.predefined_type,
|
|
|
|
|
"name": obj.name,
|
2021-01-26 13:56:38 +11:00
|
|
|
"OwnerHistory": create_owner_history()
|
2021-01-06 15:19:55 +11:00
|
|
|
},
|
|
|
|
|
).execute()
|
|
|
|
|
obj.name = "{}/{}".format(product.is_a(), obj.name)
|
|
|
|
|
obj.BIMObjectProperties.ifc_definition_id = int(product.id())
|
|
|
|
|
|
2021-01-16 15:36:06 +11:00
|
|
|
if obj.data:
|
|
|
|
|
bpy.ops.bim.add_representation(obj=obj.name, context_id=self.context_id)
|
2021-01-06 15:19:55 +11:00
|
|
|
|
2021-01-07 21:02:46 +11:00
|
|
|
if product.is_a("IfcElementType"):
|
2021-01-06 15:19:55 +11:00
|
|
|
self.place_in_types_collection(obj)
|
2021-01-07 21:02:46 +11:00
|
|
|
elif (
|
|
|
|
|
product.is_a("IfcSpatialElement")
|
|
|
|
|
or product.is_a("IfcSpatialStructureElement")
|
|
|
|
|
or product.is_a("IfcProject")
|
|
|
|
|
or product.is_a("IfcContext")
|
|
|
|
|
):
|
2021-01-06 15:19:55 +11:00
|
|
|
self.place_in_spatial_collection(obj)
|
|
|
|
|
else:
|
|
|
|
|
self.assign_potential_spatial_container(obj)
|
|
|
|
|
|
2021-01-04 11:08:15 +11:00
|
|
|
def place_in_types_collection(self, obj):
|
|
|
|
|
for project in [c for c in bpy.context.view_layer.layer_collection.children if "IfcProject" in c.name]:
|
|
|
|
|
if not [c for c in project.children if "Types" in c.name]:
|
|
|
|
|
types = bpy.data.collections.new("Types")
|
|
|
|
|
project.collection.children.link(types)
|
|
|
|
|
for collection in [c for c in project.children if "Types" in c.name]:
|
|
|
|
|
for user_collection in obj.users_collection:
|
|
|
|
|
user_collection.objects.unlink(obj)
|
|
|
|
|
collection.collection.objects.link(obj)
|
|
|
|
|
break
|
|
|
|
|
break
|
|
|
|
|
|
2021-01-06 15:19:55 +11:00
|
|
|
def place_in_spatial_collection(self, obj):
|
|
|
|
|
for collection in obj.users_collection:
|
|
|
|
|
if collection.name == obj.name:
|
|
|
|
|
return
|
|
|
|
|
parent_collection = None
|
|
|
|
|
for collection in obj.users_collection:
|
|
|
|
|
collection.objects.unlink(obj)
|
|
|
|
|
if "Ifc" in collection.name:
|
|
|
|
|
parent_collection = collection
|
|
|
|
|
collection = bpy.data.collections.new(obj.name)
|
|
|
|
|
collection.objects.link(obj)
|
|
|
|
|
if parent_collection:
|
|
|
|
|
parent_collection.children.link(collection)
|
|
|
|
|
else:
|
|
|
|
|
bpy.context.scene.collection.children.link(collection)
|
|
|
|
|
|
|
|
|
|
def assign_potential_spatial_container(self, obj):
|
|
|
|
|
for collection in obj.users_collection:
|
2021-01-08 11:41:54 +11:00
|
|
|
if "Ifc" not in collection.name or collection.name == obj.name:
|
2021-01-06 15:19:55 +11:00
|
|
|
continue
|
|
|
|
|
bpy.ops.bim.assign_container(relating_structure=collection.name, related_element=obj.name)
|
|
|
|
|
break
|
|
|
|
|
|
2021-01-04 11:08:15 +11:00
|
|
|
|
|
|
|
|
class UnassignClass(bpy.types.Operator):
|
|
|
|
|
bl_idname = "bim.unassign_class"
|
|
|
|
|
bl_label = "Unassign IFC Class"
|
2021-01-12 15:12:53 +11:00
|
|
|
obj: bpy.props.StringProperty()
|
2021-01-04 11:08:15 +11:00
|
|
|
|
|
|
|
|
def execute(self, context):
|
2021-01-04 13:07:29 +11:00
|
|
|
self.file = IfcStore.get_file()
|
2021-01-12 15:12:53 +11:00
|
|
|
if self.obj:
|
|
|
|
|
objects = [bpy.data.objects.get(self.obj)]
|
2021-01-04 11:08:15 +11:00
|
|
|
else:
|
|
|
|
|
objects = bpy.context.selected_objects
|
|
|
|
|
for obj in objects:
|
2021-01-04 13:07:29 +11:00
|
|
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
|
|
|
|
continue
|
|
|
|
|
usecase = remove_product.Usecase(
|
|
|
|
|
self.file,
|
|
|
|
|
{"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)},
|
|
|
|
|
)
|
|
|
|
|
usecase.execute()
|
|
|
|
|
obj.BIMObjectProperties.ifc_definition_id = 0
|
2021-01-04 11:08:15 +11:00
|
|
|
if "/" in obj.name and obj.name[0:3] == "Ifc":
|
|
|
|
|
obj.name = "/".join(obj.name.split("/")[1:])
|
|
|
|
|
return {"FINISHED"}
|