add_representation - use numpy arrays for calculations that include model offset

This commit is contained in:
Andrej730
2025-02-11 18:12:58 +05:00
parent 45e36590eb
commit f6087613f0
@@ -21,8 +21,11 @@ import math
import bmesh import bmesh
import ifcopenshell.util.shape_builder import ifcopenshell.util.shape_builder
import ifcopenshell.util.unit import ifcopenshell.util.unit
import numpy as np
import numpy.typing as npt
from mathutils import Vector, Matrix from mathutils import Vector, Matrix
from typing import Union, Optional, Literal, Any, TYPE_CHECKING from typing import Union, Optional, Literal, Any, TYPE_CHECKING
from ifcopenshell.util.shape_builder import ifc_safe_vector_type, VectorType
if TYPE_CHECKING: if TYPE_CHECKING:
from bonsai.bim.module.geometry.helper import Helper from bonsai.bim.module.geometry.helper import Helper
@@ -39,7 +42,7 @@ def add_representation(
context: ifcopenshell.entity_instance, context: ifcopenshell.entity_instance,
blender_object: bpy.types.Object, blender_object: bpy.types.Object,
geometry: Union[bpy.types.Mesh, bpy.types.Curve], geometry: Union[bpy.types.Mesh, bpy.types.Curve],
coordinate_offset: Optional[Vector] = None, coordinate_offset: Optional[npt.NDArray[np.float64]] = None,
total_items: int = 1, total_items: int = 1,
unit_scale: Optional[float] = None, unit_scale: Optional[float] = None,
should_force_faceted_brep: bool = False, should_force_faceted_brep: bool = False,
@@ -89,7 +92,7 @@ def add_representation(
"context": context, "context": context,
"blender_object": blender_object, "blender_object": blender_object,
"geometry": geometry, "geometry": geometry,
"coordinate_offset": Vector(coordinate_offset) if coordinate_offset is not None else None, "coordinate_offset": coordinate_offset if coordinate_offset is not None else None,
"total_items": total_items, "total_items": total_items,
"unit_scale": unit_scale, "unit_scale": unit_scale,
"should_force_faceted_brep": should_force_faceted_brep, "should_force_faceted_brep": should_force_faceted_brep,
@@ -107,9 +110,11 @@ class Usecase:
file: ifcopenshell.file file: ifcopenshell.file
settings: dict[str, Any] settings: dict[str, Any]
ifc_vertices: list[ifcopenshell.entity_instance] ifc_vertices: list[ifcopenshell.entity_instance]
coordinate_offset: Union[npt.NDArray[np.float64], None]
def execute(self) -> Union[ifcopenshell.entity_instance, None]: def execute(self) -> Union[ifcopenshell.entity_instance, None]:
self.is_manifold = None self.is_manifold = None
self.coordinate_offset = self.settings["coordinate_offset"]
if ( if (
isinstance(self.settings["geometry"], bpy.types.Mesh) isinstance(self.settings["geometry"], bpy.types.Mesh)
and self.settings["geometry"] == self.settings["blender_object"].data and self.settings["geometry"] == self.settings["blender_object"].data
@@ -868,11 +873,11 @@ class Usecase:
x, y, z coords are provided in SI units. x, y, z coords are provided in SI units.
""" """
if is_model_coords and self.settings["coordinate_offset"]: if is_model_coords and self.coordinate_offset is not None:
x += self.settings["coordinate_offset"][0] x += self.coordinate_offset[0]
y += self.settings["coordinate_offset"][1] y += self.coordinate_offset[1]
if z is not None: if z is not None:
z += self.settings["coordinate_offset"][2] z += self.coordinate_offset[2]
x = self.convert_si_to_unit(x) x = self.convert_si_to_unit(x)
y = self.convert_si_to_unit(y) y = self.convert_si_to_unit(y)
if z is None: if z is None:
@@ -881,21 +886,26 @@ class Usecase:
return self.file.createIfcCartesianPoint((x, y, z)) return self.file.createIfcCartesianPoint((x, y, z))
def create_cartesian_point_list_from_vertices( def create_cartesian_point_list_from_vertices(
self, vertices: list[bpy.types.MeshVertex], is_2d: bool = False, is_model_coords: bool = True self, vertices: bpy.types.MeshVertices, is_2d: bool = False, is_model_coords: bool = True
) -> ifcopenshell.entity_instance: ) -> ifcopenshell.entity_instance:
if is_model_coords and self.settings["coordinate_offset"]: # Catch values as floats to benefit from fast buffer copy.
if is_2d: coords = np.empty(len(vertices) * 3, dtype="f")
xy_offset = Vector((self.settings["coordinate_offset"][0:2])) vertices.foreach_get("co", coords)
return self.file.createIfcCartesianPointList2D( coords = coords.reshape(-1, 3)
[self.convert_si_to_unit(v.co.xy + xy_offset) for v in vertices]
)
xyz_offset = Vector((self.settings["coordinate_offset"][0:3]))
return self.file.createIfcCartesianPointList3D(
[self.convert_si_to_unit(v.co.xyz + xyz_offset) for v in vertices]
)
if is_2d: if is_2d:
return self.file.createIfcCartesianPointList2D([self.convert_si_to_unit(v.co.xy) for v in vertices]) coords = coords[:, :2]
return self.file.createIfcCartesianPointList3D([self.convert_si_to_unit(v.co) for v in vertices]) coords_class = "IfcCartesianPointList2D"
else:
coords_class = "IfcCartesianPointList3D"
if is_model_coords and (offset := self.coordinate_offset) is not None:
coords = coords.astype("d")
if is_2d:
offset = offset[:2]
coords += offset
return self.file.create_entity(coords_class, ifc_safe_vector_type(self.convert_si_to_unit(coords)))
def convert_si_to_unit(self, co): def convert_si_to_unit(self, co):
return co / self.settings["unit_scale"] return co / self.settings["unit_scale"]