First Commit
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
import ifcopenshell.util.unit
|
||||
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: SequenceOfVectors,
|
||||
location: tuple[float, float, float],
|
||||
axis: tuple[float, float, float],
|
||||
ref_direction: tuple[float, float, float],
|
||||
inner_boundaries: Optional[SequenceOfVectors] = None,
|
||||
unit_scale: Optional[float] = None,
|
||||
) -> None:
|
||||
"""Create and assign a connection geometry to a space boundary relationship
|
||||
|
||||
A space boundary may optionally have a plane that represents how that
|
||||
space is adjacent to another space, known as the connection geometry.
|
||||
You may specify this plane in terms of an outer boundary polyline, zero
|
||||
or more inner boundaries (such as for windows), and a positional matrix
|
||||
for the orientation of the plane.
|
||||
|
||||
:param rel_space_boundary: The space boundary relationship to assign the
|
||||
connection geometry to.
|
||||
: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.
|
||||
: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.
|
||||
: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.
|
||||
: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.
|
||||
: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.
|
||||
: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.
|
||||
:return: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
ifcopenshell.api.boundary.assign_connection_geometry(model,
|
||||
rel_space_boundary=element,
|
||||
outer_boundary=[(0., 0.), (1., 0.), (1., 1.), (0., 1.)],
|
||||
location=[0., 0., 0.], axis=[1., 0., 0.], ref_direction=[0., 0., 1.],
|
||||
)
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.rel_space_boundary = rel_space_boundary
|
||||
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):
|
||||
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)
|
||||
curve_bounded_plane = self.file.createIfcCurveBoundedPlane(plane, outer_boundary, inner_boundaries)
|
||||
connection_geometry = self.file.createIfcConnectionSurfaceGeometry(curve_bounded_plane)
|
||||
self.rel_space_boundary.ConnectionGeometry = connection_geometry
|
||||
|
||||
def create_point(self, point: npt.NDArray) -> ifcopenshell.entity_instance:
|
||||
return self.file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(point / self.unit_scale))
|
||||
|
||||
def close_polyline(
|
||||
self, points: tuple[ifcopenshell.entity_instance, ...]
|
||||
) -> tuple[ifcopenshell.entity_instance, ...]:
|
||||
return points + (points[0],)
|
||||
|
||||
def create_polyline(self, points: npt.NDArray) -> ifcopenshell.entity_instance:
|
||||
if np.allclose(points[0], points[-1]):
|
||||
points = points[0 : len(points) - 1]
|
||||
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: npt.NDArray, axis: npt.NDArray, ref_direction: npt.NDArray
|
||||
) -> ifcopenshell.entity_instance:
|
||||
return self.file.createIfcPlane(
|
||||
self.file.createIfcAxis2Placement3D(
|
||||
self.create_point(location),
|
||||
self.file.createIfcDirection(ifc_safe_vector_type(axis)),
|
||||
self.file.createIfcDirection(ifc_safe_vector_type(ref_direction)),
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user