Merge remote-tracking branch 'origin/v0.8.0' into tfk-rocksdb-storage

This commit is contained in:
Thomas Krijnen
2025-08-31 16:06:07 +02:00
52 changed files with 10039 additions and 450 deletions
@@ -68,13 +68,10 @@ def test_add_segment_to_layout():
_add_segment_to_layout(file, horizontal_alignment, alignment_segment)
assert len(horizontal_alignment.IsNestedBy) == 1
assert (
len(horizontal_alignment.IsNestedBy[0].RelatedObjects) == 2
) # The the segment we added and the automatically created zero length segment
assert horizontal_alignment.IsNestedBy[0].RelatedObjects[0] == alignment_segment
assert (
alignment_segment.IsNestedBy[0].RelatedObjects[0].is_a("IfcReferent")
) # a referent is automatically added at the start of the segment
segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(horizontal_alignment)
assert len(segment_nest.RelatedObjects) == 2
referent_nest = ifcopenshell.api.alignment.get_referent_nest(file, alignment)
assert len(referent_nest.RelatedObjects) == 3
test_add_segment_to_layout()
@@ -39,14 +39,14 @@ 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()
@@ -32,23 +32,25 @@ def test_add_vertical_alignment():
alignment = ifcopenshell.api.alignment.create(file, "A1", include_vertical=False)
assert len(alignment.IsDecomposedBy) == 0 # no child alignments
assert len(alignment.IsNestedBy) == 1 # one nest
assert len(alignment.IsNestedBy[0].RelatedObjects) == 2 # nesting IfcReferent, IfcAlignmentHorizontal
assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcReferent")
assert alignment.IsNestedBy[0].RelatedObjects[1].is_a("IfcAlignmentHorizontal")
assert len(alignment.IsNestedBy) == 2 # nests for layout and referents
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")
vertical_layout = ifcopenshell.api.alignment.add_vertical_layout(file, alignment)
assert len(alignment.IsDecomposedBy) == 0 # no child alignments
assert len(alignment.IsNestedBy) == 1 # one nest
assert (
len(alignment.IsNestedBy[0].RelatedObjects) == 3
) # nesting IfcReferent, IfcAlignmentHorizontal, IfcAlignmentVertical
assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcReferent")
assert alignment.IsNestedBy[0].RelatedObjects[1].is_a("IfcAlignmentHorizontal")
assert alignment.IsNestedBy[0].RelatedObjects[2].is_a("IfcAlignmentVertical")
assert len(alignment.IsNestedBy) == 2
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")
@@ -56,20 +58,18 @@ def test_add_vertical_alignment():
vertical_layout = ifcopenshell.api.alignment.add_vertical_layout(file, alignment)
assert len(alignment.IsDecomposedBy) == 1 # 1 IfcRelAggreates relationship for the child algiments
assert (
len(alignment.IsDecomposedBy[0].RelatedObjects) == 2
) # two child alignments, one for the first vertical and one for the vertical just added
assert len(alignment.IsDecomposedBy[0].RelatedObjects) == 2
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) == 1 # 1 nesting relationsip for the alignments
assert len(alignment.IsNestedBy[0].RelatedObjects) == 2 # nesting IfcReferent and IfcAlignmentHorizontal
assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcReferent")
assert alignment.IsNestedBy[0].RelatedObjects[1].is_a("IfcAlignmentHorizontal")
assert len(alignment.IsNestedBy) == 2
assert len(layout_nest.RelatedObjects) == 1
assert layout_nest.RelatedObjects[0].is_a("IfcAlignmentHorizontal")
test_add_vertical_alignment()
@@ -46,22 +46,21 @@ def test_create_by_pi_method():
)
assert len(alignment.IsDecomposedBy) == 0 # no child alignments
assert len(alignment.IsNestedBy) == 1 # one nest
assert (
len(alignment.IsNestedBy[0].RelatedObjects) == 3
) # nesting IfcReferent, IfcAlignmentHorizontal, IfcAlignmentVertical
assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcReferent")
assert alignment.IsNestedBy[0].RelatedObjects[1].is_a("IfcAlignmentHorizontal")
assert alignment.IsNestedBy[0].RelatedObjects[2].is_a("IfcAlignmentVertical")
assert (
len(alignment.IsNestedBy[0].RelatedObjects[1].IsNestedBy) == 1
) # nesting of segments beneath IfcAlignmentHorizontal
assert (
len(alignment.IsNestedBy[0].RelatedObjects[1].IsNestedBy[0].RelatedObjects) == 8
) # segments in horizontal layout
assert (
len(alignment.IsNestedBy[0].RelatedObjects[2].IsNestedBy[0].RelatedObjects) == 10
) # segments in vertical layout
assert len(alignment.IsNestedBy) == 2
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
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
test_create_by_pi_method()
@@ -0,0 +1,68 @@
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2025 Thomas Krijnen <thomas@aecgeeks.com>
#
# 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 <http://www.gnu.org/licenses/>.
import pytest
import ifcopenshell.api.alignment
import ifcopenshell.api.context
import ifcopenshell.api.unit
def test_create_no_geometry():
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])
# creates an IfcAlignment with an IfcAlignmentHorizontal layout containing only the zero length segment
ali = ifcopenshell.api.alignment.create(file, "A1", include_vertical=True, include_geometry=False)
# append a segment to the horizontal layout
horizontal_alignment = ifcopenshell.api.alignment.get_horizontal_layout(ali)
vertical_alignment = ifcopenshell.api.alignment.get_vertical_layout(ali)
curve = ifcopenshell.api.alignment.get_curve(ali)
assert curve == None
design_parameters = file.create_entity(
type="IfcAlignmentHorizontalSegment",
StartTag=None,
EndTag=None,
StartPoint=file.createIfcCartesianPoint(Coordinates=((0.0, 0.0))),
StartDirection=0.0,
StartRadiusOfCurvature=0.0,
EndRadiusOfCurvature=0.0,
SegmentLength=100.0,
GravityCenterLineHeight=None,
PredefinedType="LINE",
)
end = ifcopenshell.api.alignment.create_layout_segment(file, horizontal_alignment, design_parameters)
assert end == None
design_parameters = file.createIfcAlignmentVerticalSegment(
StartDistAlong=0.0,
HorizontalLength=50.0,
StartHeight=20.0,
StartGradient=1.0 / 100.0,
EndGradient=1.0 / 100.0,
PredefinedType="CONSTANTGRADIENT",
)
end = ifcopenshell.api.alignment.create_layout_segment(file, vertical_alignment, design_parameters)
assert end == None
test_create_no_geometry()
@@ -45,16 +45,13 @@ def test_horizontal_layout_by_pi_method():
alignment = ifcopenshell.api.alignment.create_by_pi_method(file, "TestAlignment", coordinates, radii)
assert len(alignment.IsDecomposedBy) == 0 # no child alignments
assert len(alignment.IsNestedBy) == 1 # one nest
assert len(alignment.IsNestedBy[0].RelatedObjects) == 2 # nesting IfcReferent, IfcAlignmentHorizontal
assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcReferent")
assert alignment.IsNestedBy[0].RelatedObjects[1].is_a("IfcAlignmentHorizontal")
assert (
len(alignment.IsNestedBy[0].RelatedObjects[1].IsNestedBy) == 1
) # nesting of segments beneath IfcAlignmentHorizontal
assert (
len(alignment.IsNestedBy[0].RelatedObjects[1].IsNestedBy[0].RelatedObjects) == 3
) # segments in horizontal layout
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 referent_nest.RelatedObjects[0].is_a("IfcReferent")
assert layout_nest.RelatedObjects[0].is_a("IfcAlignmentHorizontal")
segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(layout_nest.RelatedObjects[0])
assert len(segment_nest.RelatedObjects) == 3 # segments in horizontal layout
test_horizontal_layout_by_pi_method()
@@ -45,12 +45,15 @@ def test_name_segments():
file, "TestAlignment", coordinates, radii, vpoints, lengths
)
for rel in alignment.IsNestedBy:
for a in rel.RelatedObjects:
if a.is_a("IfcLinearElement"):
ifcopenshell.api.alignment.name_segments("Q", a)
i = 1
for sr in a.IsNestedBy:
for s in sr.RelatedObjects:
assert f"Q{i}" == s.Name
i += 1
layout_nest = ifcopenshell.api.alignment.get_alignment_layout_nest(alignment)
for layout in layout_nest.RelatedObjects:
assert layout.is_a("IfcLinearElement")
ifcopenshell.api.alignment.name_segments("Q", layout)
segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(layout)
i = 1
for segment in segment_nest.RelatedObjects:
assert f"Q{i}" == segment.Name
i += 1
test_name_segments()
@@ -97,32 +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, default_names_alignment)
assert "P.O.B." in hlayout.IsNestedBy[0].RelatedObjects[0].IsNestedBy[0].RelatedObjects[0].Name
assert "P.C." in hlayout.IsNestedBy[0].RelatedObjects[1].IsNestedBy[0].RelatedObjects[0].Name
assert "P.T." in hlayout.IsNestedBy[0].RelatedObjects[2].IsNestedBy[0].RelatedObjects[0].Name
assert "P.O.E." in hlayout.IsNestedBy[0].RelatedObjects[-1].IsNestedBy[0].RelatedObjects[0].Name
vlayout = ifcopenshell.api.alignment.get_vertical_layout(default_names_alignment)
assert "V.P.O.B." in vlayout.IsNestedBy[0].RelatedObjects[0].IsNestedBy[0].RelatedObjects[0].Name
assert "P.V.C." in vlayout.IsNestedBy[0].RelatedObjects[1].IsNestedBy[0].RelatedObjects[0].Name
assert "P.V.T." in vlayout.IsNestedBy[0].RelatedObjects[2].IsNestedBy[0].RelatedObjects[0].Name
assert "V.P.O.E." in vlayout.IsNestedBy[0].RelatedObjects[-1].IsNestedBy[0].RelatedObjects[0].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, callback_alignment)
assert "A" in hlayout.IsNestedBy[0].RelatedObjects[0].IsNestedBy[0].RelatedObjects[0].Name
assert "Q" in hlayout.IsNestedBy[0].RelatedObjects[1].IsNestedBy[0].RelatedObjects[0].Name
assert "Q" in hlayout.IsNestedBy[0].RelatedObjects[2].IsNestedBy[0].RelatedObjects[0].Name
assert "Z" in hlayout.IsNestedBy[0].RelatedObjects[-1].IsNestedBy[0].RelatedObjects[0].Name
vlayout = ifcopenshell.api.alignment.get_vertical_layout(callback_alignment)
assert "a" in vlayout.IsNestedBy[0].RelatedObjects[0].IsNestedBy[0].RelatedObjects[0].Name
assert "q" in vlayout.IsNestedBy[0].RelatedObjects[1].IsNestedBy[0].RelatedObjects[0].Name
assert "q" in vlayout.IsNestedBy[0].RelatedObjects[2].IsNestedBy[0].RelatedObjects[0].Name
assert "z" in vlayout.IsNestedBy[0].RelatedObjects[-1].IsNestedBy[0].RelatedObjects[0].Name
expected = ["A", "Q", "Z", "a", "q", "z"]
for r in referent_nest.RelatedObjects:
assert [x in r.Name for x in expected]
@@ -58,22 +58,17 @@ 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) == 1 # one nest
assert (
len(alignment.IsNestedBy[0].RelatedObjects) == 3
) # nesting IfcReferent, IfcAlignmentHorizontal, IfcAlignmentVertical
assert alignment.IsNestedBy[0].RelatedObjects[0].is_a("IfcReferent")
assert alignment.IsNestedBy[0].RelatedObjects[1].is_a("IfcAlignmentHorizontal")
assert alignment.IsNestedBy[0].RelatedObjects[2].is_a("IfcAlignmentVertical")
assert (
len(alignment.IsNestedBy[0].RelatedObjects[1].IsNestedBy) == 1
) # nesting of segments beneath IfcAlignmentHorizontal
assert (
len(alignment.IsNestedBy[0].RelatedObjects[1].IsNestedBy[0].RelatedObjects) == 2
) # segments in horizontal layout
assert (
len(alignment.IsNestedBy[0].RelatedObjects[2].IsNestedBy[0].RelatedObjects) == 3
) # segments in vertical layout
assert len(alignment.IsNestedBy) == 2
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) == 6
segment_nest = ifcopenshell.api.alignment.get_alignment_segment_nest(vlayout)
assert len(segment_nest.RelatedObjects) == 3
test_vertical_layout_by_pi_method()