diff --git a/src/bonsai/bonsai/bim/import_ifc.py b/src/bonsai/bonsai/bim/import_ifc.py index e777545780..0ed6f3d9e7 100644 --- a/src/bonsai/bonsai/bim/import_ifc.py +++ b/src/bonsai/bonsai/bim/import_ifc.py @@ -38,6 +38,7 @@ import bonsai.tool as tool from bonsai.bim.ifc import IfcStore, IFC_CONNECTED_TYPE from bonsai.tool.loader import OBJECT_DATA_TYPE from typing import Dict, Union, Optional, Any, Literal +from ifcopenshell.util.shape import MatrixType class MaterialCreator: @@ -479,14 +480,16 @@ class IfcImporter: if grid.WAxes: self.create_grid_axes(grid.WAxes, grid_obj, grid_placement) - def create_grid_axes(self, axes, grid_obj, grid_placement): + def create_grid_axes( + self, axes: list[ifcopenshell.entity_instance], grid_obj: bpy.types.Object, grid_placement: MatrixType + ) -> None: for axis in axes: shape = tool.Loader.create_generic_shape(axis.AxisCurve) mesh = self.create_mesh(axis, shape) obj = bpy.data.objects.new(tool.Loader.get_name(axis), mesh) obj.show_in_front = True self.link_element(axis, obj) - self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, grid_placement.copy())) + self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, grid_placement)) def create_element_types(self): for element_type in self.element_types: @@ -809,7 +812,7 @@ class IfcImporter: if shape: # We use numpy here because Blender mathutils.Matrix is not accurate enough - mat = np.array(shape.transformation.matrix).reshape((4, 4), order="F") + mat = ifcopenshell.util.shape.get_shape_matrix(shape) self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, mat)) assert mesh # Type checker. if not materials_updated: diff --git a/src/bonsai/bonsai/tool/loader.py b/src/bonsai/bonsai/tool/loader.py index cd7e0471ec..c40adddf00 100644 --- a/src/bonsai/bonsai/tool/loader.py +++ b/src/bonsai/bonsai/tool/loader.py @@ -929,13 +929,14 @@ class Loader(bonsai.core.tool.Loader): @classmethod def apply_blender_offset_to_matrix_world(cls, obj: bpy.types.Object, matrix: np.ndarray) -> Matrix: + """ + :param matrix: 4x4 numpy matrix. + """ + # Shouldn't mutate original matrix as we return a different object anyway. + M_TRANSLATION = (slice(0, 3), 3) oprops = tool.Blender.get_object_bim_props(obj) - if ( - not obj.data - and tool.Cad.is_x(matrix[0][3], 0) - and tool.Cad.is_x(matrix[1][3], 0) - and tool.Cad.is_x(matrix[2][3], 0) - ): + translation = matrix[M_TRANSLATION] + if not obj.data and np.allclose(translation, 0.0, atol=1e-5): # We assume any non-geometric matrix at 0,0,0 is not # positionally significant and is left alone. This handles # scenarios where often spatial elements are left at 0,0,0 and @@ -947,11 +948,10 @@ class Loader(bonsai.core.tool.Loader): oprops.blender_offset_type = "CARTESIAN_POINT" if cartesian_point_offset := obj.data.get("cartesian_point_offset", None): oprops.cartesian_point_offset = cartesian_point_offset + matrix = matrix.copy() offset_xyz = list(map(float, cartesian_point_offset.split(","))) + [1.0] offset_xyz = matrix @ offset_xyz - matrix[0][3] = offset_xyz[0] - matrix[1][3] = offset_xyz[1] - matrix[2][3] = offset_xyz[2] + matrix[M_TRANSLATION] = offset_xyz[:3] props = tool.Georeference.get_georeference_props() if props.has_blender_offset: