From 8789a19f57f5ff60fef3b8515bcad4bfce4c84c1 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 1 Oct 2022 20:31:03 +1000 Subject: [PATCH] Basic show and remove representation boolean operators --- .../blenderbim/bim/module/model/__init__.py | 2 + .../blenderbim/bim/module/model/opening.py | 101 +++++++++++++++++- src/blenderbim/blenderbim/bim/prop.py | 2 + src/blenderbim/blenderbim/tool/model.py | 2 +- 4 files changed, 105 insertions(+), 2 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py index 0d1553694d..79e2bf0af5 100644 --- a/src/blenderbim/blenderbim/bim/module/model/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py @@ -39,6 +39,8 @@ classes = ( opening.AddElementOpening, opening.AddPotentialHalfSpaceSolid, opening.AddPotentialOpening, + opening.RemoveBooleans, + opening.ShowBooleans, profile.ChangeCardinalPoint, profile.ChangeProfileDepth, profile.ExtendProfile, diff --git a/src/blenderbim/blenderbim/bim/module/model/opening.py b/src/blenderbim/blenderbim/bim/module/model/opening.py index 9accc5951b..f7f240e518 100644 --- a/src/blenderbim/blenderbim/bim/module/model/opening.py +++ b/src/blenderbim/blenderbim/bim/module/model/opening.py @@ -27,7 +27,7 @@ import blenderbim.tool as tool import blenderbim.core.geometry from blenderbim.bim.ifc import IfcStore from math import pi -from mathutils import Vector +from mathutils import Vector, Matrix from bpy.types import Operator from bpy.types import SpaceView3D from bpy.props import FloatProperty @@ -328,6 +328,105 @@ class AddBoolean(Operator, tool.Ifc.Operator): return {"FINISHED"} +class ShowBooleans(Operator, tool.Ifc.Operator, AddObjectHelper): + bl_idname = "bim.show_booleans" + bl_label = "Show Booleans" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + obj = context.active_object + if ( + not obj.data + or not hasattr(obj.data, "BIMMeshProperties") + or not obj.data.BIMMeshProperties.ifc_definition_id + ): + return {"FINISHED"} + representation = tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id) + booleans = [] + for item in representation.Items: + booleans.extend(self.get_booleans(item)) + for boolean in booleans: + if boolean.is_a() == "IfcHalfSpaceSolid": + if boolean.BaseSurface.is_a("IfcPlane"): + boolean_obj = self.create_half_space_solid() + position = boolean.BaseSurface.Position + position = Matrix(ifcopenshell.util.placement.get_axis2placement(position).tolist()) + boolean_obj.matrix_world = position + boolean_obj.data.BIMMeshProperties.ifc_boolean_id = boolean.id() + boolean_obj.data.BIMMeshProperties.obj = obj + return {"FINISHED"} + + def get_booleans(self, item): + results = [] + if item.is_a("IfcBooleanResult"): + results.extend(self.get_booleans(item.FirstOperand)) + results.append(item.SecondOperand) + return results + + def create_half_space_solid(self): + props = bpy.context.scene.BIMModelProperties + bm = bmesh.new() + bmesh.ops.create_grid(bm, size=0.5) + bm.verts.ensure_lookup_table() + bm.edges.ensure_lookup_table() + bm.faces.ensure_lookup_table() + mesh = bpy.data.meshes.new(name="Dumb Opening") + bm.to_mesh(mesh) + bm.free() + obj = object_data_add(bpy.context, mesh, operator=self) + obj.name = "HalfSpaceSolid" + + has_deleted_opening = True + while has_deleted_opening: + has_deleted_opening = False + for i, opening in enumerate(props.openings): + if not opening.obj: + props.openings.remove(i) + has_deleted_opening = True + + new = props.openings.add() + new.obj = obj + + DecorationsHandler.install(bpy.context) + return obj + + +class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper): + bl_idname = "bim.remove_booleans" + bl_label = "Remove Booleans" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + for obj in context.selected_objects: + if ( + not obj.data + or not hasattr(obj.data, "BIMMeshProperties") + or not obj.data.BIMMeshProperties.ifc_boolean_id + ): + continue + try: + boolean = tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_boolean_id) + except: + continue + ifcopenshell.api.run("geometry.remove_boolean", tool.Ifc.get(), item=boolean) + if obj.data.BIMMeshProperties.obj: + upstream_obj = obj.data.BIMMeshProperties.obj + element = tool.Ifc.get_entity(upstream_obj) + body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW") + if body: + blenderbim.core.geometry.switch_representation( + tool.Geometry, + obj=upstream_obj, + representation=body, + should_reload=True, + enable_dynamic_voids=False, + is_global=True, + should_sync_changes_first=False, + ) + bpy.data.objects.remove(obj) + return {"FINISHED"} + + class DecorationsHandler: installed = None diff --git a/src/blenderbim/blenderbim/bim/prop.py b/src/blenderbim/blenderbim/bim/prop.py index 359d10ffb1..f6beae20c4 100644 --- a/src/blenderbim/blenderbim/bim/prop.py +++ b/src/blenderbim/blenderbim/bim/prop.py @@ -367,6 +367,8 @@ class BIMMaterialProperties(PropertyGroup): class BIMMeshProperties(PropertyGroup): ifc_definition_id: IntProperty(name="IFC Definition ID") + ifc_boolean_id: IntProperty(name="IFC Boolean ID") + obj: bpy.props.PointerProperty(type=bpy.types.Object) is_native: BoolProperty(name="Is Native", default=False) is_swept_solid: BoolProperty(name="Is Swept Solid") is_parametric: BoolProperty(name="Is Parametric", default=False) diff --git a/src/blenderbim/blenderbim/tool/model.py b/src/blenderbim/blenderbim/tool/model.py index ee8cf8ae07..d713478053 100644 --- a/src/blenderbim/blenderbim/tool/model.py +++ b/src/blenderbim/blenderbim/tool/model.py @@ -42,7 +42,7 @@ class Model(blenderbim.core.tool.Model): while True: if item.is_a("IfcExtrudedAreaSolid"): return item - elif item.is_a("IfcBooleanClippingResult"): + elif item.is_a("IfcBooleanResult"): item = item.FirstOperand else: break