mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
WIP assigning a class now ported over to partial editing and creates an IFC element. See #1222.
This commit is contained in:
@@ -5,6 +5,7 @@ bpy = sys.modules.get("bpy")
|
||||
|
||||
if bpy is not None:
|
||||
import bpy
|
||||
import blenderbim.bim.module.root as module_root
|
||||
import blenderbim.bim.module.bcf as module_bcf
|
||||
import blenderbim.bim.module.context as module_context
|
||||
import blenderbim.bim.module.covetool as module_covetool
|
||||
@@ -13,9 +14,6 @@ if bpy is not None:
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = [
|
||||
operator.ReassignClass,
|
||||
operator.AssignClass,
|
||||
operator.UnassignClass,
|
||||
operator.SelectClass,
|
||||
operator.SelectType,
|
||||
operator.OpenUri,
|
||||
@@ -312,6 +310,7 @@ if bpy is not None:
|
||||
ui.BIM_ADDON_preferences,
|
||||
]
|
||||
|
||||
classes.extend(module_root.classes)
|
||||
classes.extend(module_bcf.classes)
|
||||
classes.extend(module_context.classes)
|
||||
classes.extend(module_covetool.classes)
|
||||
@@ -348,6 +347,7 @@ if bpy is not None:
|
||||
bpy.types.Camera.BIMCameraProperties = bpy.props.PointerProperty(type=prop.BIMCameraProperties)
|
||||
bpy.types.TextCurve.BIMTextProperties = bpy.props.PointerProperty(type=prop.BIMTextProperties)
|
||||
bpy.types.SCENE_PT_unit.append(ui.ifc_units)
|
||||
module_root.register()
|
||||
module_bcf.register()
|
||||
module_context.register()
|
||||
module_covetool.register()
|
||||
@@ -378,4 +378,5 @@ if bpy is not None:
|
||||
module_covetool.unregister()
|
||||
module_context.unregister()
|
||||
module_bcf.unregister()
|
||||
module_root.unregister()
|
||||
bpy.app.handlers.depsgraph_update_pre.remove(operator.depsgraph_update_pre_handler)
|
||||
|
||||
@@ -12,6 +12,7 @@ class Usecase:
|
||||
definition = self.settings["product"].Representation
|
||||
if not definition:
|
||||
definition = self.file.createIfcProductDefinitionShape()
|
||||
representations = list(definition.Representations)
|
||||
self.settings["product"].Representation = definition
|
||||
representations = list(definition.Representations) if definition.Representations else []
|
||||
representations.append(self.settings["representation"])
|
||||
definition.Representations = representations
|
||||
|
||||
@@ -6,6 +6,8 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
if not self.settings["styles"]:
|
||||
return []
|
||||
self.results = []
|
||||
for element in self.file.traverse(self.settings["shape_representation"]):
|
||||
if not element.is_a("IfcShapeRepresentation"):
|
||||
|
||||
@@ -22,20 +22,35 @@ class AddRepresentation(bpy.types.Operator):
|
||||
self.context_id = bpy.context.scene.BIMProperties.contexts
|
||||
|
||||
element = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
|
||||
usecase = add_representation.Usecase(self.file, {
|
||||
"context": self.file.by_id(int(self.context_id)),
|
||||
"geometry": obj.data,
|
||||
"total_items": max(1, len(obj.material_slots)),
|
||||
})
|
||||
usecase = add_representation.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"context": self.file.by_id(int(self.context_id)),
|
||||
"geometry": obj.data,
|
||||
"total_items": max(1, len(obj.material_slots)),
|
||||
},
|
||||
)
|
||||
result = usecase.execute()
|
||||
if not result:
|
||||
print("Failed to write shape representation")
|
||||
return {"FINISHED"}
|
||||
|
||||
usecase = assign_representation.Usecase(self.file, {
|
||||
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
|
||||
"representation": result
|
||||
})
|
||||
usecase = assign_styles.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"shape_representation": result,
|
||||
"styles": [
|
||||
self.file.by_id(s.material.BIMMaterialProperties.ifc_style_id)
|
||||
for s in obj.material_slots
|
||||
if s.material
|
||||
],
|
||||
},
|
||||
)
|
||||
usecase.execute()
|
||||
|
||||
usecase = assign_representation.Usecase(
|
||||
self.file, {"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), "representation": result}
|
||||
)
|
||||
usecase.execute()
|
||||
|
||||
existing_mesh = obj.data
|
||||
@@ -116,27 +131,40 @@ class BakeParametricGeometry(bpy.types.Operator):
|
||||
obj = bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
|
||||
usecase = add_object_placement.Usecase(self.file, {
|
||||
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
|
||||
"matrix": np.array(obj.matrix_world)
|
||||
})
|
||||
usecase = add_object_placement.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
|
||||
"matrix": np.array(obj.matrix_world),
|
||||
},
|
||||
)
|
||||
result = usecase.execute()
|
||||
|
||||
element = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
|
||||
usecase = add_representation.Usecase(self.file, {
|
||||
"context": element.ContextOfItems,
|
||||
"geometry": obj.data,
|
||||
"total_items": max(1, len(obj.material_slots)),
|
||||
})
|
||||
usecase = add_representation.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"context": element.ContextOfItems,
|
||||
"geometry": obj.data,
|
||||
"total_items": max(1, len(obj.material_slots)),
|
||||
},
|
||||
)
|
||||
result = usecase.execute()
|
||||
if not result:
|
||||
print("Failed to write shape representation")
|
||||
return {"FINISHED"}
|
||||
|
||||
usecase = assign_styles.Usecase(self.file, {
|
||||
"shape_representation": result,
|
||||
"styles": [self.file.by_id(s.material.BIMMaterialProperties.ifc_style_id) for s in obj.material_slots if s.material]
|
||||
})
|
||||
usecase = assign_styles.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"shape_representation": result,
|
||||
"styles": [
|
||||
self.file.by_id(s.material.BIMMaterialProperties.ifc_style_id)
|
||||
for s in obj.material_slots
|
||||
if s.material
|
||||
],
|
||||
},
|
||||
)
|
||||
usecase.execute()
|
||||
|
||||
for inverse in self.file.get_inverse(element):
|
||||
@@ -157,7 +185,7 @@ class UpdateIfcRepresentation(bpy.types.Operator):
|
||||
props = obj.data.BIMMeshProperties
|
||||
parameter = props.ifc_parameters[self.index]
|
||||
element = IfcStore.get_file().by_id(parameter.step_id)[parameter.index] = parameter.value
|
||||
bpy.ops.bim.switch_representation(ifc_definition_id = props.ifc_definition_id)
|
||||
bpy.ops.bim.switch_representation(ifc_definition_id=props.ifc_definition_id)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import bpy
|
||||
from . import operator
|
||||
|
||||
classes = (
|
||||
operator.ReassignClass,
|
||||
operator.AssignClass,
|
||||
operator.UnassignClass,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
pass
|
||||
|
||||
|
||||
def unregister():
|
||||
pass
|
||||
@@ -0,0 +1,24 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"ifc_class": "IfcBuildingElementProxy",
|
||||
"predefined_type": None,
|
||||
"name": None,
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
element = self.file.create_entity(self.settings["ifc_class"], **{"GlobalId": ifcopenshell.guid.new()})
|
||||
element.Name = self.settings["name"] or None
|
||||
if self.settings["predefined_type"] and hasattr(element, "PredefinedType"):
|
||||
try:
|
||||
element.PredefinedType = self.settings["predefined_type"]
|
||||
except:
|
||||
element.PredefinedType = "USERDEFINED"
|
||||
element.ObjectType = self.settings["predefined_type"]
|
||||
return element
|
||||
@@ -0,0 +1,135 @@
|
||||
import bpy
|
||||
import numpy as np
|
||||
import ifcopenshell
|
||||
import blenderbim.bim.module.root.assign_class as assign_class
|
||||
import blenderbim.bim.module.geometry.add_representation as add_representation
|
||||
import blenderbim.bim.module.geometry.assign_styles as assign_styles
|
||||
import blenderbim.bim.module.geometry.assign_representation as assign_representation
|
||||
import blenderbim.bim.module.geometry.add_object_placement as add_object_placement
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
# from blenderbim.bim.module.geometry.data import Data
|
||||
|
||||
|
||||
class ReassignClass(bpy.types.Operator):
|
||||
bl_idname = "bim.reassign_class"
|
||||
bl_label = "Reassign IFC Class"
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.context.active_object
|
||||
ifc_class = obj.name.split("/")[0]
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
|
||||
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:
|
||||
if ifcopenshell.util.schema.is_a(ifc_schema.declaration_by_name(ifc_class), ifc_product):
|
||||
bpy.context.scene.BIMProperties.ifc_product = ifc_product
|
||||
bpy.context.scene.BIMProperties.ifc_class = obj.name.split("/")[0]
|
||||
predefined_type = obj.BIMObjectProperties.attributes.get("PredefinedType")
|
||||
if predefined_type:
|
||||
bpy.context.scene.BIMProperties.ifc_predefined_type = predefined_type.string_value
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AssignClass(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_class"
|
||||
bl_label = "Assign IFC Class"
|
||||
object_name: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
objects = [bpy.data.objects.get(self.object_name)] if self.object_name else bpy.context.selected_objects
|
||||
self.file = IfcStore.get_file()
|
||||
for obj in objects:
|
||||
if obj.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
usecase = assign_class.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"ifc_class": bpy.context.scene.BIMProperties.ifc_class,
|
||||
"predefined_type": bpy.context.scene.BIMProperties.ifc_predefined_type,
|
||||
"name": obj.name,
|
||||
},
|
||||
)
|
||||
product = usecase.execute()
|
||||
|
||||
usecase = add_object_placement.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"product": product,
|
||||
"matrix": np.array(obj.matrix_world),
|
||||
},
|
||||
)
|
||||
result = usecase.execute()
|
||||
|
||||
if obj.data:
|
||||
usecase = add_representation.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"context": self.file.by_id(int(bpy.context.scene.BIMProperties.contexts)),
|
||||
"geometry": obj.data,
|
||||
"total_items": max(1, len(obj.material_slots)),
|
||||
},
|
||||
)
|
||||
representation = usecase.execute()
|
||||
|
||||
usecase = assign_styles.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"shape_representation": representation,
|
||||
"styles": [
|
||||
self.file.by_id(s.material.BIMMaterialProperties.ifc_style_id)
|
||||
for s in obj.material_slots
|
||||
if s.material
|
||||
],
|
||||
},
|
||||
)
|
||||
usecase.execute()
|
||||
|
||||
usecase = assign_representation.Usecase(
|
||||
self.file, {"product": product, "representation": representation}
|
||||
)
|
||||
usecase.execute()
|
||||
|
||||
obj.name = "{}/{}".format(bpy.context.scene.BIMProperties.ifc_class, obj.name)
|
||||
obj.BIMObjectProperties.ifc_definition_id = int(result.id())
|
||||
if bpy.context.scene.BIMProperties.ifc_product == "IfcElementType":
|
||||
self.place_in_types_collection(obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
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
|
||||
|
||||
|
||||
class UnassignClass(bpy.types.Operator):
|
||||
bl_idname = "bim.unassign_class"
|
||||
bl_label = "Unassign IFC Class"
|
||||
object_name: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
if self.object_name:
|
||||
objects = [bpy.data.objects.get(self.object_name)]
|
||||
else:
|
||||
objects = bpy.context.selected_objects
|
||||
for obj in objects:
|
||||
existing_class = None
|
||||
if "/" in obj.name and obj.name[0:3] == "Ifc":
|
||||
obj.name = "/".join(obj.name.split("/")[1:])
|
||||
return {"FINISHED"}
|
||||
@@ -229,101 +229,6 @@ class SelectPset(bpy.types.Operator):
|
||||
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
|
||||
ifc_class = obj.name.split("/")[0]
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
|
||||
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:
|
||||
if ifcopenshell.util.schema.is_a(ifc_schema.declaration_by_name(ifc_class), ifc_product):
|
||||
bpy.context.scene.BIMProperties.ifc_product = ifc_product
|
||||
bpy.context.scene.BIMProperties.ifc_class = obj.name.split("/")[0]
|
||||
predefined_type = obj.BIMObjectProperties.attributes.get("PredefinedType")
|
||||
if predefined_type:
|
||||
bpy.context.scene.BIMProperties.ifc_predefined_type = predefined_type.string_value
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AssignClass(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_class"
|
||||
bl_label = "Assign IFC Class"
|
||||
object_name: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
if self.object_name:
|
||||
objects = [bpy.data.objects.get(self.object_name)]
|
||||
objects[0].BIMObjectProperties.is_reassigning_class = False
|
||||
else:
|
||||
objects = bpy.context.selected_objects
|
||||
for obj in objects:
|
||||
existing_class = None
|
||||
if "/" in obj.name and obj.name[0:3] == "Ifc":
|
||||
existing_class = obj.name.split("/")[0]
|
||||
if existing_class:
|
||||
obj.name = "{}/{}".format(bpy.context.scene.BIMProperties.ifc_class, obj.name.split("/")[1])
|
||||
else:
|
||||
obj.name = "{}/{}".format(bpy.context.scene.BIMProperties.ifc_class, obj.name)
|
||||
predefined_type_index = obj.BIMObjectProperties.attributes.find("PredefinedType")
|
||||
if predefined_type_index >= 0:
|
||||
obj.BIMObjectProperties.attributes.remove(predefined_type_index)
|
||||
object_type_index = obj.BIMObjectProperties.attributes.find("ObjectType")
|
||||
if object_type_index >= 0:
|
||||
obj.BIMObjectProperties.attributes.remove(object_type_index)
|
||||
if bpy.context.scene.BIMProperties.ifc_predefined_type:
|
||||
predefined_type = obj.BIMObjectProperties.attributes.add()
|
||||
predefined_type.name = "PredefinedType"
|
||||
predefined_type.string_value = (
|
||||
bpy.context.scene.BIMProperties.ifc_predefined_type
|
||||
) # TODO: make it an enum
|
||||
if bpy.context.scene.BIMProperties.ifc_predefined_type == "USERDEFINED":
|
||||
object_type = obj.BIMObjectProperties.attributes.add()
|
||||
object_type.name = "ObjectType"
|
||||
object_type.string_value = bpy.context.scene.BIMProperties.ifc_userdefined_type
|
||||
if bpy.context.scene.BIMProperties.ifc_product == "IfcElementType":
|
||||
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
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class UnassignClass(bpy.types.Operator):
|
||||
bl_idname = "bim.unassign_class"
|
||||
bl_label = "Unassign IFC Class"
|
||||
object_name: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
if self.object_name:
|
||||
objects = [bpy.data.objects.get(self.object_name)]
|
||||
else:
|
||||
objects = bpy.context.selected_objects
|
||||
for obj in objects:
|
||||
existing_class = None
|
||||
if "/" in obj.name and obj.name[0:3] == "Ifc":
|
||||
obj.name = "/".join(obj.name.split("/")[1:])
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SelectClass(bpy.types.Operator):
|
||||
bl_idname = "bim.select_class"
|
||||
bl_label = "Select IFC Class"
|
||||
|
||||
Reference in New Issue
Block a user