set_element_value - optimizations setting enum values

1) Identify from previous pset value whether prop was an enum (by checking if previous value is a list), instead of searching through prop templates

2) Compare previous and new enum values - if they match, skip editing IFC.
This commit is contained in:
Andrej730
2024-12-06 16:30:43 +05:00
parent c7af55183b
commit 2da5f2d61e
@@ -17,6 +17,7 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import re
import types
import lark
import numpy as np
import ifcopenshell.api.pset
@@ -466,7 +467,12 @@ class SetElementValueException(Exception): ...
def set_element_value(
ifc_file: ifcopenshell.file,
element: Union[ifcopenshell.entity_instance, Iterable[ifcopenshell.entity_instance], None],
element: Union[
ifcopenshell.entity_instance,
dict[str, Any],
Iterable[ifcopenshell.entity_instance],
None,
],
query: Union[str, list[str]],
value: Any,
*,
@@ -656,14 +662,30 @@ def set_element_value(
ifcopenshell.api.pset.edit_qto(ifc_file, qto=pset, properties={prop: float(value)})
elif pset.is_a("IfcPropertySet") and element.get(key, None) != value:
def process_pset_prop_value(pset: ifcopenshell.entity_instance, prop: str, value: Any) -> Any:
def process_pset_prop_value(
pset: ifcopenshell.entity_instance, prop: str, value: Any
) -> Union[Any, types.EllipsisType]:
"""Try to process value for edit_pset.
`edit_pset` is expecting a sequence of values
for enum properties, not just a string of some-symbol-separated values.
Return `...` if property can be skipped as it has the same value.
"""
if not isinstance(value, str):
return value
current_value = element.get(key, ...)
# Check if previous value is a list as a fast way to identify enum properties.
if not isinstance(current_value, (types.EllipsisType, list)):
return value
if isinstance(current_value, list):
# Value won't change, safe to skip editing IFC.
enum_values = value.split(concat)
if len(enum_values) == len(current_value) and set(enum_values) == set(current_value):
return ...
template = ifcopenshell.util.pset.get_template(ifc_file.schema)
pset_template = template.get_by_name(pset.Name)
if pset_template is None:
@@ -704,6 +726,8 @@ def set_element_value(
return value
value = process_pset_prop_value(pset, key, value)
if value == ...:
return
ifcopenshell.api.pset.edit_pset(ifc_file, pset=pset, properties={key: value})
elif pset.is_a("IfcElementQuantity"):
try: