From 34bf374047093a41c1d5aa00ef924cdb4c5f3ad7 Mon Sep 17 00:00:00 2001 From: Richard Brice <37087370+RickBrice@users.noreply.github.com> Date: Fri, 29 Aug 2025 12:48:03 -0700 Subject: [PATCH] Corrects nesting of referents --- .../ifcopenshell/api/alignment/__init__.py | 4 +- .../api/alignment/_add_segment_to_layout.py | 9 ++- .../api/alignment/_add_zero_length_segment.py | 4 +- .../api/alignment/add_stationing_referent.py | 55 ++++++++++--------- .../api/alignment/add_vertical_layout.py | 15 ++++- .../api/alignment/add_zero_length_segment.py | 5 +- .../ifcopenshell/api/alignment/create.py | 10 ++-- .../api/alignment/create_as_offset_curve.py | 5 -- .../alignment/distance_along_from_station.py | 2 +- ...tion.py => get_alignment_start_station.py} | 13 +++-- .../api/alignment/get_referent_nest.py | 13 +++-- .../alignment/test_add_segment_to_layout.py | 6 +- .../test_add_stationing_to_alignment.py | 25 +++++---- .../alignment/test_add_vertical_alignment.py | 28 ++++++---- .../api/alignment/test_create_by_pi_method.py | 7 +-- .../test/api/alignment/test_referent_names.py | 36 +++--------- .../test_vertical_layout_by_pi_method.py | 8 ++- 17 files changed, 125 insertions(+), 120 deletions(-) rename src/ifcopenshell-python/ifcopenshell/api/alignment/{get_alignment_station.py => get_alignment_start_station.py} (77%) diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/__init__.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/__init__.py index fb51da7cde..563376485f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/__init__.py @@ -62,7 +62,7 @@ from .distance_along_from_station import distance_along_from_station from .get_alignment import get_alignment from .get_alignment_layout_nest import get_alignment_layout_nest from .get_alignment_segment_nest import get_alignment_segment_nest -from .get_alignment_station import get_alignment_station +from .get_alignment_start_station import get_alignment_start_station from .get_curve_segment_transition_code import get_curve_segment_transition_code from .get_layout_segments import get_layout_segments from .get_horizontal_layout import get_horizontal_layout @@ -103,7 +103,7 @@ __all__ = [ "get_alignment_layout_nest", "get_alignment_layouts", "get_alignment_segment_nest", - "get_alignment_station", + "get_alignment_start_station", "get_axis_subcontext", "get_basis_curve", "get_cant_layout", diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_layout.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_layout.py index b6e10113a7..6ab52af076 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_layout.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_layout.py @@ -83,7 +83,7 @@ def _add_segment_to_layout(file: ifcopenshell.file, layout: entity_instance, seg # get the station of the start of the segment alignment = ifcopenshell.api.alignment.get_alignment(layout) - start_station = ifcopenshell.api.alignment.get_alignment_station(file, alignment) + start_station = ifcopenshell.api.alignment.get_alignment_start_station(file, alignment) station = start_station + dist_along # update the zero length layout segment @@ -137,8 +137,7 @@ 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 - referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, layout) - end_referent = referent_nest.RelatedObjects[-1] + end_referent = zero_length_segment.PositionedRelativeTo[0].RelatingPositioningElement 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 @@ -166,7 +165,7 @@ def _add_segment_to_layout(file: ifcopenshell.file, layout: entity_instance, seg end_referent.ObjectPlacement.CartesianPosition.Axis.DirectionRatios = (ax, ay, az) end_referent.ObjectPlacement.CartesianPosition.RefDirection.DirectionRatios = (rx, ry, rz) - start_station = ifcopenshell.api.alignment.get_alignment_station(file, alignment) + start_station = ifcopenshell.api.alignment.get_alignment_start_station(file, alignment) end_referent_station = start_station + start_dist_along pset_stationing = ifcopenshell.api.pset.add_pset(file, product=end_referent, name="Pset_Stationing") ifcopenshell.api.pset.edit_pset(file, pset=pset_stationing, properties={"Station": end_referent_station}) @@ -178,7 +177,7 @@ def _add_segment_to_layout(file: ifcopenshell.file, layout: entity_instance, seg 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, layout, distance_along=dist_along, station=station, name=name, positioned_product=segment + file, alignment, distance_along=dist_along, station=station, name=name, positioned_product=segment ) ifcopenshell.api.nest.reorder_nesting(file, referent, -1, -1) diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_zero_length_segment.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_zero_length_segment.py index dacae0be54..1219e35762 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_zero_length_segment.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_zero_length_segment.py @@ -51,6 +51,6 @@ def _add_zero_length_segment(file: ifcopenshell.file, layout: entity_instance) - 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) + station = ifcopenshell.api.alignment.get_alignment_start_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, layout, 0.0, station, name, segment) + referent = ifcopenshell.api.alignment.add_stationing_referent(file, alignment, 0.0, station, name, segment) diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py index c1590164e9..fe53ef5ca5 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py @@ -30,18 +30,17 @@ import numpy as np def add_stationing_referent( file: ifcopenshell.file, - element: entity_instance, + alignment: entity_instance, 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. - If element is an IfcAlignment, IfcReferent.PredefinedType is set to "STATION", otherwise "POSITION" + Adds an IfcReferent to the alignment with the Pset_Stationing property set. - :param element: the element to receive the referent, expected to be an IfcAlignment or IfcAlignmentSegment - :param distance_along: distance along the alignment curve + :param alignment: the alignment to receive the referent + :param distance_along: distance along the alignment basis 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 @@ -52,21 +51,8 @@ def add_stationing_referent( .. code:: python alignment = model.by_type("IfcAlignment")[0] - ifcopenshell.api.alignment.add_stationing_referent(model,entity=alignment,distance_along=0.0,station=100.0) + ifcopenshell.api.alignment.add_stationing_referent(model,alignment=alignment,distance_along=0.0,station=100.0) """ - 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) @@ -86,6 +72,8 @@ def add_stationing_referent( ) is_valid_curve = True + if basis_curve.is_a("IfcCompositeCurve") and len(basis_curve.Segments) == 0: + is_valid_curve = False if basis_curve.is_a("IfcPolyline") and len(basis_curve.Points) < 2: is_valid_curve = False elif basis_curve.is_a("IfcIndexedPolyCurve") and len(basis_curve.Points.CoordList) < 2: @@ -101,6 +89,7 @@ def add_stationing_referent( fn = ifcopenshell_wrapper.convert_loop_to_function_item(fn) evaluator = ifcopenshell_wrapper.function_item_evaluator(settings, fn) + p = evaluator.evaluate(distance_along * unit_scale) p = np.array(p) @@ -115,12 +104,23 @@ def add_stationing_referent( ax = float(p[0, 2]) ay = float(p[1, 2]) az = float(p[2, 2]) + else: + x = 0. + y = 0. + z = 0. + rx = 1. + ry = 0. + rz = 0. + ax = 0. + ay = 0. + az = 1. - object_placement.CartesianPosition = file.createIfcAxis2Placement3D( - Location=file.createIfcCartesianPoint((x, y, z)), - Axis=file.createIfcDirection((ax, ay, az)), - RefDirection=file.createIfcDirection((rx, ry, rz)), - ) + object_placement.CartesianPosition = file.createIfcAxis2Placement3D( + Location=file.createIfcCartesianPoint((x, y, z)), + Axis=file.createIfcDirection((ax, ay, az)), + RefDirection=file.createIfcDirection((rx, ry, rz)), + ) + # this commented out code is what you would do to add a geometric representation of the referent # the example is a circle. a better way would be to pass a representation into the function # representation = file.create_entity( @@ -130,7 +130,6 @@ def add_stationing_referent( # ) # create referent for the station - predefined_type = "STATION" if element.is_a("IfcAlignment") else "POSITION" referent = file.createIfcReferent( GlobalId=ifcopenshell.guid.new(), OwnerHistory=None, @@ -139,14 +138,16 @@ def add_stationing_referent( ObjectType=None, ObjectPlacement=object_placement, Representation=representation, - PredefinedType=predefined_type, + PredefinedType="STATION", ) pset_stationing = ifcopenshell.api.pset.add_pset(file, product=referent, name="Pset_Stationing") ifcopenshell.api.pset.edit_pset(file, pset=pset_stationing, properties={"Station": station}) - nest = ifcopenshell.api.alignment.get_referent_nest(file, element) + nest = ifcopenshell.api.alignment.get_referent_nest(file, alignment) nest.RelatedObjects += (referent,) + nest.RelatedObjects = sorted(nest.RelatedObjects,key=lambda x: ifcopenshell.util.element.get_pset(x, name="Pset_Stationing", prop="Station")) + if len(referent.Positions) == 0: rel_positions = file.createIfcRelPositions( GlobalId=ifcopenshell.guid.new(), diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_vertical_layout.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_vertical_layout.py index 6a388ff9d0..ffbd6b0870 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_vertical_layout.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_vertical_layout.py @@ -50,9 +50,22 @@ def _move_vertical_layout_to_child_alignment( # nest the vertical layout onto the child alignment ifcopenshell.api.nest.assign_object(file, related_objects=[vertical_layout], relating_object=child_alignment) - # aggreage the child alignment to the parent alignment + # aggregate the child alignment to the parent alignment ifcopenshell.api.aggregate.assign_object(file, products=[child_alignment], relating_object=parent_alignment) + # move all referents positioning segments of the vertical layout to the referent nest of the child alignment + child_referent_nest = ifcopenshell.api.alignment.get_referent_nest(file,child_alignment) + parent_referent_nest = ifcopenshell.api.alignment.get_referent_nest(file,parent_alignment) + for referent in parent_referent_nest.RelatedObjects: + for product in referent.Positions[0].RelatedProducts: + if product.is_a("IfcAlignmentSegment") and product.Nests[0].RelatingObject == vertical_layout: + #ifcopenshell.api.nest.change_nest(file,referent,child_alignment) - this doesn't work because referent is assigned to child_alignment.IsNestedBy[0].RelatedObjects + # and it needs to be assigned to child_alignment.IsNestedBy[1].RelatedObjects + # move the referent manually - unassign it and add it to the child alignment's referent nest + ifcopenshell.api.nest.unassign_object(file,[referent]) + child_referent_nest.RelatedObjects += (referent,) + + # if the parent alignment has a representation, move the Axis/Curve3D represention to the child alignment base_curve = ifcopenshell.api.alignment.get_basis_curve(parent_alignment) if base_curve: diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_zero_length_segment.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_zero_length_segment.py index 339098fa40..fbb159426a 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_zero_length_segment.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_zero_length_segment.py @@ -231,8 +231,9 @@ def add_zero_length_segment(file: ifcopenshell.file, layout: entity_instance, in if include_referent: alignment = ifcopenshell.api.alignment.get_alignment(layout) - station = ifcopenshell.api.alignment.get_alignment_station(file, alignment) + station = ifcopenshell.api.alignment.get_alignment_start_station(file, alignment) name = f"{_get_segment_start_point_label(zero_length_curve_segment,None)} ({ifcopenshell.util.alignment.station_as_string(file,station)})" - ifcopenshell.api.alignment.add_stationing_referent(file, zero_length_curve_segment, 0.0, station, name=name) + referent = ifcopenshell.api.alignment.add_stationing_referent(file, alignment, 0.0, station, name, zero_length_curve_segment) + referent.Description = f"Positions zero length segment {zero_length_curve_segment.id()}" return True diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py index daa44ed460..af106a584b 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py @@ -79,17 +79,15 @@ def create( if include_geometry: _create_geometric_representation(file, alignment) - - for layout in alignment_layouts: - _add_zero_length_segment(file, layout) - - 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, alignment ) + for layout in alignment_layouts: + _add_zero_length_segment(file, layout) + # IFC 4.1.4.1.1 Alignment Aggregation To Project project = file.by_type("IfcProject")[0] if project: diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_offset_curve.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_offset_curve.py index dd7be84223..a206fda69b 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_offset_curve.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_offset_curve.py @@ -53,11 +53,6 @@ def create_as_offset_curve( _create_offset_curve_representation(file, alignment, offsets) - # 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) - # ifcopenshell.api.nest.reorder_nesting(file, referent, -1, 0) - # IFC 4.1.4.1.1 Alignment Aggregation To Project project = file.by_type("IfcProject")[0] if project: diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py index e67b468c75..c52d9962ad 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py @@ -43,6 +43,6 @@ def distance_along_from_station(file: ifcopenshell.file, alignment: entity_insta print(dist_along) # 100.00 """ - start_station = ifcopenshell.api.alignment.get_alignment_station(file, alignment) + start_station = ifcopenshell.api.alignment.get_alignment_start_station(file, alignment) dist_along = station - start_station return dist_along diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_station.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_start_station.py similarity index 77% rename from src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_station.py rename to src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_start_station.py index 313ab949a7..8f9a5f0beb 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_station.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_start_station.py @@ -22,10 +22,10 @@ import ifcopenshell.util.element from ifcopenshell import entity_instance -def get_alignment_station(file: ifcopenshell.file, alignment: entity_instance) -> float: +def get_alignment_start_station(file: ifcopenshell.file, alignment: entity_instance) -> float: """ - 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, + Returns the start station of the alignment. The starting station is defined by the first nested IfcReferent. + This is interpreted to mean the first IfcReferent with an occurance of Pset_Stationing.Station, otherwise returns 0.0. """ @@ -36,12 +36,13 @@ def get_alignment_station(file: ifcopenshell.file, alignment: entity_instance) - parent_alignment = ifcopenshell.api.alignment.get_parent_alignment(alignment) if parent_alignment: - start_station = ifcopenshell.api.alignment.get_alignment_station(file, parent_alignment) + start_station = ifcopenshell.api.alignment.get_alignment_start_station(file, parent_alignment) else: components = ifcopenshell.util.element.get_components(alignment) for c in components: - if c.is_a("IfcReferent") and ifcopenshell.util.element.get_predefined_type(c) == "STATION": + if c.is_a("IfcReferent"): start_station = ifcopenshell.util.element.get_pset(c, name="Pset_Stationing", prop="Station") - break + if not start_station == None: + break return start_station diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/get_referent_nest.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_referent_nest.py index 0efad8c3cb..297d32a7e6 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/get_referent_nest.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_referent_nest.py @@ -20,18 +20,23 @@ import ifcopenshell from ifcopenshell import entity_instance -def get_referent_nest(file: ifcopenshell.file, entity: entity_instance) -> entity_instance: +def get_referent_nest(file: ifcopenshell.file, alignment: entity_instance) -> entity_instance: """ Searches for the IfcRelNest that contains IfcReferent. If one is not found, a empty IfcRelNests is created. :param file: - :param entity: any entity that is the parent in a nesting relationship, but intended to be IfcAlignment, IfcAlignmentHorizontal, IfcAlignmentVertical, or IfcAlignmentCant + :param alignment: The IfcAlignment which hosts IfcReferent :return: Returns the IfcRelNests. """ - for nest in entity.IsNestedBy: + if not alignment.is_a("IfcAlignment"): + raise TypeError( + f"Expected IfcAlignment, instead received {alignment.is_a()}" + ) + + for nest in alignment.IsNestedBy: for related_object in nest.RelatedObjects: if related_object.is_a("IfcReferent"): return nest - nest = file.createIfcRelNests(GlobalId=ifcopenshell.guid.new(), RelatingObject=entity, RelatedObjects=[]) + nest = file.createIfcRelNests(GlobalId=ifcopenshell.guid.new(), RelatingObject=alignment, RelatedObjects=[]) return nest diff --git a/src/ifcopenshell-python/test/api/alignment/test_add_segment_to_layout.py b/src/ifcopenshell-python/test/api/alignment/test_add_segment_to_layout.py index 6ca593f7dd..bea6f8989a 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_add_segment_to_layout.py +++ b/src/ifcopenshell-python/test/api/alignment/test_add_segment_to_layout.py @@ -67,11 +67,11 @@ def test_add_segment_to_layout(): _add_segment_to_layout(file, horizontal_alignment, alignment_segment) - assert len(horizontal_alignment.IsNestedBy) == 2 - referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, horizontal_alignment) + assert len(horizontal_alignment.IsNestedBy) == 1 segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(horizontal_alignment) assert len(segment_nest.RelatedObjects) == 2 - assert len(referent_nest.RelatedObjects) == 2 + referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, alignment) + assert len(referent_nest.RelatedObjects) == 3 test_add_segment_to_layout() diff --git a/src/ifcopenshell-python/test/api/alignment/test_add_stationing_to_alignment.py b/src/ifcopenshell-python/test/api/alignment/test_add_stationing_to_alignment.py index d4d75b31d5..0e8731d5f2 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_add_stationing_to_alignment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_add_stationing_to_alignment.py @@ -39,14 +39,17 @@ def test_add_stationing_to_alignment(): alignment = ifcopenshell.api.alignment.create(file, "TestAlignment", start_station=2000.0) - for rel in alignment.IsNestedBy: - for referent in rel.RelatedObjects: - if referent.is_a("IfcReferent"): - assert referent.PredefinedType == "STATION" - assert referent.Name == "2+000.000" - assert ifcopenshell.util.element.get_pset(element=referent, name="Pset_Stationing") - assert ( - ifcopenshell.util.element.get_pset(element=referent, name="Pset_Stationing", prop="Station") - == 2000.0 - ) - assert referent.ObjectPlacement != None + referent_nest = ifcopenshell.api.alignment.get_referent_nest(file,alignment) + referent = referent_nest.RelatedObjects[0] + + assert referent.PredefinedType == "STATION" + assert referent.Name == "2+000.000" + assert ifcopenshell.util.element.get_pset(element=referent, name="Pset_Stationing") + assert ( + ifcopenshell.util.element.get_pset(element=referent, name="Pset_Stationing", prop="Station") + == 2000.0 + ) + assert referent.ObjectPlacement != None + + +test_add_stationing_to_alignment() \ No newline at end of file diff --git a/src/ifcopenshell-python/test/api/alignment/test_add_vertical_alignment.py b/src/ifcopenshell-python/test/api/alignment/test_add_vertical_alignment.py index 70247f97e5..7d03dbcc2e 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_add_vertical_alignment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_add_vertical_alignment.py @@ -33,9 +33,13 @@ def test_add_vertical_alignment(): assert len(alignment.IsDecomposedBy) == 0 # no child alignments assert len(alignment.IsNestedBy) == 2 # nests for layout and referents - assert len(alignment.IsNestedBy[0].RelatedObjects) == 1 - assert ifcopenshell.api.alignment.get_referent_nest(file, alignment).RelatedObjects[0].is_a("IfcReferent") - assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcAlignmentHorizontal") + layout_nest = ifcopenshell.api.alignment.get_alignment_layout_nest(alignment) + assert len(layout_nest.RelatedObjects) == 1 + assert layout_nest.RelatedObjects[0].is_a("IfcAlignmentHorizontal") + referent_nest = ifcopenshell.api.alignment.get_referent_nest(file,alignment) + assert len(referent_nest.RelatedObjects) == 2 + assert referent_nest.RelatedObjects[0].is_a("IfcReferent") + curve = ifcopenshell.api.alignment.get_curve(alignment) assert curve.is_a("IfcCompositeCurve") @@ -43,9 +47,10 @@ def test_add_vertical_alignment(): assert len(alignment.IsDecomposedBy) == 0 # no child alignments assert len(alignment.IsNestedBy) == 2 - assert len(alignment.IsNestedBy[0].RelatedObjects) == 2 - assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcAlignmentHorizontal") - assert alignment.IsNestedBy[0].RelatedObjects[1].is_a("IfcAlignmentVertical") + assert len(layout_nest.RelatedObjects) == 2 + assert layout_nest.RelatedObjects[0].is_a("IfcAlignmentHorizontal") + assert layout_nest.RelatedObjects[1].is_a("IfcAlignmentVertical") + curve = ifcopenshell.api.alignment.get_curve(alignment) assert curve.is_a("IfcGradientCurve") @@ -57,13 +62,14 @@ def test_add_vertical_alignment(): for child_alignment in alignment.IsDecomposedBy[0].RelatedObjects: assert child_alignment.is_a("IfcAlignment") - assert len(child_alignment.IsNestedBy) == 1 # one nesting relationship for the IfcAlignmentVertical - assert len(child_alignment.IsNestedBy[0].RelatedObjects) == 1 # The IfcAlignmentVertical - assert child_alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcAlignmentVertical") + assert len(child_alignment.IsNestedBy) == 2 + child_layout_nest = ifcopenshell.api.alignment.get_alignment_layout_nest(child_alignment) + assert len(child_layout_nest.RelatedObjects) == 1 # The IfcAlignmentVertical + assert child_layout_nest.RelatedObjects[0].is_a("IfcAlignmentVertical") assert len(alignment.IsNestedBy) == 2 - assert len(alignment.IsNestedBy[0].RelatedObjects) == 1 - assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcAlignmentHorizontal") + assert len(layout_nest.RelatedObjects) == 1 + assert layout_nest.RelatedObjects[0].is_a("IfcAlignmentHorizontal") test_add_vertical_alignment() diff --git a/src/ifcopenshell-python/test/api/alignment/test_create_by_pi_method.py b/src/ifcopenshell-python/test/api/alignment/test_create_by_pi_method.py index 4b3b0d3c8d..1b088afd56 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_create_by_pi_method.py +++ b/src/ifcopenshell-python/test/api/alignment/test_create_by_pi_method.py @@ -51,17 +51,16 @@ def test_create_by_pi_method(): layout_nest = ifcopenshell.api.alignment.get_alignment_layout_nest(alignment) assert len(layout_nest.RelatedObjects) == 2 + referent_nest = ifcopenshell.api.alignment.get_referent_nest(file,alignment) + assert len(referent_nest.RelatedObjects) == 19 + horizontal_layout = ifcopenshell.api.alignment.get_horizontal_layout(alignment) horizontal_segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(horizontal_layout) assert len(horizontal_segment_nest.RelatedObjects) == 8 - horizontal_referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, horizontal_layout) - assert len(horizontal_referent_nest.RelatedObjects) == 8 vertical_layout = ifcopenshell.api.alignment.get_vertical_layout(alignment) vertical_segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(vertical_layout) assert len(vertical_segment_nest.RelatedObjects) == 10 - vertical_referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, vertical_layout) - assert len(vertical_referent_nest.RelatedObjects) == 10 test_create_by_pi_method() diff --git a/src/ifcopenshell-python/test/api/alignment/test_referent_names.py b/src/ifcopenshell-python/test/api/alignment/test_referent_names.py index 6939190d5f..a99afd8e55 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_referent_names.py +++ b/src/ifcopenshell-python/test/api/alignment/test_referent_names.py @@ -97,36 +97,16 @@ def callback_alignment(): def test_with_default_names(default_names_alignment): - hlayout = ifcopenshell.api.alignment.get_horizontal_layout(default_names_alignment) - referent_nest = ifcopenshell.api.alignment.get_referent_nest(None, hlayout) + referent_nest = ifcopenshell.api.alignment.get_referent_nest(None, default_names_alignment) - assert "P.O.B." in referent_nest.RelatedObjects[0].Name - assert "P.C." in referent_nest.RelatedObjects[1].Name - assert "P.T." in referent_nest.RelatedObjects[2].Name - assert "P.O.E." in referent_nest.RelatedObjects[-1].Name - - vlayout = ifcopenshell.api.alignment.get_vertical_layout(default_names_alignment) - referent_nest = ifcopenshell.api.alignment.get_referent_nest(None, vlayout) - - assert "V.P.O.B." in referent_nest.RelatedObjects[0].Name - assert "P.V.C." in referent_nest.RelatedObjects[1].Name - assert "P.V.T." in referent_nest.RelatedObjects[2].Name - assert "V.P.O.E." in referent_nest.RelatedObjects[-1].Name + expected = ["P.O.B", "P.C.", "P.T.", "P.O.E.", "V.P.O.B.", "P.V.C.", "P.V.T.", "V.P.O.E"] + for r in referent_nest.RelatedObjects: + assert [x in r.Name for x in expected] def test_with_callbacks(callback_alignment): - hlayout = ifcopenshell.api.alignment.get_horizontal_layout(callback_alignment) - referent_nest = ifcopenshell.api.alignment.get_referent_nest(None, hlayout) + referent_nest = ifcopenshell.api.alignment.get_referent_nest(None, callback_alignment) - assert "A" in referent_nest.RelatedObjects[0].Name - assert "Q" in referent_nest.RelatedObjects[1].Name - assert "Q" in referent_nest.RelatedObjects[2].Name - assert "Z" in referent_nest.RelatedObjects[-1].Name - - vlayout = ifcopenshell.api.alignment.get_vertical_layout(callback_alignment) - referent_nest = ifcopenshell.api.alignment.get_referent_nest(None, vlayout) - - assert "a" in referent_nest.RelatedObjects[0].Name - assert "q" in referent_nest.RelatedObjects[1].Name - assert "q" in referent_nest.RelatedObjects[2].Name - assert "z" in referent_nest.RelatedObjects[-1].Name + expected = ["A","Q","Z","a","q","z"] + for r in referent_nest.RelatedObjects: + assert [x in r.Name for x in expected] diff --git a/src/ifcopenshell-python/test/api/alignment/test_vertical_layout_by_pi_method.py b/src/ifcopenshell-python/test/api/alignment/test_vertical_layout_by_pi_method.py index 5315070937..8dab67c181 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_vertical_layout_by_pi_method.py +++ b/src/ifcopenshell-python/test/api/alignment/test_vertical_layout_by_pi_method.py @@ -58,11 +58,15 @@ def test_vertical_layout_by_pi_method(): ifcopenshell.api.alignment.layout_vertical_alignment_by_pi_method(file, vlayout, vpoints, lengths) assert len(alignment.IsDecomposedBy) == 0 # no child alignments + assert len(alignment.IsNestedBy) == 2 - referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, alignment) + layout_nest = ifcopenshell.api.alignment.get_alignment_layout_nest(alignment) - assert len(referent_nest.RelatedObjects) == 1 assert len(layout_nest.RelatedObjects) == 2 + + referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, alignment) + assert len(referent_nest.RelatedObjects) == 6 + segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(vlayout) assert len(segment_nest.RelatedObjects) == 3