Fixes problems with referents

This commit is contained in:
Richard Brice
2025-08-27 11:32:25 -07:00
parent c090073858
commit 39100b7c97
10 changed files with 85 additions and 55 deletions
@@ -89,7 +89,8 @@ def _add_segment_to_layout(file: ifcopenshell.file, layout: entity_instance, seg
# update the zero length layout segment
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file)
zero_length_segment = layout.IsNestedBy[0].RelatedObjects[-1]
segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(layout)
zero_length_segment = segment_nest.RelatedObjects[-1]
# DesignParameters.StartPoint for IfcAlignmentHorizontalSegment is automatically updated when the
# geometric representation is updated because the semantic and geometric data use the same IfcPoint.
# This is not the case of IfcAlignmentVerticalSegment and IfcAlignmentCantSegment. For these
@@ -136,7 +137,8 @@ def _add_segment_to_layout(file: ifcopenshell.file, layout: entity_instance, seg
start_dist_along = segment.DesignParameters.StartDistAlong + segment.DesignParameters.HorizontalLength
zero_length_segment.DesignParameters.StartDistAlong = start_dist_along
end_referent = zero_length_segment.IsNestedBy[0].RelatedObjects[0]
referent_nest = ifcopenshell.api.alignment.get_referent_nest(file,layout)
end_referent = referent_nest.RelatedObjects[-1]
end_referent.Name = f"{_get_segment_start_point_label(zero_length_segment,None)} ({ifcopenshell.util.alignment.station_as_string(file,start_station+start_dist_along)})"
# update the referent's geometric representation's location
@@ -173,12 +175,12 @@ def _add_segment_to_layout(file: ifcopenshell.file, layout: entity_instance, seg
# get the previous segment. Working from the end of the basis curve, -1 is zero length segment
# -2 is the newly added segment, so -3 is the segment occuring just before the newly added segment
segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(layout)
prev_segment = segment_nest.RelatedObjects[-3] if 2 < len(segment_nest.RelatedObjects) else None
name = f"{_get_segment_start_point_label(prev_segment,segment)} ({ifcopenshell.util.alignment.station_as_string(file,station)})"
referent = ifcopenshell.api.alignment.add_stationing_referent(
file, segment, distance_along=dist_along, station=station, name=name
file, layout, distance_along=dist_along, station=station, name=name, positioned_product=segment
)
ifcopenshell.api.nest.reorder_nesting(file,referent,-1,-1)
if len(curve.Segments) == 2 and layout.is_a("IfcAlignmentHorizontal"):
# this is the first real segment in the horizontal alignment
@@ -48,8 +48,9 @@ def _add_zero_length_segment(file: ifcopenshell.file, layout: entity_instance) -
if curve:
ifcopenshell.api.alignment.add_zero_length_segment(file, curve)
segment = layout.IsNestedBy[0].RelatedObjects[-1]
segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(layout)
segment = segment_nest.RelatedObjects[-1]
alignment = ifcopenshell.api.alignment.get_alignment(layout)
station = ifcopenshell.api.alignment.get_alignment_station(file, alignment)
name = f"{_get_segment_start_point_label(segment,None)} ({ifcopenshell.util.alignment.station_as_string(file,station)})"
ifcopenshell.api.alignment.add_stationing_referent(file, segment, 0.0, station, name=name)
ifcopenshell.api.alignment.add_stationing_referent(file, layout, 0.0, station, name, segment)
@@ -34,6 +34,7 @@ def add_stationing_referent(
distance_along: float,
station: float,
name: str,
positioned_product: entity_instance
) -> entity_instance:
"""
Adds an IfcReferent to the element with the Pset_Stationing property set.
@@ -43,6 +44,7 @@ def add_stationing_referent(
:param distance_along: distance along the alignment curve
:param station: station value
:param name: name to assign to IfcReferent.Name, typically a stringized version of the station value
:param positioned_product: the product whose position is informed by the referent
:return: referent
Example:
@@ -54,9 +56,17 @@ def add_stationing_referent(
"""
alignment = element
layout_types = [
"IfcAlignmentHorizontal",
"IfcAlignmentVertical",
"IfcAlignmentCant",
]
if element.is_a("IfcAlignmentSegment"):
layout = element.Nests[0].RelatingObject
alignment = ifcopenshell.api.alignment.get_alignment(layout)
elif element.is_a() in layout_types:
alignment = ifcopenshell.api.alignment.get_alignment(element)
basis_curve = ifcopenshell.api.alignment.get_basis_curve(alignment)
@@ -137,15 +147,15 @@ def add_stationing_referent(
nest = ifcopenshell.api.alignment.get_referent_nest(file,element)
nest.RelatedObjects += (referent,)
if len(alignment.Positions) == 0:
if len(referent.Positions) == 0:
rel_positions = file.createIfcRelPositions(
GlobalId=ifcopenshell.guid.new(),
RelatingPositioningElement=alignment,
RelatingPositioningElement=referent,
RelatedProducts=[
referent,
positioned_product,
],
)
else:
alignment.Positions[0].RelatedProducts += (referent,)
referent.Positions[0].RelatedProducts += (positioned_product,)
return referent
@@ -86,7 +86,7 @@ def create(
if include_geometry:
# define stationing
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, alignment)
# IFC 4.1.4.1.1 Alignment Aggregation To Project
@@ -137,13 +137,11 @@ def create_as_polyline(
Name=name,
)
# _create_layout(file,alignment,points)
_create_polyline_representation(file, alignment, points)
# define stationing
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, alignment)
ifcopenshell.api.nest.reorder_nesting(file, referent, -1, 0)
# IFC 4.1.4.1.1 Alignment Aggregation To Project
@@ -162,3 +162,11 @@ def print_composite_curve_deep(curve):
print(" " * 4, segment.Placement)
print(" " * 4, segment.Placement.Location)
print(" " * 4, segment.Placement.RefDirection)
def print_positioned_products(file: ifcopenshell.file):
referents = file.by_type("IfcReferent")
for referent in referents:
print(referent)
for rel in referent.Positions:
for product in rel.RelatedProducts:
print(" " * 2,product)