Updates to space boundary geometry now auto updates on export.

This commit is contained in:
Dion Moult
2022-01-24 21:52:51 +11:00
parent f88a1038a8
commit 5884af0678
5 changed files with 82 additions and 43 deletions
@@ -1,5 +1,5 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on # BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Cyril Waechter <cyril@biminsight.ch>
# #
# This file is part of BlenderBIM Add-on. # This file is part of BlenderBIM Add-on.
# #
@@ -16,16 +16,13 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import logging
import bpy import bpy
import mathutils import logging
import ifcopenshell.util.attribute
import ifcopenshell.api import ifcopenshell.api
import blenderbim.tool as tool import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.boundary.data import Data from ifcopenshell.api.boundary.data import Data
import blenderbim.bim.import_ifc as import_ifc import blenderbim.bim.import_ifc as import_ifc
from blenderbim.bim.module.geometry.helper import Helper
def get_boundaries_collection(blender_space): def get_boundaries_collection(blender_space):
@@ -70,6 +67,7 @@ class Loader:
surface.InnerBoundaries = () surface.InnerBoundaries = ()
shape = ifcopenshell.geom.create_shape(self.settings, surface) shape = ifcopenshell.geom.create_shape(self.settings, surface)
mesh = self.ifc_importer.create_mesh(None, shape) 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 = bpy.data.objects.new(f"{boundary.is_a()}/{boundary.Name}", mesh)
obj.matrix_world = blender_space.matrix_world obj.matrix_world = blender_space.matrix_world
boundaries_collection = get_boundaries_collection(blender_space) boundaries_collection = get_boundaries_collection(blender_space)
@@ -267,20 +265,11 @@ class EditBoundaryAttributes(bpy.types.Operator):
return {"FINISHED"} 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): class UpdateBoundaryGeometry(bpy.types.Operator):
bl_idname = "bim.update_boundary_geometry" bl_idname = "bim.update_boundary_geometry"
bl_label = "Update boundary geometry" bl_label = "Update boundary geometry"
bl_description = """ 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. Mesh must lie on a single plane. It should look like a face or a face with holes.
""" """
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@@ -289,32 +278,6 @@ class UpdateBoundaryGeometry(bpy.types.Operator):
return IfcStore.execute_ifc_operator(self, context) return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context): def _execute(self, context):
ifc_file = tool.Ifc.get() settings = tool.Boundary.get_assign_connection_geometry_settings(context.active_object)
helper = Helper(ifc_file) ifcopenshell.api.run("boundary.assign_connection_geometry", tool.Ifc.get(), **settings)
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)
return {"FINISHED"} return {"FINISHED"}
@@ -155,6 +155,11 @@ class UpdateRepresentation(bpy.types.Operator):
if product.is_a("IfcGridAxis"): if product.is_a("IfcGridAxis"):
ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"axis_curve": obj, "grid_axis": product}) ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"axis_curve": obj, "grid_axis": product})
return 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) core.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
+4
View File
@@ -41,6 +41,10 @@ class Aggregate:
class Blender: pass class Blender: pass
@interface
class Boundary: pass
@interface @interface
class Brick: class Brick:
def add_brick(cls, namespace, brick_class): pass def add_brick(cls, namespace, brick_class): pass
@@ -18,6 +18,7 @@
from blenderbim.tool.aggregate import Aggregate from blenderbim.tool.aggregate import Aggregate
from blenderbim.tool.blender import Blender from blenderbim.tool.blender import Blender
from blenderbim.tool.boundary import Boundary
from blenderbim.tool.brick import Brick from blenderbim.tool.brick import Brick
from blenderbim.tool.collector import Collector from blenderbim.tool.collector import Collector
from blenderbim.tool.context import Context from blenderbim.tool.context import Context
@@ -0,0 +1,66 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Cyril Waechter <cyril@biminsight.ch>
#
# 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 <http://www.gnu.org/licenses/>.
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)