New recipe to clean up IFCs that store quantities in properties.

This commit is contained in:
Dion Moult
2021-05-10 09:27:31 +10:00
parent e98771ae09
commit 19e67613db
3 changed files with 63 additions and 1 deletions
@@ -22,6 +22,7 @@ class Usecase:
"RelatingPropertyDefinition": pset,
}
)
return pset
elif self.settings["product"].is_a("IfcTypeObject"):
pset = self.file.create_entity(
"IfcPropertySet", **{"GlobalId": ifcopenshell.guid.new(), "Name": self.settings["Name"]}
@@ -29,8 +30,9 @@ class Usecase:
has_property_sets = list(self.settings["product"].HasPropertySets or [])
has_property_sets.append(pset)
self.settings["product"].HasPropertySets = has_property_sets
return pset
elif self.settings["product"].is_a("IfcMaterialDefinition"):
pset = self.file.create_entity(
return self.file.create_entity(
"IfcMaterialProperties",
**{
"Name": self.settings["Name"],
@@ -22,3 +22,4 @@ class Usecase:
"RelatingPropertyDefinition": qto,
}
)
return qto
@@ -0,0 +1,59 @@
import ifcopenshell
import ifcopenshell.util.pset
import ifcopenshell.util.element
class Patcher:
def __init__(self, src, file, logger, args=None):
self.src = src
self.file = file
self.logger = logger
self.args = args
def patch(self):
self.qto_template_cache = {}
self.psetqto = ifcopenshell.util.pset.get_template("IFC4")
self.source_property_name = self.args[0]
self.destination_quantity_name = self.args[1]
for product in self.file.by_type("IfcTypeProduct"):
self.process_product(product, product.HasPropertySets or [])
for product in self.file.by_type("IfcProduct"):
self.process_product(
product,
[r.RelatingPropertyDefinition for r in product.IsDefinedBy if r.is_a("IfcRelDefinesByProperties")],
)
def process_product(self, product, definitions):
value = None
has_quantity = False
qtos = {}
for definition in definitions or []:
if definition.is_a("IfcPropertySet"):
for prop in definition.HasProperties:
if prop.is_a("IfcPropertySingleValue") and prop.Name == self.source_property_name:
value = prop.NominalValue.wrappedValue if prop.NominalValue else None
elif definition.is_a("IfcElementQuantity"):
qtos[definition.Name] = definition
for quantity in definition.Quantities:
if quantity.is_a("IfcPhysicalSimpleQuantity") and quantity.Name == self.destination_quantity_name:
has_quantity = True
if value and not has_quantity:
qto_name = self.get_qto_name(product.is_a())
qto = qtos.get(qto_name, ifcopenshell.api.run("pset.add_qto", self.file, product=product, Name=qto_name))
ifcopenshell.api.run(
"pset.edit_qto", self.file, qto=qto, Properties={self.destination_quantity_name: value}
)
def get_qto_name(self, ifc_class):
for template in self.get_qto_templates(ifc_class):
if self.destination_quantity_name in [t.Name for t in template.HasPropertyTemplates]:
return template.Name
def get_qto_templates(self, ifc_class):
if ifc_class not in self.qto_template_cache:
self.qto_template_cache[ifc_class] = self.psetqto.get_applicable(ifc_class, qto_only=True)
return self.qto_template_cache[ifc_class]