This commit is contained in:
Ryan Schultz
2025-10-30 17:04:29 -05:00
parent 768c779e91
commit ca382f47df
+25 -9
View File
@@ -92,24 +92,40 @@ def quantify(ifc_file: ifcopenshell.file, elements: set[ifcopenshell.entity_inst
for calculator, queries in rules["calculators"].items():
calculator = calculators[calculator]
if not set(m.lower() for m in queries.keys()) - lower_case_entity_names(ifc_file.schema_identifier):
# all defined queries are actually simple entity names: instead of looping over all
# calculators we loop over the entity types so that we don't have to repeatedly query
# the model, especially when the set of elements is small.
# Cache schema entity names once per file
schema_entity_names = lower_case_entity_names(ifc_file.schema_identifier)
# Fast path: all queries are simple entity names
if not set(m.lower() for m in queries.keys()) - schema_entity_names:
casenorm = {k.lower(): k for k in queries.keys()}
pred = lambda inst: inst.is_a().lower()
for ty, elements in itertools.groupby(sorted(elements, key=pred), key=pred):
for ty, group in itertools.groupby(sorted(elements, key=pred), key=pred):
group_elements = list(group)
# check entity type and its supertypes for matching QTO rules
for sty in entity_supertypes(ifc_file.schema_identifier, ty):
if qtos := queries.get(casenorm.get(sty)):
calculator.calculate(ifc_file, list(elements), qtos, results)
calculator.calculate(ifc_file, group_elements, qtos, results)
# Fallback: per-query evaluation
for query, qtos in queries.items():
if query.lower() in lower_case_entity_names(ifc_file.schema_identifier):
# by_type is faster than selector parsing
filtered_elements = ifc_file.by_type(query)
# Simple entity name: use by_type but restrict to incoming elements
if query.lower() in schema_entity_names:
by_type_all = ifc_file.by_type(query)
# ensure we don't expand beyond provided elements subset
if isinstance(elements, set):
filtered_elements = [e for e in by_type_all if e in elements]
else:
elements_set = set(elements)
filtered_elements = [e for e in by_type_all if e in elements_set]
else:
filtered_elements = ifcopenshell.util.selector.filter_elements(ifc_file, query, elements)
if filtered_elements:
calculator.calculate(ifc_file, filtered_elements, qtos, results)
return results