From a839183ac290fdbc46b9f5fdd5396c4f60f53bfa Mon Sep 17 00:00:00 2001 From: Richard Brice <37087370+RickBrice@users.noreply.github.com> Date: Fri, 29 Aug 2025 14:37:17 -0700 Subject: [PATCH] Fixes referent sorting --- .../api/alignment/_add_segment_to_layout.py | 1 - .../api/alignment/add_stationing_referent.py | 24 ++++++++++--------- .../api/alignment/add_vertical_layout.py | 9 ++++--- .../api/alignment/add_zero_length_segment.py | 4 +++- .../ifcopenshell/api/alignment/create.py | 2 +- .../api/alignment/create_as_polyline.py | 1 - .../api/alignment/get_referent_nest.py | 6 ++--- .../test_add_stationing_to_alignment.py | 9 +++---- .../alignment/test_add_vertical_alignment.py | 2 +- .../api/alignment/test_create_by_pi_method.py | 2 +- .../test/api/alignment/test_referent_names.py | 2 +- 11 files changed, 29 insertions(+), 33 deletions(-) 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 6ab52af076..88b68ff674 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 @@ -179,7 +179,6 @@ def _add_segment_to_layout(file: ifcopenshell.file, layout: entity_instance, seg referent = ifcopenshell.api.alignment.add_stationing_referent( file, alignment, 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 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 fe53ef5ca5..1534ad9d5d 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py @@ -105,22 +105,22 @@ def add_stationing_referent( 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. + x = 0.0 + y = 0.0 + z = 0.0 + rx = 1.0 + ry = 0.0 + rz = 0.0 + ax = 0.0 + ay = 0.0 + az = 1.0 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( @@ -146,7 +146,9 @@ def add_stationing_referent( 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")) + 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( 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 ffbd6b0870..06c1ef9fa8 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_vertical_layout.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_vertical_layout.py @@ -54,18 +54,17 @@ def _move_vertical_layout_to_child_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) + 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 + # 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]) + 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 fbb159426a..fc2fcb2c0e 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 @@ -233,7 +233,9 @@ def add_zero_length_segment(file: ifcopenshell.file, layout: entity_instance, in alignment = ifcopenshell.api.alignment.get_alignment(layout) 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)})" - referent = ifcopenshell.api.alignment.add_stationing_referent(file, alignment, 0.0, station, name, zero_length_curve_segment) + 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 af106a584b..cd707920c0 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py @@ -79,7 +79,7 @@ def create( if include_geometry: _create_geometric_representation(file, alignment) - + 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 diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_polyline.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_polyline.py index d8c48d1b3c..1048f1fa69 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_polyline.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_polyline.py @@ -142,7 +142,6 @@ def create_as_polyline( # 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) - 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] 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 297d32a7e6..b57b787e38 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/get_referent_nest.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_referent_nest.py @@ -29,10 +29,8 @@ def get_referent_nest(file: ifcopenshell.file, alignment: entity_instance) -> en :return: Returns the IfcRelNests. """ if not alignment.is_a("IfcAlignment"): - raise TypeError( - f"Expected IfcAlignment, instead received {alignment.is_a()}" - ) - + 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"): 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 0e8731d5f2..49cbd70367 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,17 +39,14 @@ def test_add_stationing_to_alignment(): alignment = ifcopenshell.api.alignment.create(file, "TestAlignment", start_station=2000.0) - referent_nest = ifcopenshell.api.alignment.get_referent_nest(file,alignment) + 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 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 +test_add_stationing_to_alignment() 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 7d03dbcc2e..243188866c 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 @@ -36,7 +36,7 @@ def test_add_vertical_alignment(): 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) + referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, alignment) assert len(referent_nest.RelatedObjects) == 2 assert referent_nest.RelatedObjects[0].is_a("IfcReferent") 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 1b088afd56..bd3a25faed 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,7 +51,7 @@ 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) + 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) 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 a99afd8e55..2e0e50a683 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_referent_names.py +++ b/src/ifcopenshell-python/test/api/alignment/test_referent_names.py @@ -107,6 +107,6 @@ def test_with_default_names(default_names_alignment): def test_with_callbacks(callback_alignment): referent_nest = ifcopenshell.api.alignment.get_referent_nest(None, callback_alignment) - expected = ["A","Q","Z","a","q","z"] + expected = ["A", "Q", "Z", "a", "q", "z"] for r in referent_nest.RelatedObjects: assert [x in r.Name for x in expected]