mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-12 06:32:09 +00:00
Alignments can now be created with or without geometric representations
This commit is contained in:
@@ -60,6 +60,7 @@ def _add_segment_to_layout(file: ifcopenshell.file, layout: entity_instance, seg
|
|||||||
# swap the last two segments
|
# swap the last two segments
|
||||||
ifcopenshell.api.nest.reorder_nesting(file, segment, -1, -1)
|
ifcopenshell.api.nest.reorder_nesting(file, segment, -1, -1)
|
||||||
|
|
||||||
|
if curve:
|
||||||
# add the new segment to the geometric representation curve
|
# add the new segment to the geometric representation curve
|
||||||
_add_segment_to_curve(file, segment, curve)
|
_add_segment_to_curve(file, segment, curve)
|
||||||
|
|
||||||
|
|||||||
@@ -33,27 +33,31 @@ def create(
|
|||||||
name: str,
|
name: str,
|
||||||
include_vertical: bool = False,
|
include_vertical: bool = False,
|
||||||
include_cant: bool = False,
|
include_cant: bool = False,
|
||||||
|
include_geometry: bool = True,
|
||||||
start_station: float = 0.0,
|
start_station: float = 0.0,
|
||||||
) -> entity_instance:
|
) -> entity_instance:
|
||||||
"""
|
"""
|
||||||
Creates a new IfcAlignment with an IfcRelNests nesting an IfcReferent (for stationing) and IfcAlignmentHorizontal. The nest relationship can optionally
|
Creates a new alignment with a horizontal layout. Optionally, vertical and cant layouts can be created as well.
|
||||||
include IfcAlignmentVertical and IfcAlignmentCant. Geometric representations for the alignment layouts (IfcCompositeCurve,
|
The geometric representations are created as well, unless they are explicitly excluded.
|
||||||
IfcGradientCurve, IfcSegmentedReferenceCurve) are created as well.
|
Zero length segments are added at the end of the layouts and geometric representations.
|
||||||
|
The alignment is automatically aggreated to the project if it exists.
|
||||||
|
|
||||||
Zero length segments are added at the end.
|
Use get_horizontal_layout(alignment), get_vertical_layout(alignment) and get_cant_layout(alignment) to get the
|
||||||
|
corresponding IfcAlignmentHorizontal, IfcAlignmentVertical, and IfcAlignmentCant layout entities.
|
||||||
|
|
||||||
The IfcAlignment is aggreated to IfcProject
|
If the alignment has Viennese Bend transition curves, create the segments in the cant layout before the horizontal layout using create_layout_segment().
|
||||||
|
The horizontal geometry in the Viennese Bend transition curves depends on the Viennese Bend cant parameters. create_layout_segment() automatically creates
|
||||||
|
the geometric representation from the semantic definition. The horizontal segment geometric representation will fail if the cant segment is not defined.
|
||||||
|
|
||||||
Use get_horizontal_layout(alignment) to get the IfcAlignmentHorizontal layout.
|
If geometric representations are created, the alignment stationing referent is also created using the start_station value. IfcReferent.ObjectPlacement
|
||||||
|
is required for linear positiion elements and IfcLinearPlacement is defined relative to alignment curve geometry.
|
||||||
If the alignment has Viennese Bend transition curves, create the cant layout before the horizontal layout. This is because the horizontal layout
|
|
||||||
in the Viennese Bend transition curves depends on the Viennese Bend cant parameters.
|
|
||||||
|
|
||||||
:param file:
|
:param file:
|
||||||
:param name: name assigned to IfcAlignment.Name
|
:param name: name assigned to IfcAlignment.Name
|
||||||
:param include_vertical: If True, IfcAlignmentVertical and IfcGradientCurve are created
|
:param include_vertical: If True, IfcAlignmentVertical is created. IfcGradientCurve is created if include_geometry is True
|
||||||
:param include_cant: If True, IfcAlignmentCant and IfcSegmentedReferenceCurve are created
|
:param include_cant: If True, IfcAlignmentCant is created. IfcSegmentedReferenceCurve is created if include_geometry is True
|
||||||
:param start_station: station value at the start of the alignment
|
:param include_geometry: If True, the geometric representations are added
|
||||||
|
:param start_station: station value at the start of the alignment.
|
||||||
:return: Returns an IfcAlignment
|
:return: Returns an IfcAlignment
|
||||||
"""
|
"""
|
||||||
alignment = file.createIfcAlignment(
|
alignment = file.createIfcAlignment(
|
||||||
@@ -73,16 +77,19 @@ def create(
|
|||||||
|
|
||||||
ifcopenshell.api.nest.assign_object(file, related_objects=alignment_layouts, relating_object=alignment)
|
ifcopenshell.api.nest.assign_object(file, related_objects=alignment_layouts, relating_object=alignment)
|
||||||
|
|
||||||
|
if include_geometry:
|
||||||
_create_geometric_representation(file, alignment)
|
_create_geometric_representation(file, alignment)
|
||||||
|
|
||||||
for layout in alignment_layouts:
|
for layout in alignment_layouts:
|
||||||
_add_zero_length_segment(file, layout)
|
_add_zero_length_segment(file, layout)
|
||||||
|
|
||||||
|
if include_geometry:
|
||||||
# define stationing
|
# define stationing
|
||||||
name = ifcopenshell.util.alignment.station_as_string(file, start_station)
|
name = ifcopenshell.util.alignment.station_as_string(file, start_station)
|
||||||
referent = ifcopenshell.api.alignment.add_stationing_referent(file, alignment, 0.0, start_station, name)
|
referent = ifcopenshell.api.alignment.add_stationing_referent(file, alignment, 0.0, start_station, name)
|
||||||
ifcopenshell.api.nest.reorder_nesting(file, referent, -1, 0)
|
ifcopenshell.api.nest.reorder_nesting(file, referent, -1, 0)
|
||||||
|
|
||||||
|
|
||||||
# IFC 4.1.4.1.1 Alignment Aggregation To Project
|
# IFC 4.1.4.1.1 Alignment Aggregation To Project
|
||||||
project = file.by_type("IfcProject")[0]
|
project = file.by_type("IfcProject")[0]
|
||||||
if project:
|
if project:
|
||||||
|
|||||||
@@ -23,20 +23,21 @@ from ifcopenshell import entity_instance
|
|||||||
import math
|
import math
|
||||||
from ifcopenshell import ifcopenshell_wrapper
|
from ifcopenshell import ifcopenshell_wrapper
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
from ifcopenshell.api.alignment._add_segment_to_layout import _add_segment_to_layout
|
from ifcopenshell.api.alignment._add_segment_to_layout import _add_segment_to_layout
|
||||||
|
|
||||||
|
|
||||||
def create_layout_segment(
|
def create_layout_segment(
|
||||||
file: ifcopenshell.file, layout: entity_instance, design_parameters: entity_instance
|
file: ifcopenshell.file, layout: entity_instance, design_parameters: entity_instance
|
||||||
) -> np.array:
|
) -> Union[np.array, None]:
|
||||||
"""
|
"""
|
||||||
Creates a new IfcAlignmentSegment using the IfcAlignmentParameterSegment design parameters.
|
Creates a new IfcAlignmentSegment using the IfcAlignmentParameterSegment design parameters.
|
||||||
The new segment is appended to the layout alignment and the corresponding IfcCurveSegment is created in the geometric representation
|
The new segment is appended to the layout alignment and the corresponding IfcCurveSegment is created in the geometric representation if it exists.
|
||||||
|
|
||||||
:param layout: The layout to receive the new layout segment. This parameter is expected to be IfcAlignmentHorizontal, IfcAlignmentVertical or IfcAlignmentCant
|
:param layout: The layout to receive the new layout segment. This parameter is expected to be IfcAlignmentHorizontal, IfcAlignmentVertical or IfcAlignmentCant
|
||||||
:param design_parameters: The parameters defining the segment. Expected to be the appropreate subclass of IfcAlignmentParameterSegment
|
:param design_parameters: The parameters defining the segment. Expected to be the appropreate subclass of IfcAlignmentParameterSegment
|
||||||
:return: 4x4 matrix at end of segment as np.array intended to be used as the start point geometry for the next segment.
|
:return: 4x4 matrix at end of segment as np.array intended to be used as the start point geometry for the next segment or None if there is the geometric representation is not defined.
|
||||||
"""
|
"""
|
||||||
expected_types = ["IfcAlignmentHorizontal", "IfcAlignmentVertical", "IfcAlignmentCant"]
|
expected_types = ["IfcAlignmentHorizontal", "IfcAlignmentVertical", "IfcAlignmentCant"]
|
||||||
if not layout.is_a() in expected_types:
|
if not layout.is_a() in expected_types:
|
||||||
@@ -60,6 +61,7 @@ def create_layout_segment(
|
|||||||
alignment = ifcopenshell.api.alignment.get_alignment(layout)
|
alignment = ifcopenshell.api.alignment.get_alignment(layout)
|
||||||
curve = ifcopenshell.api.alignment.get_curve(alignment)
|
curve = ifcopenshell.api.alignment.get_curve(alignment)
|
||||||
|
|
||||||
|
if curve:
|
||||||
if layout.is_a("IfcAlignmentHorizontal"):
|
if layout.is_a("IfcAlignmentHorizontal"):
|
||||||
if curve.is_a("IfcGradientCurve"):
|
if curve.is_a("IfcGradientCurve"):
|
||||||
curve = curve.BaseCurve
|
curve = curve.BaseCurve
|
||||||
@@ -82,3 +84,5 @@ def create_layout_segment(
|
|||||||
end = np.array(e)
|
end = np.array(e)
|
||||||
|
|
||||||
return end
|
return end
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|||||||
@@ -21,12 +21,11 @@ import ifcopenshell.api.alignment
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
from ifcopenshell import entity_instance
|
from ifcopenshell import entity_instance
|
||||||
|
|
||||||
|
|
||||||
def get_alignment_station(file: ifcopenshell.file, alignment: entity_instance) -> float:
|
def get_alignment_station(file: ifcopenshell.file, alignment: entity_instance) -> float:
|
||||||
"""
|
"""
|
||||||
Returns the start station of the alignment. If the alignment is nested by an IfcReferent
|
Returns the start station of the alignment. If the alignment is nested by an IfcReferent
|
||||||
the referent is checked for PredefinedType of STATION and an occurance of Pset_Stationing.Station,
|
the referent is checked for PredefinedType of STATION and an occurance of Pset_Stationing.Station,
|
||||||
otherwise start station is taken to be 0.0.
|
otherwise returns 0.0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not alignment.is_a("IfcAlignment"):
|
if not alignment.is_a("IfcAlignment"):
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# IfcOpenShell - IFC toolkit and geometry engine
|
||||||
|
# Copyright (C) 2025 Thomas Krijnen <thomas@aecgeeks.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/>.
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import ifcopenshell.api.alignment
|
||||||
|
import ifcopenshell.api.context
|
||||||
|
import ifcopenshell.api.unit
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_no_geometry():
|
||||||
|
file = ifcopenshell.file(schema="IFC4X3_ADD2")
|
||||||
|
project = file.createIfcProject(GlobalId=ifcopenshell.guid.new(), Name="Test")
|
||||||
|
length = ifcopenshell.api.unit.add_si_unit(file, unit_type="LENGTHUNIT")
|
||||||
|
ifcopenshell.api.unit.assign_unit(file, units=[length])
|
||||||
|
|
||||||
|
# creates an IfcAlignment with an IfcAlignmentHorizontal layout containing only the zero length segment
|
||||||
|
ali = ifcopenshell.api.alignment.create(file, "A1", include_vertical=True,include_geometry=False)
|
||||||
|
|
||||||
|
# append a segment to the horizontal layout
|
||||||
|
horizontal_alignment = ifcopenshell.api.alignment.get_horizontal_layout(ali)
|
||||||
|
vertical_alignment = ifcopenshell.api.alignment.get_vertical_layout(ali)
|
||||||
|
|
||||||
|
curve = ifcopenshell.api.alignment.get_curve(ali)
|
||||||
|
assert curve == None
|
||||||
|
|
||||||
|
design_parameters = file.create_entity(
|
||||||
|
type="IfcAlignmentHorizontalSegment",
|
||||||
|
StartTag=None,
|
||||||
|
EndTag=None,
|
||||||
|
StartPoint=file.createIfcCartesianPoint(Coordinates=((0.0, 0.0))),
|
||||||
|
StartDirection=0.0,
|
||||||
|
StartRadiusOfCurvature=0.0,
|
||||||
|
EndRadiusOfCurvature=0.0,
|
||||||
|
SegmentLength=100.0,
|
||||||
|
GravityCenterLineHeight=None,
|
||||||
|
PredefinedType="LINE",
|
||||||
|
)
|
||||||
|
end = ifcopenshell.api.alignment.create_layout_segment(file, horizontal_alignment, design_parameters)
|
||||||
|
assert end == None
|
||||||
|
|
||||||
|
design_parameters = file.createIfcAlignmentVerticalSegment(
|
||||||
|
StartDistAlong=0.0,
|
||||||
|
HorizontalLength=50.0,
|
||||||
|
StartHeight=20.0,
|
||||||
|
StartGradient=1.0 / 100.0,
|
||||||
|
EndGradient=1.0 / 100.0,
|
||||||
|
PredefinedType="CONSTANTGRADIENT",
|
||||||
|
)
|
||||||
|
end = ifcopenshell.api.alignment.create_layout_segment(file, vertical_alignment, design_parameters)
|
||||||
|
assert end == None
|
||||||
|
|
||||||
|
|
||||||
|
test_create_no_geometry()
|
||||||
Reference in New Issue
Block a user