mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
Updates update_key_point_referents to confirm to CT 4.1.4.4.3
This commit is contained in:
@@ -32,21 +32,6 @@ from ifcopenshell.api.alignment._sort_nest import _sort_nest
|
|||||||
from ifcopenshell.api.alignment.update_fallback_position import update_fallback_position
|
from ifcopenshell.api.alignment.update_fallback_position import update_fallback_position
|
||||||
|
|
||||||
|
|
||||||
def _get_key_point_referent_nest(layout: entity_instance) -> Optional[entity_instance]:
|
|
||||||
"""
|
|
||||||
Searches layout.IsNestedBy for the IfcRelNests whose RelatedObjects are IfcReferent.
|
|
||||||
|
|
||||||
This is distinct from both get_stationing_nest (scoped to the parent IfcAlignment, and
|
|
||||||
specifically the STATION/station-equation nest) and get_alignment_segment_nest (the *segment*
|
|
||||||
nest that also lives on layout.IsNestedBy, holding IfcAlignmentSegment, never IfcReferent).
|
|
||||||
"""
|
|
||||||
for nest in layout.IsNestedBy:
|
|
||||||
for related_object in nest.RelatedObjects:
|
|
||||||
if related_object.is_a("IfcReferent"):
|
|
||||||
return nest
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _remove_referent(file: ifcopenshell.file, referent: entity_instance) -> None:
|
def _remove_referent(file: ifcopenshell.file, referent: entity_instance) -> None:
|
||||||
"""Cleanly deletes a key-point IfcReferent: its Pset_Stationing, its ObjectPlacement (if
|
"""Cleanly deletes a key-point IfcReferent: its Pset_Stationing, its ObjectPlacement (if
|
||||||
exclusively owned by it), and finally the referent itself."""
|
exclusively owned by it), and finally the referent itself."""
|
||||||
@@ -129,9 +114,11 @@ def update_key_point_referents(
|
|||||||
get_stationing_nest) -- key-point referents never belong in either of those.
|
get_stationing_nest) -- key-point referents never belong in either of those.
|
||||||
|
|
||||||
:param layout: IfcAlignmentHorizontal, IfcAlignmentVertical, or IfcAlignmentCant
|
:param layout: IfcAlignmentHorizontal, IfcAlignmentVertical, or IfcAlignmentCant
|
||||||
:param rel_nests: an existing IfcRelNests to (re)populate. May live anywhere (e.g. the parent
|
:param rel_nests: an existing IfcRelNests to (re)populate; its RelatingObject must be the
|
||||||
IfcAlignment, the layout, or elsewhere) -- the caller decides. If omitted, an existing
|
IfcAlignment that nests `layout` (TypeError is raised otherwise). If omitted, a new
|
||||||
referent-nest already on `layout` is reused, or a new one is created and related to `layout`.
|
IfcRelNests is always created and related to that IfcAlignment -- there is no implicit
|
||||||
|
search for or reuse of a previously created nest. Callers who want to regenerate into an
|
||||||
|
existing nest must pass it back in explicitly via `rel_nests`.
|
||||||
:param clear: if True, deletes all IfcReferent currently in rel_nests.RelatedObjects (and their
|
:param clear: if True, deletes all IfcReferent currently in rel_nests.RelatedObjects (and their
|
||||||
Pset_Stationing) before regenerating. If False (default), new referents are appended to
|
Pset_Stationing) before regenerating. If False (default), new referents are appended to
|
||||||
whatever already exists -- no deduplication.
|
whatever already exists -- no deduplication.
|
||||||
@@ -167,12 +154,20 @@ def update_key_point_referents(
|
|||||||
f"Expected entity type to be one of {[_ for _ in expected_types]}, instead received {layout.is_a()}"
|
f"Expected entity type to be one of {[_ for _ in expected_types]}, instead received {layout.is_a()}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if rel_nests is None:
|
alignment = ifcopenshell.api.alignment.get_alignment(layout)
|
||||||
rel_nests = _get_key_point_referent_nest(layout)
|
if alignment is None:
|
||||||
if rel_nests is None:
|
raise ValueError(f"{layout.is_a()} #{layout.id()} is not nested under an IfcAlignment.")
|
||||||
rel_nests = file.createIfcRelNests(
|
|
||||||
GlobalId=ifcopenshell.guid.new(), RelatingObject=layout, RelatedObjects=()
|
if rel_nests is not None:
|
||||||
|
if not rel_nests.RelatingObject.is_a("IfcAlignment"):
|
||||||
|
raise TypeError(
|
||||||
|
f"Expected rel_nests.RelatingObject to be IfcAlignment, instead received "
|
||||||
|
f"{rel_nests.RelatingObject.is_a()}"
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
rel_nests = file.createIfcRelNests(
|
||||||
|
GlobalId=ifcopenshell.guid.new(), RelatingObject=alignment, RelatedObjects=()
|
||||||
|
)
|
||||||
|
|
||||||
if clear:
|
if clear:
|
||||||
for referent in list(rel_nests.RelatedObjects):
|
for referent in list(rel_nests.RelatedObjects):
|
||||||
@@ -189,7 +184,6 @@ def update_key_point_referents(
|
|||||||
)
|
)
|
||||||
return rel_nests
|
return rel_nests
|
||||||
|
|
||||||
alignment = ifcopenshell.api.alignment.get_alignment(layout)
|
|
||||||
start_station = ifcopenshell.api.alignment.get_alignment_start_station(file, alignment)
|
start_station = ifcopenshell.api.alignment.get_alignment_start_station(file, alignment)
|
||||||
curve = ifcopenshell.api.alignment.get_layout_curve(layout)
|
curve = ifcopenshell.api.alignment.get_layout_curve(layout)
|
||||||
is_horizontal = layout.is_a("IfcAlignmentHorizontal")
|
is_horizontal = layout.is_a("IfcAlignmentHorizontal")
|
||||||
|
|||||||
@@ -82,13 +82,13 @@ def test_default_rel_nests_created_when_none_provided():
|
|||||||
nest = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal)
|
nest = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal)
|
||||||
|
|
||||||
assert nest.is_a("IfcRelNests")
|
assert nest.is_a("IfcRelNests")
|
||||||
assert nest.RelatingObject == horizontal
|
assert nest.RelatingObject == alignment
|
||||||
assert nest.id() != segment_nest.id()
|
assert nest.id() != segment_nest.id()
|
||||||
assert len(nest.RelatedObjects) == 8
|
assert len(nest.RelatedObjects) == 8
|
||||||
assert all(r.is_a("IfcReferent") for r in nest.RelatedObjects)
|
assert all(r.is_a("IfcReferent") for r in nest.RelatedObjects)
|
||||||
|
|
||||||
|
|
||||||
def test_second_call_without_rel_nests_reuses_existing_nest():
|
def test_second_call_without_rel_nests_creates_separate_nest():
|
||||||
file = _new_file()
|
file = _new_file()
|
||||||
alignment = _build_alignment(file)
|
alignment = _build_alignment(file)
|
||||||
horizontal = ifcopenshell.api.alignment.get_horizontal_layout(alignment)
|
horizontal = ifcopenshell.api.alignment.get_horizontal_layout(alignment)
|
||||||
@@ -97,18 +97,31 @@ def test_second_call_without_rel_nests_reuses_existing_nest():
|
|||||||
nest1 = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal)
|
nest1 = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal)
|
||||||
nest2 = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal)
|
nest2 = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal)
|
||||||
|
|
||||||
assert nest1.id() == nest2.id()
|
assert nest1.id() != nest2.id()
|
||||||
assert len(nest2.RelatedObjects) == 16
|
assert len(nest1.RelatedObjects) == 8
|
||||||
|
assert len(nest2.RelatedObjects) == 8
|
||||||
segment_count_after = len(ifcopenshell.api.alignment.get_alignment_segment_nest(horizontal).RelatedObjects)
|
segment_count_after = len(ifcopenshell.api.alignment.get_alignment_segment_nest(horizontal).RelatedObjects)
|
||||||
assert segment_count_after == segment_count_before
|
assert segment_count_after == segment_count_before
|
||||||
|
|
||||||
|
|
||||||
|
def test_passing_previous_nest_back_in_accumulates():
|
||||||
|
file = _new_file()
|
||||||
|
alignment = _build_alignment(file)
|
||||||
|
horizontal = ifcopenshell.api.alignment.get_horizontal_layout(alignment)
|
||||||
|
|
||||||
|
nest1 = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal)
|
||||||
|
nest2 = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal, rel_nests=nest1)
|
||||||
|
|
||||||
|
assert nest1.id() == nest2.id()
|
||||||
|
assert len(nest2.RelatedObjects) == 16
|
||||||
|
|
||||||
|
|
||||||
def test_provided_rel_nests_is_used_as_is():
|
def test_provided_rel_nests_is_used_as_is():
|
||||||
file = _new_file()
|
file = _new_file()
|
||||||
alignment = _build_alignment(file)
|
alignment = _build_alignment(file)
|
||||||
horizontal = ifcopenshell.api.alignment.get_horizontal_layout(alignment)
|
horizontal = ifcopenshell.api.alignment.get_horizontal_layout(alignment)
|
||||||
|
|
||||||
# the nest may live anywhere the caller chooses, e.g. hung off the parent IfcAlignment
|
# rel_nests.RelatingObject must be the IfcAlignment that nests `layout`
|
||||||
rel_nests = file.createIfcRelNests(GlobalId=ifcopenshell.guid.new(), RelatingObject=alignment, RelatedObjects=())
|
rel_nests = file.createIfcRelNests(GlobalId=ifcopenshell.guid.new(), RelatingObject=alignment, RelatedObjects=())
|
||||||
|
|
||||||
result = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal, rel_nests=rel_nests)
|
result = ifcopenshell.api.alignment.update_key_point_referents(file, horizontal, rel_nests=rel_nests)
|
||||||
@@ -118,6 +131,17 @@ def test_provided_rel_nests_is_used_as_is():
|
|||||||
assert len(result.RelatedObjects) == 8
|
assert len(result.RelatedObjects) == 8
|
||||||
|
|
||||||
|
|
||||||
|
def test_provided_rel_nests_with_wrong_relating_object_raises_type_error():
|
||||||
|
file = _new_file()
|
||||||
|
alignment = _build_alignment(file)
|
||||||
|
horizontal = ifcopenshell.api.alignment.get_horizontal_layout(alignment)
|
||||||
|
|
||||||
|
rel_nests = file.createIfcRelNests(GlobalId=ifcopenshell.guid.new(), RelatingObject=horizontal, RelatedObjects=())
|
||||||
|
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ifcopenshell.api.alignment.update_key_point_referents(file, horizontal, rel_nests=rel_nests)
|
||||||
|
|
||||||
|
|
||||||
def test_clear_true_removes_old_referents_and_psets():
|
def test_clear_true_removes_old_referents_and_psets():
|
||||||
file = _new_file()
|
file = _new_file()
|
||||||
alignment = _build_alignment(file)
|
alignment = _build_alignment(file)
|
||||||
@@ -356,8 +380,10 @@ def test_returns_ifc_rel_nests():
|
|||||||
|
|
||||||
test_wrong_layout_type_raises_type_error()
|
test_wrong_layout_type_raises_type_error()
|
||||||
test_default_rel_nests_created_when_none_provided()
|
test_default_rel_nests_created_when_none_provided()
|
||||||
test_second_call_without_rel_nests_reuses_existing_nest()
|
test_second_call_without_rel_nests_creates_separate_nest()
|
||||||
|
test_passing_previous_nest_back_in_accumulates()
|
||||||
test_provided_rel_nests_is_used_as_is()
|
test_provided_rel_nests_is_used_as_is()
|
||||||
|
test_provided_rel_nests_with_wrong_relating_object_raises_type_error()
|
||||||
test_clear_true_removes_old_referents_and_psets()
|
test_clear_true_removes_old_referents_and_psets()
|
||||||
test_clear_false_appends_without_dedup()
|
test_clear_false_appends_without_dedup()
|
||||||
test_default_horizontal_labels_and_order()
|
test_default_horizontal_labels_and_order()
|
||||||
|
|||||||
Reference in New Issue
Block a user