mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
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:
@@ -474,7 +474,7 @@ class UpdateRepresentation(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
if product.is_a("IfcGridAxis"):
|
if product.is_a("IfcGridAxis"):
|
||||||
# Grid geometry does not follow the "representation" paradigm and needs to be treated specially
|
# Grid geometry does not follow the "representation" paradigm and needs to be treated specially
|
||||||
ifcopenshell.api.grid.create_axis_curve(self.file, axis_curve=obj, grid_axis=product)
|
tool.Model.create_axis_curve(obj, product)
|
||||||
return
|
return
|
||||||
elif product.is_a("IfcRelSpaceBoundary"):
|
elif product.is_a("IfcRelSpaceBoundary"):
|
||||||
# TODO refactor
|
# TODO refactor
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ def add_object(self, context):
|
|||||||
"grid.create_grid_axis", tool.Ifc.get(), axis_tag=tag, uvw_axes="UAxes", grid=grid
|
"grid.create_grid_axis", tool.Ifc.get(), axis_tag=tag, uvw_axes="UAxes", grid=grid
|
||||||
)
|
)
|
||||||
tool.Ifc.link(result, obj)
|
tool.Ifc.link(result, obj)
|
||||||
ifcopenshell.api.run("grid.create_axis_curve", tool.Ifc.get(), axis_curve=obj, grid_axis=result)
|
tool.Model.create_axis_curve(obj, result)
|
||||||
tool.Collector.assign(obj)
|
tool.Collector.assign(obj)
|
||||||
|
|
||||||
for i in range(0, self.total_v):
|
for i in range(0, self.total_v):
|
||||||
@@ -69,7 +69,7 @@ def add_object(self, context):
|
|||||||
"grid.create_grid_axis", tool.Ifc.get(), axis_tag=tag, uvw_axes="VAxes", grid=grid
|
"grid.create_grid_axis", tool.Ifc.get(), axis_tag=tag, uvw_axes="VAxes", grid=grid
|
||||||
)
|
)
|
||||||
tool.Ifc.link(result, obj)
|
tool.Ifc.link(result, obj)
|
||||||
ifcopenshell.api.run("grid.create_axis_curve", tool.Ifc.get(), axis_curve=obj, grid_axis=result)
|
tool.Model.create_axis_curve(obj, result)
|
||||||
tool.Collector.assign(obj)
|
tool.Collector.assign(obj)
|
||||||
|
|
||||||
tool.Root.reload_grid_decorator()
|
tool.Root.reload_grid_decorator()
|
||||||
|
|||||||
@@ -1978,3 +1978,11 @@ class Model(bonsai.core.tool.Model):
|
|||||||
x_angle = Vector((0, 1)).angle_signed(Vector((y, z)))
|
x_angle = Vector((0, 1)).angle_signed(Vector((y, z)))
|
||||||
|
|
||||||
return x_angle
|
return x_angle
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_axis_curve(cls, obj: bpy.types.Object, grid_axis: ifcopenshell.entity_instance):
|
||||||
|
m = tool.Surveyor.get_absolute_matrix(obj)
|
||||||
|
points = [m @ np.array(v.co.to_4d()) for v in obj.data.vertices[0:2]]
|
||||||
|
ifcopenshell.api.grid.create_axis_curve(
|
||||||
|
tool.Ifc.get(), p1=points[0], p2=points[1], is_si=True, grid_axis=grid_axis
|
||||||
|
)
|
||||||
|
|||||||
@@ -26,32 +26,20 @@ geometry extrusions).
|
|||||||
from .. import wrap_usecases
|
from .. import wrap_usecases
|
||||||
from .add_axis_representation import add_axis_representation
|
from .add_axis_representation import add_axis_representation
|
||||||
from .add_boolean import add_boolean
|
from .add_boolean import add_boolean
|
||||||
|
from .add_door_representation import add_door_representation
|
||||||
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_footprint_representation import add_footprint_representation
|
from .add_footprint_representation import add_footprint_representation
|
||||||
from .add_mesh_representation import add_mesh_representation
|
from .add_mesh_representation import add_mesh_representation
|
||||||
from .add_profile_representation import add_profile_representation
|
from .add_profile_representation import add_profile_representation
|
||||||
|
from .add_railing_representation import add_railing_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}")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from .add_representation import add_representation
|
from .add_representation import add_representation
|
||||||
except ModuleNotFoundError as e:
|
except ModuleNotFoundError:
|
||||||
print(f"Note: API not available due to missing dependencies: geometry.add_representation - {e}")
|
pass # Silently fail. This is Blender / Bonsai specific and on its way out.
|
||||||
from .add_shape_aspect import add_shape_aspect
|
from .add_shape_aspect import add_shape_aspect
|
||||||
from .add_slab_representation import add_slab_representation
|
from .add_slab_representation import add_slab_representation
|
||||||
from .add_wall_representation import add_wall_representation
|
from .add_wall_representation import add_wall_representation
|
||||||
|
from .add_window_representation import add_window_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 .assign_representation import assign_representation
|
from .assign_representation import assign_representation
|
||||||
from .connect_element import connect_element
|
from .connect_element import connect_element
|
||||||
from .connect_path import connect_path
|
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
|
from .. import wrap_usecases
|
||||||
|
|
||||||
try:
|
from .create_axis_curve import create_axis_curve
|
||||||
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_grid_axis import create_grid_axis
|
from .create_grid_axis import create_grid_axis
|
||||||
from .remove_grid_axis import remove_grid_axis
|
from .remove_grid_axis import remove_grid_axis
|
||||||
|
|
||||||
|
|||||||
@@ -21,27 +21,26 @@ import ifcopenshell
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
import ifcopenshell.util.placement
|
import ifcopenshell.util.placement
|
||||||
from mathutils import Matrix # For now, we depend on Blender
|
import numpy as np
|
||||||
import bpy.types
|
|
||||||
|
|
||||||
|
|
||||||
def create_axis_curve(
|
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:
|
) -> None:
|
||||||
"""Adds curve geometry to a grid axis to represent the axis extents
|
"""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
|
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.
|
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
|
:param p1: The first point of the grid axis
|
||||||
single edge.
|
:param p2: The second point of the grid axis
|
||||||
:type axis_curve: bpy.types.Object
|
|
||||||
:param grid_axis: The IfcGridAxis element to add geometry to.
|
:param grid_axis: The IfcGridAxis element to add geometry to.
|
||||||
:type grid_axis: ifcopenshell.entity_instance
|
:param is_si: If true, the points are in meters, not project units
|
||||||
:return: None
|
|
||||||
:rtype: None
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -54,48 +53,27 @@ def create_axis_curve(
|
|||||||
axis_1 = ifcopenshell.api.grid.create_grid_axis(model,
|
axis_1 = ifcopenshell.api.grid.create_grid_axis(model,
|
||||||
axis_tag="1", uvw_axes="VAxes", grid=grid)
|
axis_tag="1", uvw_axes="VAxes", grid=grid)
|
||||||
|
|
||||||
# Assume you have these Blender objects in your active Blender session
|
# By convention, alphabetic grids are horizontal, and numeric are vertical
|
||||||
obj1 = bpy.data.objects.get("AxisA")
|
ifcopenshell.api.grid.create_axis_curve(
|
||||||
obj2 = bpy.data.objects.get("Axis1")
|
model, p1=np.array((0., 0., 0.)), p2=np.array((10., 0., 0.)), grid_axis=axis_a)
|
||||||
ifcopenshell.api.grid.create_axis_curve(model, axis_curve=obj1, grid_axis=axis_a)
|
ifcopenshell.api.grid.create_axis_curve(
|
||||||
ifcopenshell.api.grid.create_axis_curve(model, axis_curve=obj2, grid_axis=axis_1)
|
model, p1=np.array((0., 0., 0.)), p2=np.array((0., 10., 0.)), grid_axis=axis_1)
|
||||||
"""
|
"""
|
||||||
usecase = Usecase()
|
existing_curve = grid_axis.AxisCurve
|
||||||
usecase.file = file
|
|
||||||
usecase.settings = {
|
|
||||||
"axis_curve": axis_curve, # A Blender object
|
|
||||||
"grid_axis": grid_axis,
|
|
||||||
}
|
|
||||||
return usecase.execute()
|
|
||||||
|
|
||||||
|
if is_si:
|
||||||
|
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file)
|
||||||
|
p1 /= unit_scale
|
||||||
|
p2 /= unit_scale
|
||||||
|
|
||||||
class Usecase:
|
grid = [i for i in file.get_inverse(grid_axis) if i.is_a("IfcGrid")][0]
|
||||||
def execute(self):
|
grid_matrix_i = np.linalg.inv(ifcopenshell.util.placement.get_local_placement(grid.ObjectPlacement))
|
||||||
existing_curve = self.settings["grid_axis"].AxisCurve
|
grid_axis.AxisCurve = file.createIfcPolyline(
|
||||||
|
(
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
file.createIfcCartesianPoint((grid_matrix_i @ p1).tolist()),
|
||||||
grid = [i for i in self.file.get_inverse(self.settings["grid_axis"]) if i.is_a("IfcGrid")][0]
|
file.createIfcCartesianPoint((grid_matrix_i @ p2).tolist()),
|
||||||
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]),
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if existing_curve:
|
if existing_curve:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, existing_curve)
|
ifcopenshell.util.element.remove_deep2(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"]
|
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
# mathutils is broken on Python < 3.10.
|
|
||||||
# See: https://gitlab.com/ideasman42/blender-mathutils/-/merge_requests/3
|
|
||||||
geometry = ["mathutils"]
|
|
||||||
dev = ["pytest"]
|
dev = ["pytest"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
|||||||
Reference in New Issue
Block a user