Fix bug where migrating length units didn't change properties. Unit utility for checking attribute types now considers select types too

Changing properties is very critical for IFC2X3 georeferencing which is stored in a pset.
This commit is contained in:
Dion Moult
2024-06-29 17:04:27 +10:00
parent 2129350ab7
commit 0d401c9272
2 changed files with 32 additions and 2 deletions
@@ -749,10 +749,23 @@ def format_length(
def is_attr_type(
content_type: ifcopenshell_wrapper.parameter_type,
ifc_unit_type_name: str,
include_select_types: bool = True
) -> Union[ifcopenshell_wrapper.type_declaration, None]:
cur_decl = content_type
if include_select_types:
if hasattr(cur_decl, "select_list"):
for select_item in cur_decl.select_list():
if is_attr_type(select_item, ifc_unit_type_name):
return select_item
while hasattr(cur_decl, "declared_type") is True:
cur_decl = cur_decl.declared_type()
if include_select_types:
if hasattr(cur_decl, "select_list"):
for select_item in cur_decl.select_list():
if is_attr_type(select_item, ifc_unit_type_name):
return select_item
if hasattr(cur_decl, "name") is False:
continue
if cur_decl.name() == ifc_unit_type_name:
@@ -800,6 +813,9 @@ def iter_element_and_attributes_per_type(
if val is None:
continue
if isinstance(val, ifcopenshell.entity_instance) and not val.is_a(attr_type_name):
continue
yield element, attr, val
@@ -833,8 +849,12 @@ def convert_file_length_units(ifc_file: ifcopenshell.file, target_units: str = "
# Traverse all elements and their nested attributes in the file and convert them
for element, attr, val in iter_element_and_attributes_per_type(file_patched, "IfcLengthMeasure"):
new_value = convert_value(val)
setattr(element, attr.name(), new_value)
if isinstance(val, ifcopenshell.entity_instance):
new_value = convert_value(val.wrappedValue)
getattr(element, attr.name()).wrappedValue = new_value
else:
new_value = convert_value(val)
setattr(element, attr.name(), new_value)
file_patched.remove(old_length)
unit_assignment.Units = tuple([new_length, *unit_assignment.Units])
@@ -82,3 +82,13 @@ class TestFormatLength(test.bootstrap.IFC4):
assert (
subject.format_length(25.23, 4, unit_system="imperial", input_unit="inch", output_unit="inch") == '25 1/4"'
)
class TestIsAttrType(test.bootstrap.IFC4):
def test_run(self):
schema = ifcopenshell.schema_by_name("IFC4")
declaration = schema.declaration_by_name("IfcPropertySingleValue")
nominal_value = declaration.attribute_by_index(2).type_of_attribute()
assert subject.is_attr_type(nominal_value, "IfcValue")
assert subject.is_attr_type(nominal_value, "IfcLengthMeasure")
assert not subject.is_attr_type(nominal_value, "IfcLengthMeasure", include_select_types=False)