mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Fix error applying blender offset to read-only matrix (e.g. during linking)
Example:
```
File "\bonsai\bim\module\project\operator.py", line 1815, in execute
self.process_occurrence(shape)
File "\bonsai\bim\module\project\operator.py", line 1952, in process_occurrence
obj.matrix_world = tool.Loader.apply_blender_offset_to_matrix_world(obj, mat)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\bonsai\tool\loader.py", line 952, in apply_blender_offset_to_matrix_world
matrix[0][3] = offset_xyz[0]
~~~~~~~~~^^^
ValueError: assignment destination is read-only
```
Noticed investigating #6242
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user