diff --git a/src/blenderbim/blenderbim/bim/module/cost/operator.py b/src/blenderbim/blenderbim/bim/module/cost/operator.py index 4a480a2d8e..37019a692c 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/operator.py +++ b/src/blenderbim/blenderbim/bim/module/cost/operator.py @@ -608,7 +608,7 @@ class SelectCostItemProducts(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - related_products = Data.cost_items[self.cost_item]["Controls"] + related_products = Data.cost_items[self.cost_item]["Controls"].keys() for obj in context.visible_objects: obj.select_set(False) if obj.BIMObjectProperties.ifc_definition_id in related_products: @@ -635,7 +635,7 @@ class SelectCostScheduleProducts(bpy.types.Operator): return {"FINISHED"} def get_related_products(self, cost_item): - self.related_products.extend(cost_item["Controls"]) + self.related_products.extend(cost_item["Controls"].keys()) for child_id in cost_item["IsNestedBy"]: self.get_related_products(Data.cost_items[child_id]) @@ -696,18 +696,21 @@ class LoadCostItemQuantities(bpy.types.Operator): bl_options = {"REGISTER", "UNDO"} def execute(self, context): - print('EXECUTING') self.props = context.scene.BIMCostProperties self.file = IfcStore.get_file() while len(self.props.cost_item_products) > 0: self.props.cost_item_products.remove(0) ifc_definition_id = self.props.cost_items[self.props.active_cost_item_index].ifc_definition_id - for control in Data.cost_items[ifc_definition_id]["Controls"]: - related_object = self.file.by_id(control) + for control_id, quantity_ids in Data.cost_items[ifc_definition_id]["Controls"].items(): + related_object = self.file.by_id(control_id) if related_object.is_a("IfcProduct"): new = self.props.cost_item_products.add() - new.ifc_definition_id = control + new.ifc_definition_id = control_id new.name = related_object.Name or "Unnamed" + total_quantity = 0 + for quantity_id in quantity_ids: + total_quantity += self.file.by_id(quantity_id)[3] + new.total_quantity = total_quantity elif related_object.is_a("IfcProduct"): pass elif related_object.is_a("IfcResource"): diff --git a/src/blenderbim/blenderbim/bim/module/cost/prop.py b/src/blenderbim/blenderbim/bim/module/cost/prop.py index 8b6b673211..ff43627408 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/prop.py +++ b/src/blenderbim/blenderbim/bim/module/cost/prop.py @@ -99,6 +99,7 @@ class CostItem(PropertyGroup): class CostItemProduct(PropertyGroup): name: StringProperty(name="Name") ifc_definition_id: IntProperty(name="IFC Definition ID") + total_quantity: FloatProperty(name="Total Quantity") class BIMCostProperties(PropertyGroup): diff --git a/src/blenderbim/blenderbim/bim/module/cost/ui.py b/src/blenderbim/blenderbim/bim/module/cost/ui.py index 8e8ac6d54a..731e2812cd 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/ui.py +++ b/src/blenderbim/blenderbim/bim/module/cost/ui.py @@ -398,6 +398,7 @@ class BIM_UL_cost_item_products(UIList): if item: row = layout.row(align=True) row.prop(item, "name", emboss=False, text="") + row.label(text="{0:.2f}".format(item.total_quantity)) op = row.operator("bim.unassign_cost_item_product", text="", icon="X") op.cost_item = cost_item.ifc_definition_id op.related_object = item.ifc_definition_id diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_product.py b/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_product.py index a86392bdeb..21f4447383 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_product.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_product.py @@ -21,13 +21,11 @@ class Usecase: self.settings["cost_item"].CostQuantities = list(self.quantities) def add_quantity_from_related_object(self, element): - if element.is_a("IfcTypeObject"): - for definition in element.HasPropertySets or []: - self.add_quantity_from_qto(definition) - else: - for relationship in element.IsDefinedBy: - if relationship.is_a("IfcRelDefinesByProperties"): - self.add_quantity_from_qto(relationship.RelatingPropertyDefinition) + if not element.is_a("IfcObject"): + return + for relationship in element.IsDefinedBy: + if relationship.is_a("IfcRelDefinesByProperties"): + self.add_quantity_from_qto(relationship.RelatingPropertyDefinition) def add_quantity_from_qto(self, qto): if not qto.is_a("IfcElementQuantity"): diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/data.py b/src/ifcopenshell-python/ifcopenshell/api/cost/data.py index 3e08f7ad47..ee823244f8 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/data.py @@ -51,21 +51,43 @@ class Data: del data["OwnerHistory"] del data["CostValues"] data["IsNestedBy"] = [] - data["Controls"] = [] + data["Controls"] = {} for rel in cost_item.IsNestedBy: [data["IsNestedBy"].append(o.id()) for o in rel.RelatedObjects if o.is_a("IfcCostItem")] + parametric_quantities = [] for rel in cost_item.Controls: - [data["Controls"].append(o.id()) for o in rel.RelatedObjects or []] + for related_object in rel.RelatedObjects or []: + quantities = cls.get_object_quantities(cost_item, related_object) + data["Controls"][related_object.id()] = quantities + parametric_quantities.extend(quantities) cls.cost_items[cost_item.id()] = data - cls.load_cost_item_quantities(cost_item, data) + cls.load_cost_item_quantities(cost_item, data, parametric_quantities) cls.load_cost_item_values(cost_item, data) cls.is_loaded = True @classmethod - def load_cost_item_quantities(cls, cost_item, data): + def get_object_quantities(cls, cost_item, element): + if not element.is_a("IfcObject"): + return [] + results = [] + for relationship in element.IsDefinedBy: + if not relationship.is_a("IfcRelDefinesByProperties"): + continue + qto = relationship.RelatingPropertyDefinition + if not qto.is_a("IfcElementQuantity"): + continue + for prop in qto.Quantities: + if prop in cost_item.CostQuantities or []: + results.append(prop.id()) + return results + + @classmethod + def load_cost_item_quantities(cls, cost_item, data, parametric_quantities): data["CostQuantities"] = [] data["TotalCostQuantity"] = cls.get_total_quantity(cost_item) for quantity in cost_item.CostQuantities or []: + if quantity.id() in parametric_quantities: + continue quantity_data = quantity.get_info() del quantity_data["Unit"] cls.physical_quantities[quantity.id()] = quantity_data