You can now duplicate or linked duplicate objects in IFC. Neat. See #1222.

This commit is contained in:
Dion Moult
2021-01-27 19:00:35 +11:00
parent c472dc2f1b
commit a37e124d8f
6 changed files with 83 additions and 9 deletions
@@ -10,12 +10,13 @@ class Usecase:
self.settings[key] = value
def execute(self):
self.get_mapping_source()
self.zero = self.file.createIfcCartesianPoint((0.0, 0.0, 0.0))
self.x_axis = self.file.createIfcDirection((1.0, 0.0, 0.0))
self.y_axis = self.file.createIfcDirection((0.0, 1.0, 0.0))
self.z_axis = self.file.createIfcDirection((0.0, 0.0, 1.0))
self.get_mapping_source()
mapping_target = self.file.createIfcCartesianTransformationOperator3D(
self.x_axis, self.y_axis, self.zero, 1, self.z_axis
)
@@ -179,20 +179,23 @@ class MapRepresentation(bpy.types.Operator):
bl_idname = "bim.map_representation"
bl_label = "Map Representation"
obj: bpy.props.StringProperty()
target_obj: bpy.props.StringProperty()
obj_data: bpy.props.StringProperty()
def execute(self, context):
objs = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects
target_obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
objs = [o for o in objs if o != target_obj]
obj_data = bpy.data.meshes.get(self.obj_data) if self.obj_data else bpy.context.active_object.data
objs = [o for o in objs if o.data != obj_data]
self.file = IfcStore.get_file()
for obj in objs:
bpy.ops.bim.edit_object_placement(obj=obj.name)
product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
old_representation = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
target_representation = self.file.by_id(target_obj.data.BIMMeshProperties.ifc_definition_id)
obj.data = target_obj.data
if obj.data.BIMMeshProperties.ifc_definition_id:
old_representation = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
else:
old_representation = None
target_representation = self.file.by_id(obj_data.BIMMeshProperties.ifc_definition_id)
obj.data = obj_data
result = map_representation.Usecase(
self.file,
{
@@ -201,7 +204,8 @@ class MapRepresentation(bpy.types.Operator):
},
).execute()
assign_representation.Usecase(self.file, {"product": product, "representation": result}).execute()
bpy.ops.bim.remove_representation(ifc_definition_id=old_representation.id())
if old_representation:
bpy.ops.bim.remove_representation(ifc_definition_id=old_representation.id())
Data.load(obj.BIMObjectProperties.ifc_definition_id)
return {"FINISHED"}
@@ -8,6 +8,7 @@ classes = (
operator.AssignClass,
operator.UnassignClass,
operator.UnlinkObject,
operator.CopyClass,
prop.BIMRootProperties,
ui.BIM_PT_class,
)
@@ -0,0 +1,37 @@
import ifcopenshell
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {"product": None}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
result = self.file.create_entity(self.settings["product"].is_a())
self.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(self.file.schema)
self.copy_attributes(self.settings["product"], result)
for inverse in self.file.get_inverse(self.settings["product"]):
for i, value in enumerate(inverse):
if value == self.settings["product"]:
new_inverse = self.file.create_entity(inverse.is_a())
self.copy_attributes(inverse, new_inverse)
new_inverse[i] = result
elif isinstance(value, (tuple, list)) and self.settings["product"] in value:
new_value = list(value)
new_value.append(result)
inverse[i] = new_value
if result.is_a("IfcProduct"):
result.Representation = None
elif result.is_a("IfcTypeProduct"):
result.RepresentationMaps = None
return result
def copy_attributes(self, from_element, to_element):
declaration = self.schema.declaration_by_name(from_element.is_a())
for attribute in declaration.all_attributes():
if attribute.name() == "GlobalId":
setattr(to_element, attribute.name(), ifcopenshell.guid.new())
else:
setattr(to_element, attribute.name(), getattr(from_element, attribute.name()))
@@ -5,6 +5,7 @@ import ifcopenshell.util.schema
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
import blenderbim.bim.module.root.copy_class as copy_class
from blenderbim.bim.module.owner.api import create_owner_history
from blenderbim.bim.ifc import IfcStore
@@ -203,3 +204,32 @@ class UnlinkObject(bpy.types.Operator):
if obj.BIMObjectProperties.ifc_definition_id:
obj.BIMObjectProperties.ifc_definition_id = 0
return {"FINISHED"}
class CopyClass(bpy.types.Operator):
bl_idname = "bim.copy_class"
bl_label = "Copy Class"
obj: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
if self.obj:
objects = [bpy.data.objects.get(self.obj)]
else:
objects = bpy.context.selected_objects
for obj in objects:
if not obj.BIMObjectProperties.ifc_definition_id:
continue
result = copy_class.Usecase(self.file, {
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
}).execute()
obj.BIMObjectProperties.ifc_definition_id = result.id()
if obj.data.users == 1:
bpy.ops.bim.add_representation(obj=obj.name)
else:
obj_data = obj.data.name
temporary_mesh = bpy.data.meshes.new("Temporary Mesh")
obj.data = temporary_mesh
bpy.ops.bim.map_representation(obj=obj.name, obj_data=obj_data)
bpy.data.meshes.remove(temporary_mesh)
return {"FINISHED"}
@@ -34,6 +34,7 @@ class BIM_PT_class(Panel):
name += "[{}]".format(data["PredefinedType"])
row = self.layout.row(align=True)
row.label(text=name)
row.operator("bim.copy_class", icon="DUPLICATE", text="").obj = context.active_object.name
row.operator("bim.unlink_object", icon="UNLINKED", text="").obj = context.active_object.name
row.operator("bim.enable_reassign_class", icon="GREASEPENCIL", text="")
row.operator("bim.unassign_class", icon="X", text="").obj = context.active_object.name