This commit is contained in:
Andrej730
2025-02-18 15:18:23 +05:00
parent 83a351b1c7
commit 17642ca4e9
117 changed files with 683 additions and 1005 deletions
@@ -17,17 +17,20 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell.util.unit
import numpy as np
import numpy.typing as npt
from typing import Optional
from ifcopenshell.util.shape_builder import SequenceOfVectors, V, ifc_safe_vector_type
def assign_connection_geometry(
file: ifcopenshell.file,
rel_space_boundary: ifcopenshell.entity_instance,
outer_boundary: list[tuple[float, float]],
outer_boundary: SequenceOfVectors,
location: tuple[float, float, float],
axis: tuple[float, float, float],
ref_direction: tuple[float, float, float],
inner_boundaries: Optional[list[list[tuple[float, float]]]] = None,
inner_boundaries: Optional[SequenceOfVectors] = None,
unit_scale: Optional[float] = None,
) -> None:
"""Create and assign a connection geometry to a space boundary relationship
@@ -40,35 +43,28 @@ def assign_connection_geometry(
:param rel_space_boundary: The space boundary relationship to assign the
connection geometry to.
:type rel_space_boundary: ifcopenshell.entity_instance
:param outer_boundary: A list of 2D points representing an open
polyline. The last point will connect to the first point. Each
point is represented by an interable of 2 floats. The coordinates of
the points are relative to the positional matrix arguments.
:type outer_boundary: list[tuple[float, float]]
:param inner_boundaries: A list of zero or more inner boundaries to use
for the plane. Each boundary is represented by an open polyline, as
defined by the outer_boundary argument.
:type inner_boundaries: list[list[tuple[float, float]]], optional
:param location: The local origin of the connection geometry, defined as
an XYZ coordinate relative to the placement of the space that is
being bounded.
:type location: tuple[float, float, float]
:param axis: The local X axis of the connection geometry, defined as an
XYZ vector relative to the placement of the space that is being
bounded.
:type axis: tuple[float, float, float]
:param ref_direction: The local Z axis of the connection geometry,
defined as an XYZ vector relative to the placement of the space that
is being bounded. The Y vector is automatically derived using the
right hand rule.
:type ref_direction: tuple[float, float, float]
:param unit_scale: The unit scale as calculated by
ifcopenshell.util.unit.calculate_unit_scale. If not provided, it
will be automatically calculated for you.
:type unit_scale: float, optional
:return: None
:rtype: None
Example:
@@ -83,19 +79,26 @@ def assign_connection_geometry(
usecase = Usecase()
usecase.file = file
usecase.rel_space_boundary = rel_space_boundary
usecase.outer_boundary = outer_boundary
usecase.inner_boundaries = inner_boundaries or ()
usecase.location = location
usecase.axis = axis
usecase.ref_direction = ref_direction
usecase.unit_scale = unit_scale
usecase.outer_boundary = V(outer_boundary)
usecase.inner_boundaries = V(inner_boundaries or [])
usecase.location = V(location)
usecase.axis = V(axis)
usecase.ref_direction = V(ref_direction)
usecase.unit_scale = unit_scale if unit_scale is not None else ifcopenshell.util.unit.calculate_unit_scale(file)
return usecase.execute()
class Usecase:
file: ifcopenshell.file
rel_space_boundary: ifcopenshell.entity_instance
outer_boundary: npt.NDArray
inner_boundaries: npt.NDArray
location: npt.NDArray
axis: npt.NDArray
ref_direction: npt.NDArray
unit_scale: float
def execute(self):
if self.unit_scale is None:
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
outer_boundary = self.create_polyline(self.outer_boundary)
inner_boundaries = tuple(self.create_polyline(boundary) for boundary in self.inner_boundaries)
plane = self.create_plane(self.location, self.axis, self.ref_direction)
@@ -103,18 +106,23 @@ class Usecase:
connection_geometry = self.file.createIfcConnectionSurfaceGeometry(curve_bounded_plane)
self.rel_space_boundary.ConnectionGeometry = connection_geometry
def create_point(self, point):
return self.file.createIfcCartesianPoint(point / self.unit_scale)
def create_point(self, point: npt.NDArray) -> ifcopenshell.entity_instance:
return self.file.create_enitty("IfcCartesianPoint", ifc_safe_vector_type(point / self.unit_scale))
def close_polyline(self, points):
def close_polyline(
self, points: tuple[ifcopenshell.entity_instance, ...]
) -> tuple[ifcopenshell.entity_instance, ...]:
return points + (points[0],)
def create_polyline(self, points):
if points[0] == points[-1]:
def create_polyline(self, points: npt.NDArray) -> ifcopenshell.entity_instance:
if np.allclose(points[0], points[-1]):
points = points[0 : len(points) - 1]
return self.file.createIfcPolyline(self.close_polyline(tuple(self.create_point(point) for point in points)))
ifc_points = tuple(self.create_point(point) for point in points)
return self.file.createIfcPolyline(self.close_polyline(ifc_points))
def create_plane(self, location, axis, ref_direction):
def create_plane(
self, location: npt.NDArray, axis: npt.NDArray, ref_direction: npt.NDArray
) -> ifcopenshell.entity_instance:
return self.file.createIfcPlane(
self.file.createIfcAxis2Placement3D(
self.create_point(location),