Purge usage of mathutils in grid API functions

The only thing left is add_representation which is Blender specific
anyway and is slowly being refactored out.
This commit is contained in:
Dion Moult
2025-02-16 08:20:59 +11:00
parent aff90e89f7
commit 774a770c48
7 changed files with 46 additions and 78 deletions
@@ -26,32 +26,20 @@ geometry extrusions).
from .. import wrap_usecases
from .add_axis_representation import add_axis_representation
from .add_boolean import add_boolean
try:
from .add_door_representation import add_door_representation
except ModuleNotFoundError as e:
print(f"Note: API not available due to missing dependencies: geometry.add_door_representation - {e}")
from .add_door_representation import add_door_representation
from .add_footprint_representation import add_footprint_representation
from .add_mesh_representation import add_mesh_representation
from .add_profile_representation import add_profile_representation
try:
from .add_railing_representation import add_railing_representation
except ModuleNotFoundError as e:
print(f"Note: API not available due to missing dependencies: geometry.add_railing_representation - {e}")
from .add_railing_representation import add_railing_representation
try:
from .add_representation import add_representation
except ModuleNotFoundError as e:
print(f"Note: API not available due to missing dependencies: geometry.add_representation - {e}")
except ModuleNotFoundError:
pass # Silently fail. This is Blender / Bonsai specific and on its way out.
from .add_shape_aspect import add_shape_aspect
from .add_slab_representation import add_slab_representation
from .add_wall_representation import add_wall_representation
try:
from .add_window_representation import add_window_representation
except ModuleNotFoundError as e:
print(f"Note: API not available due to missing dependencies: geometry.add_window_representation - {e}")
from .add_window_representation import add_window_representation
from .assign_representation import assign_representation
from .connect_element import connect_element
from .connect_path import connect_path
@@ -23,10 +23,7 @@ A grid in IFC may contain two or more axes running in two or more directions.
from .. import wrap_usecases
try:
from .create_axis_curve import create_axis_curve
except ModuleNotFoundError as e:
print(f"Note: API not available due to missing dependencies: grid.create_axis_curve - {e}")
from .create_axis_curve import create_axis_curve
from .create_grid_axis import create_grid_axis
from .remove_grid_axis import remove_grid_axis
@@ -21,27 +21,26 @@ import ifcopenshell
import ifcopenshell.util.element
import ifcopenshell.util.unit
import ifcopenshell.util.placement
from mathutils import Matrix # For now, we depend on Blender
import bpy.types
import numpy as np
def create_axis_curve(
file: ifcopenshell.file, axis_curve: bpy.types.Object, grid_axis: ifcopenshell.entity_instance
file: ifcopenshell.file,
*,
p1: np.ndarray,
p2: np.ndarray,
grid_axis: ifcopenshell.entity_instance,
is_si: bool = True,
) -> None:
"""Adds curve geometry to a grid axis to represent the axis extents
This currently depends on the Blender geometry kernel to function.
An IFC grid will have a minimum of two axes (typically perpendicular). Each
axis will then have a line which represents the extents of the axis.
:param axis_curve: The Blender object that contains a mesh data block with a
single edge.
:type axis_curve: bpy.types.Object
:param p1: The first point of the grid axis
:param p2: The second point of the grid axis
:param grid_axis: The IfcGridAxis element to add geometry to.
:type grid_axis: ifcopenshell.entity_instance
:return: None
:rtype: None
:param is_si: If true, the points are in meters, not project units
Example:
@@ -54,48 +53,27 @@ def create_axis_curve(
axis_1 = ifcopenshell.api.grid.create_grid_axis(model,
axis_tag="1", uvw_axes="VAxes", grid=grid)
# Assume you have these Blender objects in your active Blender session
obj1 = bpy.data.objects.get("AxisA")
obj2 = bpy.data.objects.get("Axis1")
ifcopenshell.api.grid.create_axis_curve(model, axis_curve=obj1, grid_axis=axis_a)
ifcopenshell.api.grid.create_axis_curve(model, axis_curve=obj2, grid_axis=axis_1)
# By convention, alphabetic grids are horizontal, and numeric are vertical
ifcopenshell.api.grid.create_axis_curve(
model, p1=np.array((0., 0., 0.)), p2=np.array((10., 0., 0.)), grid_axis=axis_a)
ifcopenshell.api.grid.create_axis_curve(
model, p1=np.array((0., 0., 0.)), p2=np.array((0., 10., 0.)), grid_axis=axis_1)
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {
"axis_curve": axis_curve, # A Blender object
"grid_axis": grid_axis,
}
return usecase.execute()
existing_curve = grid_axis.AxisCurve
if is_si:
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file)
p1 /= unit_scale
p2 /= unit_scale
class Usecase:
def execute(self):
existing_curve = self.settings["grid_axis"].AxisCurve
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
grid = [i for i in self.file.get_inverse(self.settings["grid_axis"]) if i.is_a("IfcGrid")][0]
grid_matrix_i = Matrix(ifcopenshell.util.placement.get_local_placement(grid.ObjectPlacement))
grid_matrix_i.translation *= self.settings["unit_scale"]
grid_matrix_i = grid_matrix_i.inverted()
points = [
grid_matrix_i @ (self.settings["axis_curve"].matrix_world @ v.co)
for v in self.settings["axis_curve"].data.vertices[0:2]
]
self.settings["grid_axis"].AxisCurve = self.file.createIfcPolyline(
[
self.create_cartesian_point(points[0][0], points[0][1]),
self.create_cartesian_point(points[1][0], points[1][1]),
]
grid = [i for i in file.get_inverse(grid_axis) if i.is_a("IfcGrid")][0]
grid_matrix_i = np.linalg.inv(ifcopenshell.util.placement.get_local_placement(grid.ObjectPlacement))
grid_axis.AxisCurve = file.createIfcPolyline(
(
file.createIfcCartesianPoint((grid_matrix_i @ p1).tolist()),
file.createIfcCartesianPoint((grid_matrix_i @ p2).tolist()),
)
)
if existing_curve:
ifcopenshell.util.element.remove_deep2(self.file, existing_curve)
def create_cartesian_point(self, x, y):
x = self.convert_si_to_unit(x)
y = self.convert_si_to_unit(y)
return self.file.createIfcCartesianPoint((x, y))
def convert_si_to_unit(self, co):
return co / self.settings["unit_scale"]
if existing_curve:
ifcopenshell.util.element.remove_deep2(file, existing_curve)