Updates alignment api. Fixes bugs authoring semantic-only alignment

This commit is contained in:
Richard Brice
2026-05-25 10:31:57 -07:00
committed by Thomas Krijnen
parent 852311279d
commit 3559d23f81
27 changed files with 1086 additions and 373 deletions
@@ -23,6 +23,7 @@ from ifcopenshell.api.alignment._add_segment_to_curve import _add_segment_to_cur
from ifcopenshell.api.alignment._create_geometric_representation import (
_create_geometric_representation,
)
from ifcopenshell.api.alignment.update_fallback_position import update_fallback_position
def create_representation(
@@ -34,8 +35,13 @@ def create_representation(
This function is intended to be used when a model has only the semantic definition of an alignment
and you want to add the geometric representation.
If the alignments are complete, it is recommended that add_zero_length_segment is called after this method to ensure
the proper structure of the semantic and geometric definitions of the alignment
If the alignments are complete, it is recommended that add_zero_length_segment is called before this method to ensure
the proper structure of the semantic and geometric definitions of the alignment.
It is presumed that the alignment does not have any geometric representation. However, if the alignment has stationing defined,
the referent defining the stationing is not related to the alignment geometry (it can't be because the geometry doesn't exist yet).
When the geometric representation is created, the referent is updated to have an IfcLinearPlacement that references the basis curve geometry.
This function assumes the referent defines the stationing at the start of the alignment, and therefore sets the IfcLinearPlacement.RelativePlacement.Location.DistanceAlong to 0.0.
:param alignment: The alignment to create the representation.
"""
@@ -51,6 +57,40 @@ def create_representation(
layouts = ifcopenshell.api.alignment.get_alignment_layouts(alignment)
for layout in layouts:
curve = ifcopenshell.api.alignment.get_layout_curve(layout)
layout_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(layout)
for segment in layout_nest.RelatedObjects:
_add_segment_to_curve(file, segment, curve)
# if the alignment is created without geometry it's stationing referent isn't related to the alignment geometry.
# the stationing referent needs to be updated to have an IfcLinearPlacement that references the basis curve geometry
referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, alignment)
if (
referent_nest
and 0 < len(referent_nest.RelatedObjects)
and referent_nest.RelatedObjects[0].ObjectPlacement
and not referent_nest.RelatedObjects[0].ObjectPlacement.is_a("IfcLinearPlacement")
):
basis_curve = ifcopenshell.api.alignment.get_basis_curve(alignment)
if referent_nest.RelatedObjects[0].ObjectPlacement:
if referent_nest.RelatedObjects[0].ObjectPlacement.RelativePlacement.Location:
file.remove(referent_nest.RelatedObjects[0].ObjectPlacement.RelativePlacement.Location)
if referent_nest.RelatedObjects[0].ObjectPlacement.RelativePlacement.RefDirection:
file.remove(referent_nest.RelatedObjects[0].ObjectPlacement.RelativePlacement.RefDirection)
file.remove(referent_nest.RelatedObjects[0].ObjectPlacement.RelativePlacement)
file.remove(referent_nest.RelatedObjects[0].ObjectPlacement)
lp = file.createIfcLinearPlacement(
RelativePlacement=file.createIfcAxis2PlacementLinear(
Location=file.createIfcPointByDistanceExpression(
DistanceAlong=file.createIfcLengthMeasure(0.0),
OffsetLateral=None,
OffsetVertical=None,
OffsetLongitudinal=None,
BasisCurve=basis_curve,
)
)
)
update_fallback_position(file, lp)
referent_nest.RelatedObjects[0].ObjectPlacement = lp