This commit is contained in:
Andrej730
2025-03-14 10:43:47 +05:00
parent 10ecac33b8
commit 0e8810c1f5
118 changed files with 869 additions and 1203 deletions
@@ -54,12 +54,9 @@ def add_cost_item_quantity(
using another API call.
:param cost_item: The IfcCostItem to add the quantity to
:type cost_item: ifcopenshell.entity_instance
:param ifc_class: The type of quantity to add
:type ifc_class: str, optional
:return: The newly created quantity entity, chosen from the ifc_class
parameter
:rtype: ifcopenshell.entity_instance
Example:
@@ -76,20 +73,18 @@ def add_cost_item_quantity(
ifcopenshell.api.cost.add_cost_item_quantity(model,
cost_item=item, ifc_class="IfcQuantityCount")
"""
settings = {"cost_item": cost_item, "ifc_class": ifc_class}
quantity = file.create_entity(settings["ifc_class"], Name="Unnamed")
quantity = file.create_entity(ifc_class, Name="Unnamed")
# 3 IfcPhysicalSimpleQuantity Value
# This is a bold assumption
# https://forums.buildingsmart.org/t/how-does-a-cost-item-know-that-it-is-counting-a-controlled-product/3564
if settings["ifc_class"] == "IfcQuantityCount":
if ifc_class == "IfcQuantityCount":
count = 0
for rel in settings["cost_item"].Controls:
for rel in cost_item.Controls:
count += len(rel.RelatedObjects)
quantity[3] = count
else:
quantity[3] = 0.0
quantities = list(settings["cost_item"].CostQuantities or [])
quantities = list(cost_item.CostQuantities or [])
quantities.append(quantity)
settings["cost_item"].CostQuantities = quantities
cost_item.CostQuantities = quantities
return quantity
@@ -39,13 +39,10 @@ def add_cost_schedule(
managing any cost items.
:param name: The name of the cost schedule.
:type name: str, optional
:param predefined_type: The predefined type of the cost schedule, chosen
from a valid type in the IFC documentation for
IfcCostScheduleTypeEnum
:type predefined_type: str, optional
:return: The newly created IfcCostSchedule entity
:rtype: ifcopenshell.entity_instance
Example:
@@ -55,13 +52,11 @@ def add_cost_schedule(
# Now that we have a cost schedule, we may add cost items to it
item = ifcopenshell.api.cost.add_cost_item(model, cost_schedule=schedule)
"""
settings = {"name": name, "predefined_type": predefined_type}
cost_schedule = ifcopenshell.api.root.create_entity(
file,
ifc_class="IfcCostSchedule",
predefined_type=settings["predefined_type"],
name=settings["name"],
predefined_type=predefined_type,
name=name,
)
if file.schema == "IFC2X3":
cost_schedule.UpdateDate = createIfcDateAndTime(file, datetime.now())
@@ -46,9 +46,7 @@ def add_cost_value(file: ifcopenshell.file, parent: ifcopenshell.entity_instance
:param parent: A parent IfcCostItem, if specifying a price directly to a
cost item, or a top-level price component. Alternatively, this can
be set to a IfcCostValue, if specifying price subcomponents.
:type parent: ifcopenshell.entity_instance
:return: The newly created IfcCostValue
:rtype: ifcopenshell.entity_instance
Example:
@@ -91,19 +89,17 @@ def add_cost_value(file: ifcopenshell.file, parent: ifcopenshell.entity_instance
ifcopenshell.api.cost.edit_cost_value(model,
cost_value=subvalue2, attributes={"AppliedValue": 3.0})
"""
settings = {"parent": parent}
value = file.create_entity("IfcCostValue")
if settings["parent"].is_a("IfcCostItem"):
values = list(settings["parent"].CostValues or [])
if parent.is_a("IfcCostItem"):
values = list(parent.CostValues or [])
values.append(value)
settings["parent"].CostValues = values
elif settings["parent"].is_a("IfcConstructionResource"):
values = list(settings["parent"].BaseCosts or [])
parent.CostValues = values
elif parent.is_a("IfcConstructionResource"):
values = list(parent.BaseCosts or [])
values.append(value)
settings["parent"].BaseCosts = values
elif settings["parent"].is_a("IfcCostValue"):
values = list(settings["parent"].Components or [])
parent.BaseCosts = values
elif parent.is_a("IfcCostValue"):
values = list(parent.Components or [])
values.append(value)
settings["parent"].Components = values
parent.Components = values
return value
@@ -36,11 +36,8 @@ def assign_cost_value(
rates as a "template" to quickly populate your rates from.
:param cost_item: The IfcCostItem that you want to copy the values to
:type cost_item: ifcopenshell.entity_instance
:param cost_rate: The IfcCostItem that you want to copy the values from
:type cost_rate: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
@@ -61,16 +58,14 @@ def assign_cost_value(
# Now the cost item has the same rate as the one from the schedule of rate's item
ifcopenshell.api.cost.assign_cost_value(model, cost_item=item, cost_rate=rate)
"""
settings = {"cost_item": cost_item, "cost_rate": cost_rate}
if settings["cost_item"].CostValues:
if cost_item.CostValues:
[
ifcopenshell.api.cost.remove_cost_value(
file,
parent=settings["cost_item"],
parent=cost_item,
cost_value=cost_value,
)
for cost_value in settings["cost_item"].CostValues
for cost_value in cost_item.CostValues
]
# This is an assumption, and not part of the official IFC documentation
settings["cost_item"].CostValues = settings["cost_rate"].CostValues
cost_item.CostValues = cost_rate.CostValues
@@ -83,13 +83,11 @@ def calculate_cost_item_resource_value(file: ifcopenshell.file, cost_item: ifcop
# (42 * 200) + 50000 = 58400 is our calculated cost
ifcopenshell.api.cost.calculate_cost_item_resource_value(model, cost_item=item)
"""
settings = {"cost_item": cost_item}
for cost_value in settings["cost_item"].CostValues or []:
ifcopenshell.api.cost.remove_cost_value(file, parent=settings["cost_item"], cost_value=cost_value)
for cost_value in cost_item.CostValues or []:
ifcopenshell.api.cost.remove_cost_value(file, parent=cost_item, cost_value=cost_value)
resources = []
for rel in settings["cost_item"].Controls or []:
for rel in cost_item.Controls or []:
for related_object in rel.RelatedObjects:
if related_object.is_a("IfcConstructionResource"):
resources.append(related_object)
@@ -112,6 +110,6 @@ def calculate_cost_item_resource_value(file: ifcopenshell.file, cost_item: ifcop
if unit and "day" in unit:
quantity = quantity / 8 # Assume 8 hour working day - TODO implement resource calendar
formula = "{}*{}".format(cost, quantity)
cost_value = ifcopenshell.api.cost.add_cost_value(file, parent=settings["cost_item"])
cost_value = ifcopenshell.api.cost.add_cost_value(file, parent=cost_item)
cost_value.Name = resource.Name
ifcopenshell.api.cost.edit_cost_value_formula(file, cost_value=cost_value, formula=formula)
@@ -29,9 +29,7 @@ def remove_cost_item(file: ifcopenshell.file, cost_item: ifcopenshell.entity_ins
retained.
:param cost_item: The IfcCostItem entity you want to remove
:type cost_item: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
@@ -41,15 +39,13 @@ def remove_cost_item(file: ifcopenshell.file, cost_item: ifcopenshell.entity_ins
item = ifcopenshell.api.cost.add_cost_item(model, cost_schedule=schedule)
ifcopenshell.api.cost.remove_cost_item(model, cost_item=item)
"""
settings = {"cost_item": cost_item}
# TODO: do a deep purge
for inverse in file.get_inverse(settings["cost_item"]):
for inverse in file.get_inverse(cost_item):
if inverse.is_a("IfcRelNests"):
if inverse.RelatingObject == settings["cost_item"]:
if inverse.RelatingObject == cost_item:
for related_object in inverse.RelatedObjects:
ifcopenshell.api.cost.remove_cost_item(file, cost_item=related_object)
elif inverse.RelatedObjects == (settings["cost_item"],):
elif inverse.RelatedObjects == (cost_item,):
history = inverse.OwnerHistory
file.remove(inverse)
if history:
@@ -59,7 +55,7 @@ def remove_cost_item(file: ifcopenshell.file, cost_item: ifcopenshell.entity_ins
file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(file, history)
history = settings["cost_item"].OwnerHistory
file.remove(settings["cost_item"])
history = cost_item.OwnerHistory
file.remove(cost_item)
if history:
ifcopenshell.util.element.remove_deep2(file, history)
@@ -40,17 +40,15 @@ def remove_cost_schedule(file: ifcopenshell.file, cost_schedule: ifcopenshell.en
item = ifcopenshell.api.cost.add_cost_item(model, cost_schedule=schedule)
ifcopenshell.api.cost.remove_cost_schedule(model, cost_schedule=schedule)
"""
settings = {"cost_schedule": cost_schedule}
# TODO: do a deep purge
for inverse in file.get_inverse(settings["cost_schedule"]):
for inverse in file.get_inverse(cost_schedule):
if inverse.is_a("IfcRelAssignsToControl"):
[
ifcopenshell.api.cost.remove_cost_item(file, cost_item=related_object)
for related_object in inverse.RelatedObjects
if related_object.is_a("IfcCostItem")
]
history = settings["cost_schedule"].OwnerHistory
file.remove(settings["cost_schedule"])
history = cost_schedule.OwnerHistory
file.remove(cost_schedule)
if history:
ifcopenshell.util.element.remove_deep2(file, history)