From 99640912c15a296d0cefc3b48386048f352fe1c5 Mon Sep 17 00:00:00 2001 From: Richard Brice <37087370+RickBrice@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:21:05 -0800 Subject: [PATCH] Adds alignment API function to get the alignment layout from one of its segments --- .../ifcopenshell/api/alignment/__init__.py | 2 + .../api/alignment/get_alignment_layout.py | 41 ++++++++++++++++ .../alignment/test_get_alignment_layout.py | 49 +++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_layout.py create mode 100644 src/ifcopenshell-python/test/api/alignment/test_get_alignment_layout.py diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/__init__.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/__init__.py index 42a5057c2e..977f4ac3b2 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/__init__.py @@ -63,6 +63,7 @@ from .create_segment_representations import create_segment_representations 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_layout import get_alignment_layout from .get_alignment_layouts import get_alignment_layouts from .get_alignment_segment_nest import get_alignment_segment_nest from .get_alignment_start_station import get_alignment_start_station @@ -107,6 +108,7 @@ __all__ = [ "distance_along_from_station", "get_alignment", "get_alignment_layout_nest", + "get_alignment_layout", "get_alignment_layouts", "get_alignment_segment_nest", "get_alignment_start_station", diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_layout.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_layout.py new file mode 100644 index 0000000000..fdf7d29138 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_alignment_layout.py @@ -0,0 +1,41 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2025 Thomas Krijnen +# +# 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 . + +from collections.abc import Sequence + +from ifcopenshell import entity_instance + + +def get_alignment_layout(segment: entity_instance) -> entity_instance: + """ + Returns the layout alignment that the segment is nested into + """ + expected_types = ["IfcAlignmentSegment"] + if not segment.is_a() in expected_types: + raise TypeError( + f"Expected entity type to be one of {[_ for _ in expected_types]}, instead received '{segment.is_a()}" + ) + + layout = None + layouts=["IfcAlignmentHorizontal","IfcAlignmentVertical","IfcAlignmentCant"] + for nest in segment.Nests: + if nest.RelatingObject.is_a() in layouts: + layout = nest.RelatingObject + break + + return layout diff --git a/src/ifcopenshell-python/test/api/alignment/test_get_alignment_layout.py b/src/ifcopenshell-python/test/api/alignment/test_get_alignment_layout.py new file mode 100644 index 0000000000..017b7eb58a --- /dev/null +++ b/src/ifcopenshell-python/test/api/alignment/test_get_alignment_layout.py @@ -0,0 +1,49 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2025 Thomas Krijnen +# +# 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 . + + +import ifcopenshell.api.alignment +import ifcopenshell.api.context +import ifcopenshell.api.unit + + +def test_get_alignment_layout(): + 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]) + geometric_representation_context = ifcopenshell.api.context.add_context(file, context_type="Model") + axis_model_representation_subcontext = ifcopenshell.api.context.add_context( + file, + context_type="Model", + context_identifier="Axis", + target_view="MODEL_VIEW", + parent=geometric_representation_context, + ) + + alignment = ifcopenshell.api.alignment.create(file,"Test",include_vertical=True,include_cant=True) + horiz = ifcopenshell.api.alignment.get_horizontal_layout(alignment) + vert = ifcopenshell.api.alignment.get_vertical_layout(alignment) + cant = ifcopenshell.api.alignment.get_cant_layout(alignment) + + assert horiz == ifcopenshell.api.alignment.get_alignment_layout(horiz.IsNestedBy[0].RelatedObjects[0]) + assert vert == ifcopenshell.api.alignment.get_alignment_layout(vert.IsNestedBy[0].RelatedObjects[0]) + assert cant == ifcopenshell.api.alignment.get_alignment_layout(cant.IsNestedBy[0].RelatedObjects[0]) + + +test_get_alignment_layout() \ No newline at end of file