Reuse builder.create_axis2_placement_3d

This commit is contained in:
Andrej730
2025-09-04 10:58:04 +05:00
parent 90e6838ddb
commit 8c12bd0322
8 changed files with 35 additions and 77 deletions
@@ -40,6 +40,7 @@ from mathutils import Vector, Matrix
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.model.decorator import ProfileDecorator from bonsai.bim.module.model.decorator import ProfileDecorator
from bonsai.bim.module.boundary.decorator import BoundaryDecorator from bonsai.bim.module.boundary.decorator import BoundaryDecorator
from ifcopenshell.util.shape_builder import ShapeBuilder
import bonsai.core import bonsai.core
import bonsai.core.geometry import bonsai.core.geometry
from typing import Union, Optional from typing import Union, Optional
@@ -1058,15 +1059,11 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
tool.Model.unit_scale = self.unit_scale tool.Model.unit_scale = self.unit_scale
builder = ShapeBuilder(tool.Ifc.get())
surface = tool.Ifc.get().createIfcCurveBoundedPlane() surface = tool.Ifc.get().createIfcCurveBoundedPlane()
surface.BasisSurface = tool.Ifc.get().createIfcPlane( placement = builder.create_axis2_placement_3d([o / self.unit_scale for o in p1], z_axis, x_axis)
tool.Ifc.get().createIfcAxis2Placement3D( surface.BasisSurface = tool.Ifc.get().create_entity("IfcPlane", placement)
tool.Ifc.get().createIfcCartesianPoint([o / self.unit_scale for o in p1]),
tool.Ifc.get().createIfcDirection([float(o) for o in z_axis]),
tool.Ifc.get().createIfcDirection([float(o) for o in x_axis]),
)
)
if tool.Ifc.get().schema != "IFC2X3": if tool.Ifc.get().schema != "IFC2X3":
points = [tool.Model.convert_si_to_unit(list(co)) for co in polygon.exterior.coords] points = [tool.Model.convert_si_to_unit(list(co)) for co in polygon.exterior.coords]
@@ -28,6 +28,7 @@ import bonsai.tool as tool
from math import pi, pow from math import pi, pow
from mathutils import Vector, Matrix, geometry from mathutils import Vector, Matrix, geometry
from typing import Union, Any, TypeVar, Optional from typing import Union, Any, TypeVar, Optional
from ifcopenshell.util.shape_builder import ShapeBuilder
T = TypeVar("T") T = TypeVar("T")
@@ -35,6 +36,7 @@ T = TypeVar("T")
class Helper: class Helper:
def __init__(self, file: ifcopenshell.file): def __init__(self, file: ifcopenshell.file):
self.file = file self.file = file
self.builder = ShapeBuilder(file)
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file) self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
# We can detect a rectangular extrusion by picking any face, then find an # We can detect a rectangular extrusion by picking any face, then find an
@@ -340,8 +342,10 @@ class Helper:
def create_extruded_area_solid( def create_extruded_area_solid(
self, mesh: bpy.types.Mesh, extrusion_indices: list[int], profile_def: dict[str, Any] self, mesh: bpy.types.Mesh, extrusion_indices: list[int], profile_def: dict[str, Any]
) -> ifcopenshell.entity_instance: ) -> ifcopenshell.entity_instance:
position = self.create_ifc_axis_2_placement_3d( position = self.builder.create_axis2_placement_3d(
profile_def["curve_ucs"]["center"], profile_def["curve_ucs"]["z_axis"], profile_def["curve_ucs"]["x_axis"] self.convert_si_to_unit(profile_def["curve_ucs"]["center"]),
profile_def["curve_ucs"]["z_axis"],
profile_def["curve_ucs"]["x_axis"],
) )
direction = self.get_extrusion_direction(mesh, extrusion_indices, profile_def["curve_ucs"]) direction = self.get_extrusion_direction(mesh, extrusion_indices, profile_def["curve_ucs"])
unit_direction = direction.normalized() unit_direction = direction.normalized()
@@ -505,12 +509,3 @@ class Helper:
return self.file.createIfcAxis2Placement2D( return self.file.createIfcAxis2Placement2D(
self.create_cartesian_point(point.x, point.y), self.file.createIfcDirection((forward.x, forward.y)) self.create_cartesian_point(point.x, point.y), self.file.createIfcDirection((forward.x, forward.y))
) )
def create_ifc_axis_2_placement_3d(
self, point: Vector, up: Vector, forward: Vector
) -> ifcopenshell.entity_instance:
return self.file.createIfcAxis2Placement3D(
self.create_cartesian_point(point.x, point.y, point.z),
self.file.createIfcDirection((up.x, up.y, up.z)),
self.file.createIfcDirection((forward.x, forward.y, forward.z)),
)
+3 -5
View File
@@ -58,6 +58,7 @@ from fractions import Fraction
from typing import Optional, Union, Any, Literal, TYPE_CHECKING, NamedTuple from typing import Optional, Union, Any, Literal, TYPE_CHECKING, NamedTuple
from collections.abc import Iterable, Sequence from collections.abc import Iterable, Sequence
from pathlib import Path from pathlib import Path
from ifcopenshell.util.shape_builder import ShapeBuilder
if TYPE_CHECKING: if TYPE_CHECKING:
from bonsai.bim.module.drawing.prop import ( from bonsai.bim.module.drawing.prop import (
@@ -778,11 +779,8 @@ class Drawing(bonsai.core.tool.Drawing):
@classmethod @classmethod
def add_literal(cls, **attributes: str) -> ifcopenshell.entity_instance: def add_literal(cls, **attributes: str) -> ifcopenshell.entity_instance:
ifc_file = tool.Ifc.get() ifc_file = tool.Ifc.get()
origin = ifc_file.createIfcAxis2Placement3D( builder = ShapeBuilder(ifc_file)
ifc_file.createIfcCartesianPoint((0.0, 0.0, 0.0)), origin = builder.create_axis2_placement_3d()
ifc_file.createIfcDirection((0.0, 0.0, 1.0)),
ifc_file.createIfcDirection((1.0, 0.0, 0.0)),
)
ifc_literal = ifc_file.create_entity( ifc_literal = ifc_file.create_entity(
"IfcTextLiteralWithExtent", "IfcTextLiteralWithExtent",
attributes.get("Literal", "Literal"), attributes.get("Literal", "Literal"),
+6 -14
View File
@@ -238,6 +238,8 @@ class Model(bonsai.core.tool.Model):
@classmethod @classmethod
def export_surface(cls, obj: bpy.types.Object) -> Union[ifcopenshell.entity_instance, None]: def export_surface(cls, obj: bpy.types.Object) -> Union[ifcopenshell.entity_instance, None]:
ifc_file = tool.Ifc.get()
builder = ShapeBuilder(ifc_file)
p1, p2, p3 = [v.co.copy() for v in obj.data.vertices[0:3]] p1, p2, p3 = [v.co.copy() for v in obj.data.vertices[0:3]]
edge1 = p2 - p1 edge1 = p2 - p1
@@ -271,13 +273,8 @@ class Model(bonsai.core.tool.Model):
cls.bm.edges.ensure_lookup_table() cls.bm.edges.ensure_lookup_table()
surface = tool.Ifc.get().createIfcCurveBoundedPlane() surface = tool.Ifc.get().createIfcCurveBoundedPlane()
surface.BasisSurface = tool.Ifc.get().createIfcPlane( placement = builder.create_axis2_placement_3d([o / cls.unit_scale for o in p1], z_axis, x_axis)
tool.Ifc.get().createIfcAxis2Placement3D( surface.BasisSurface = ifc_file.create_entity("IfcPlane", placement)
tool.Ifc.get().createIfcCartesianPoint([o / cls.unit_scale for o in p1]),
tool.Ifc.get().createIfcDirection([float(o) for o in z_axis]),
tool.Ifc.get().createIfcDirection([float(o) for o in x_axis]),
)
)
surface.OuterBoundary = tool.Ifc.get().add(profile_def.OuterCurve) surface.OuterBoundary = tool.Ifc.get().add(profile_def.OuterCurve)
if profile_def.is_a("IfcArbitraryProfileDefWithVoids"): if profile_def.is_a("IfcArbitraryProfileDefWithVoids"):
@@ -2124,13 +2121,8 @@ class Model(bonsai.core.tool.Model):
@classmethod @classmethod
def add_extrusion_position(cls, extrusion: ifcopenshell.entity_instance, position: Vector) -> None: def add_extrusion_position(cls, extrusion: ifcopenshell.entity_instance, position: Vector) -> None:
ifc_file = tool.Ifc.get() ifc_file = tool.Ifc.get()
builder = ShapeBuilder(ifc_file)
new_position = ifc_file.createIfcAxis2Placement3D( new_position = builder.create_axis2_placement_3d(position)
ifc_file.createIfcCartesianPoint(position),
ifc_file.createIfcDirection((0.0, 0.0, 1.0)),
ifc_file.createIfcDirection((1.0, 0.0, 0.0)),
)
extrusion.Position = new_position extrusion.Position = new_position
@classmethod @classmethod
@@ -22,6 +22,7 @@ import ifcopenshell.api.owner
import ifcopenshell.util.unit import ifcopenshell.util.unit
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.placement import ifcopenshell.util.placement
from ifcopenshell.util.shape_builder import ShapeBuilder
from typing import Optional, Union, Any from typing import Optional, Union, Any
NPArrayOfFloats = npt.NDArray[np.float64] NPArrayOfFloats = npt.NDArray[np.float64]
@@ -74,6 +75,7 @@ class Usecase:
if not hasattr(self.settings["product"], "ObjectPlacement"): if not hasattr(self.settings["product"], "ObjectPlacement"):
return return
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file) self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
self.builder = ShapeBuilder(self.file)
if not self.settings["is_si"]: if not self.settings["is_si"]:
self.convert_matrix_to_si(self.settings["matrix"]) self.convert_matrix_to_si(self.settings["matrix"])
@@ -183,25 +185,12 @@ class Usecase:
o = np.array((m[0][3], m[1][3], m[2][3])) o = np.array((m[0][3], m[1][3], m[2][3]))
object_matrix = ifcopenshell.util.placement.a2p(o, z, x) object_matrix = ifcopenshell.util.placement.a2p(o, z, x)
relative_placement_matrix = np.linalg.inv(relating_object_matrix) @ object_matrix relative_placement_matrix = np.linalg.inv(relating_object_matrix) @ object_matrix
return self.create_ifc_axis_2_placement_3d( return self.builder.create_axis2_placement_3d(
relative_placement_matrix[:, 3][0:3], self.convert_si_to_unit(relative_placement_matrix[:, 3][0:3]),
relative_placement_matrix[:, 2][0:3], relative_placement_matrix[:, 2][0:3],
relative_placement_matrix[:, 0][0:3], relative_placement_matrix[:, 0][0:3],
) )
def create_ifc_axis_2_placement_3d(
self, point: NPArrayOfFloats, up: NPArrayOfFloats, forward: NPArrayOfFloats
) -> ifcopenshell.entity_instance:
return self.file.createIfcAxis2Placement3D(
self.create_cartesian_point(point),
self.file.createIfcDirection(up.tolist()),
self.file.createIfcDirection(forward.tolist()),
)
def create_cartesian_point(self, co: NPArrayOfFloats) -> ifcopenshell.entity_instance:
co = self.convert_si_to_unit(co)
return self.file.createIfcCartesianPoint(co.tolist())
def convert_si_to_unit(self, co: NPArrayOfFloats) -> NPArrayOfFloats: def convert_si_to_unit(self, co: NPArrayOfFloats) -> NPArrayOfFloats:
return co / self.unit_scale return co / self.unit_scale
@@ -18,9 +18,9 @@
import ifcopenshell import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.geolocation
import ifcopenshell.util.unit import ifcopenshell.util.unit
import numpy as np import numpy as np
from ifcopenshell.util.shape_builder import ShapeBuilder
from math import sin, cos, radians from math import sin, cos, radians
@@ -62,6 +62,7 @@ def edit_wcs(
ifcopenshell.api.georeference.edit_wcs(model) ifcopenshell.api.georeference.edit_wcs(model)
""" """
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file) unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file)
builder = ShapeBuilder(file)
if np.isclose(rotation, 0): if np.isclose(rotation, 0):
xaxis_x = 1.0 xaxis_x = 1.0
xaxis_y = 0.0 xaxis_y = 0.0
@@ -74,14 +75,10 @@ def edit_wcs(
old_wcs = context.WorldCoordinateSystem old_wcs = context.WorldCoordinateSystem
if context.CoordinateSpaceDimension == 3: if context.CoordinateSpaceDimension == 3:
if is_si: if is_si:
point = file.createIfcCartesianPoint((x / unit_scale, y / unit_scale, z / unit_scale)) xyz = (x / unit_scale, y / unit_scale, z / unit_scale)
else: else:
point = file.createIfcCartesianPoint((x, y, z)) xyz = (x, y, z)
placement = file.createIfcAxis2Placement3D( placement = builder.create_axis2_placement_3d(xyz, (0.0, 0.0, 1.0), (xaxis_x, xaxis_y, 0.0))
point,
file.createIfcDirection((0.0, 0.0, 1.0)),
file.createIfcDirection((xaxis_x, xaxis_y, 0.0)),
)
elif context.CoordinateSpaceDimension == 2: elif context.CoordinateSpaceDimension == 2:
if is_si: if is_si:
point = file.createIfcCartesianPoint((x / unit_scale, y / unit_scale)) point = file.createIfcCartesianPoint((x / unit_scale, y / unit_scale))
@@ -21,6 +21,7 @@ import numpy as np
import ifcopenshell import ifcopenshell
from typing import Any, Union from typing import Any, Union
from dataclasses import dataclass from dataclasses import dataclass
from ifcopenshell.util.shape_builder import ShapeBuilder
@dataclass @dataclass
@@ -78,9 +79,7 @@ class Clipping:
if not ifc_file: if not ifc_file:
ifc_file = first_operand.file ifc_file = first_operand.file
builder = ShapeBuilder(ifc_file)
location = ifc_file.createIfcCartesianPoint([i / unit_scale for i in self.location])
direction = ifc_file.createIfcDirection(self.normal)
normal = np.array(self.normal) normal = np.array(self.normal)
if np.allclose(normal, np.array([0.0, 0.0, 1.0]), atol=1e-2) or np.allclose( if np.allclose(normal, np.array([0.0, 0.0, 1.0]), atol=1e-2) or np.allclose(
@@ -92,9 +91,9 @@ class Clipping:
x_axis = np.cross(normal, arbitrary_vector) x_axis = np.cross(normal, arbitrary_vector)
x_axis /= np.linalg.norm(x_axis) x_axis /= np.linalg.norm(x_axis)
x_axis = ifc_file.createIfcDirection(x_axis.tolist())
plane = ifc_file.createIfcPlane(ifc_file.createIfcAxis2Placement3D(location, direction, x_axis)) placement = builder.create_axis2_placement_3d([i / unit_scale for i in self.location], self.normal, x_axis)
plane = ifc_file.create_entity("IfcPlane", placement)
second_operand = ifc_file.createIfcHalfSpaceSolid(plane, False) second_operand = ifc_file.createIfcHalfSpaceSolid(plane, False)
return ifc_file.createIfcBooleanClippingResult("DIFFERENCE", first_operand, second_operand) return ifc_file.createIfcBooleanClippingResult("DIFFERENCE", first_operand, second_operand)
@@ -21,6 +21,7 @@ import numpy as np
import ifcopenshell import ifcopenshell
import ifcopenshell.util.placement import ifcopenshell.util.placement
import typing import typing
from ifcopenshell.util.shape_builder import ShapeBuilder
class Patcher: class Patcher:
@@ -97,6 +98,7 @@ class Patcher:
self.ax = None self.ax = None
self.ay = None self.ay = None
self.az = None self.az = None
self.builder = ShapeBuilder(file)
try: try:
self.ax = float(ax) self.ax = float(ax)
@@ -183,15 +185,4 @@ class Patcher:
z = np.array((m[0][2], m[1][2], m[2][2])) z = np.array((m[0][2], m[1][2], m[2][2]))
o = np.array((m[0][3], m[1][3], m[2][3])) o = np.array((m[0][3], m[1][3], m[2][3]))
object_matrix = ifcopenshell.util.placement.a2p(o, z, x) object_matrix = ifcopenshell.util.placement.a2p(o, z, x)
return self.create_ifc_axis_2_placement_3d( return self.builder.create_axis2_placement_3d_from_matrix(object_matrix)
object_matrix[:, 3][0:3],
object_matrix[:, 2][0:3],
object_matrix[:, 0][0:3],
)
def create_ifc_axis_2_placement_3d(self, point, up, forward):
return self.file.createIfcAxis2Placement3D(
self.file.createIfcCartesianPoint(point.tolist()),
self.file.createIfcDirection(up.tolist()),
self.file.createIfcDirection(forward.tolist()),
)