From 5884af0678d05fa8f1d1b0fc9d167259fb6ea426 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 24 Jan 2022 21:52:51 +1100 Subject: [PATCH] Updates to space boundary geometry now auto updates on export. --- .../bim/module/boundary/operator.py | 49 ++------------ .../bim/module/geometry/operator.py | 5 ++ src/blenderbim/blenderbim/core/tool.py | 4 ++ src/blenderbim/blenderbim/tool/__init__.py | 1 + src/blenderbim/blenderbim/tool/boundary.py | 66 +++++++++++++++++++ 5 files changed, 82 insertions(+), 43 deletions(-) create mode 100644 src/blenderbim/blenderbim/tool/boundary.py diff --git a/src/blenderbim/blenderbim/bim/module/boundary/operator.py b/src/blenderbim/blenderbim/bim/module/boundary/operator.py index a2395135c0..05e91aad9a 100644 --- a/src/blenderbim/blenderbim/bim/module/boundary/operator.py +++ b/src/blenderbim/blenderbim/bim/module/boundary/operator.py @@ -1,5 +1,5 @@ # BlenderBIM Add-on - OpenBIM Blender Add-on -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Cyril Waechter # # This file is part of BlenderBIM Add-on. # @@ -16,16 +16,13 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . -import logging import bpy -import mathutils -import ifcopenshell.util.attribute +import logging import ifcopenshell.api import blenderbim.tool as tool from blenderbim.bim.ifc import IfcStore from ifcopenshell.api.boundary.data import Data import blenderbim.bim.import_ifc as import_ifc -from blenderbim.bim.module.geometry.helper import Helper def get_boundaries_collection(blender_space): @@ -70,6 +67,7 @@ class Loader: surface.InnerBoundaries = () shape = ifcopenshell.geom.create_shape(self.settings, surface) mesh = self.ifc_importer.create_mesh(None, shape) + self.ifc_importer.link_mesh(shape, mesh) obj = bpy.data.objects.new(f"{boundary.is_a()}/{boundary.Name}", mesh) obj.matrix_world = blender_space.matrix_world boundaries_collection = get_boundaries_collection(blender_space) @@ -267,20 +265,11 @@ class EditBoundaryAttributes(bpy.types.Operator): return {"FINISHED"} -def polyline_from_indexes(mesh, indexes): - return tuple(mesh.vertices[i].co for i in indexes) - - -def polyline_to_2d(polyline, placement_matrix): - matrix_inv = placement_matrix.inverted() - return tuple((matrix_inv @ v).to_2d() for v in polyline) - - class UpdateBoundaryGeometry(bpy.types.Operator): bl_idname = "bim.update_boundary_geometry" bl_label = "Update boundary geometry" bl_description = """ - Update boundary connection geometry from mesh. + Update boundary connection geometry from mesh. Mesh must lie on a single plane. It should look like a face or a face with holes. """ bl_options = {"REGISTER", "UNDO"} @@ -289,32 +278,6 @@ class UpdateBoundaryGeometry(bpy.types.Operator): return IfcStore.execute_ifc_operator(self, context) def _execute(self, context): - ifc_file = tool.Ifc.get() - helper = Helper(ifc_file) - mesh = context.active_object.data - curves = helper.auto_detect_curve_bounded_plane(mesh) - outer_boundary = polyline_from_indexes(mesh, curves["outer_curve"]) - inner_boundaries = tuple(polyline_from_indexes(mesh, boundary) for boundary in curves["inner_curves"]) - - # Create placement matrix - location = outer_boundary[0] - i = (outer_boundary[1] - outer_boundary[0]).normalized() - k = mesh.polygons[0].normal - j = k.cross(i) - matrix = mathutils.Matrix() - matrix[0].xyz = i - matrix[1].xyz = j - matrix[2].xyz = k - matrix.transpose() - matrix.translation = location - - settings = { - "rel_space_boundary": tool.Ifc.get_entity(context.active_object), - "outer_boundary": polyline_to_2d(outer_boundary, matrix), - "inner_boundaries": tuple(polyline_to_2d(boundary, matrix) for boundary in inner_boundaries), - "location": location, - "axis": k, - "ref_direction": i, - } - ifcopenshell.api.run("boundary.assign_connection_geometry", ifc_file, **settings) + settings = tool.Boundary.get_assign_connection_geometry_settings(context.active_object) + ifcopenshell.api.run("boundary.assign_connection_geometry", tool.Ifc.get(), **settings) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index cac144c774..aff0896a06 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -155,6 +155,11 @@ class UpdateRepresentation(bpy.types.Operator): if product.is_a("IfcGridAxis"): ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"axis_curve": obj, "grid_axis": product}) return + if product.is_a("IfcRelSpaceBoundary"): + # TODO refactor + settings = tool.Boundary.get_assign_connection_geometry_settings(obj) + ifcopenshell.api.run("boundary.assign_connection_geometry", tool.Ifc.get(), **settings) + return core.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj) diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index f3e252f499..67ec682829 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -41,6 +41,10 @@ class Aggregate: class Blender: pass +@interface +class Boundary: pass + + @interface class Brick: def add_brick(cls, namespace, brick_class): pass diff --git a/src/blenderbim/blenderbim/tool/__init__.py b/src/blenderbim/blenderbim/tool/__init__.py index 9d0172432e..a5400a099a 100644 --- a/src/blenderbim/blenderbim/tool/__init__.py +++ b/src/blenderbim/blenderbim/tool/__init__.py @@ -18,6 +18,7 @@ from blenderbim.tool.aggregate import Aggregate from blenderbim.tool.blender import Blender +from blenderbim.tool.boundary import Boundary from blenderbim.tool.brick import Brick from blenderbim.tool.collector import Collector from blenderbim.tool.context import Context diff --git a/src/blenderbim/blenderbim/tool/boundary.py b/src/blenderbim/blenderbim/tool/boundary.py new file mode 100644 index 0000000000..4e2338b302 --- /dev/null +++ b/src/blenderbim/blenderbim/tool/boundary.py @@ -0,0 +1,66 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2022 Cyril Waechter +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + +import bpy +import mathutils +import blenderbim.core.tool +import blenderbim.tool as tool +from blenderbim.bim.module.geometry.helper import Helper + + +class Boundary(blenderbim.core.tool.Boundary): + @classmethod + def get_assign_connection_geometry_settings(cls, obj): + ifc = tool.Ifc.get() + helper = Helper(ifc) + mesh = obj.data + curves = helper.auto_detect_curve_bounded_plane(mesh) + outer_boundary = cls.polyline_from_indexes(mesh, curves["outer_curve"]) + inner_boundaries = tuple(cls.polyline_from_indexes(mesh, boundary) for boundary in curves["inner_curves"]) + + # Create placement matrix + location = outer_boundary[0] + i = (outer_boundary[1] - outer_boundary[0]).normalized() + k = mesh.polygons[0].normal + j = k.cross(i) + matrix = mathutils.Matrix() + matrix[0].xyz = i + matrix[1].xyz = j + matrix[2].xyz = k + matrix.transpose() + matrix.translation = location + + return { + "rel_space_boundary": tool.Ifc.get_entity(obj), + "outer_boundary": cls.polyline_to_2d(outer_boundary, matrix), + "inner_boundaries": tuple(cls.polyline_to_2d(boundary, matrix) for boundary in inner_boundaries), + "location": location, + "axis": k, + "ref_direction": i, + } + + @classmethod + def polyline_from_indexes(cls, mesh, indexes): + return tuple(mesh.vertices[i].co for i in indexes) + + + @classmethod + def polyline_to_2d(cls, polyline, placement_matrix): + matrix_inv = placement_matrix.inverted() + return tuple((matrix_inv @ v).to_2d() for v in polyline) +