mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Merge remote-tracking branch 'origin/v0.6.0' into v0.7.0
# Conflicts: # .github/workflows/ci.yml # src/ifcparse/IfcParse.cpp
This commit is contained in:
@@ -34,9 +34,7 @@ class circle:
|
||||
radius: numpy.ndarray
|
||||
|
||||
def __call__(self, u):
|
||||
return numpy.array(
|
||||
[self.radius * numpy.cos(u), self.radius * numpy.sin(u), numpy.nan]
|
||||
)
|
||||
return numpy.array([self.radius * numpy.cos(u), self.radius * numpy.sin(u), numpy.nan])
|
||||
|
||||
|
||||
def place(matrix, func):
|
||||
|
||||
@@ -37,12 +37,14 @@ class Data:
|
||||
if data_type == "enum":
|
||||
enum_items = ifcopenshell.util.attribute.get_enum_items(attribute)
|
||||
|
||||
cls.products[product_id].append({
|
||||
"name": attribute.name(),
|
||||
"value": value,
|
||||
"type": data_type,
|
||||
"enum_items": enum_items,
|
||||
"list_type": list_type,
|
||||
"is_optional": attribute.optional(),
|
||||
"is_null": getattr(product, attribute.name()) is None
|
||||
})
|
||||
cls.products[product_id].append(
|
||||
{
|
||||
"name": attribute.name(),
|
||||
"value": value,
|
||||
"type": data_type,
|
||||
"enum_items": enum_items,
|
||||
"list_type": list_type,
|
||||
"is_optional": attribute.optional(),
|
||||
"is_null": getattr(product, attribute.name()) is None,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -57,7 +57,7 @@ class Data:
|
||||
for reference in cls._file.by_type("IfcClassificationReference"):
|
||||
data = reference.get_info()
|
||||
if reference.ReferencedSource:
|
||||
#data["ReferencedSource"] = cls.get_referenced_source(reference.ReferencedSource)
|
||||
# data["ReferencedSource"] = cls.get_referenced_source(reference.ReferencedSource)
|
||||
data["ReferencedSource"] = reference.ReferencedSource.id()
|
||||
cls.references[reference.id()] = data
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"classification": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"classification": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"reference": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"reference": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
@@ -10,11 +11,14 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
metric = self.file.create_entity("IfcMetric", **{
|
||||
"Name": "Unnamed",
|
||||
"ConstraintGrade": "NOTDEFINED",
|
||||
"Benchmark": "EQUALTO",
|
||||
})
|
||||
metric = self.file.create_entity(
|
||||
"IfcMetric",
|
||||
**{
|
||||
"Name": "Unnamed",
|
||||
"ConstraintGrade": "NOTDEFINED",
|
||||
"Benchmark": "EQUALTO",
|
||||
}
|
||||
)
|
||||
if self.settings["objective"]:
|
||||
benchmark_values = list(self.settings["objective"].BenchmarkValues or [])
|
||||
benchmark_values.append(metric)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
@@ -8,8 +9,6 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
return self.file.create_entity("IfcObjective", **{
|
||||
"Name": "Unnamed",
|
||||
"ConstraintGrade": "NOTDEFINED",
|
||||
"ObjectiveQualifier": "NOTDEFINED"
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcObjective", **{"Name": "Unnamed", "ConstraintGrade": "NOTDEFINED", "ObjectiveQualifier": "NOTDEFINED"}
|
||||
)
|
||||
|
||||
@@ -22,8 +22,11 @@ class Usecase:
|
||||
for rel in self.file.by_type("IfcRelAssociatesConstraint"):
|
||||
if rel.RelatingConstraint == self.settings["constraint"]:
|
||||
return rel
|
||||
return self.file.create_entity("IfcRelAssociatesConstraint", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
# TODO: owner history
|
||||
"RelatingConstraint": self.settings["constraint"]
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcRelAssociatesConstraint",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
# TODO: owner history
|
||||
"RelatingConstraint": self.settings["constraint"],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -15,10 +15,9 @@ class Data:
|
||||
cls.is_loaded = False
|
||||
cls.products = {}
|
||||
cls.objectives = {}
|
||||
cls.metrics ={}
|
||||
cls.metrics = {}
|
||||
cls.references = {}
|
||||
|
||||
|
||||
@classmethod
|
||||
def load(cls, file, product_id=None):
|
||||
cls._file = file
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"metric": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"metric": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"objective": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"objective": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -35,12 +35,15 @@ class Usecase:
|
||||
project.RepresentationContexts = contexts
|
||||
return context
|
||||
parent = parent[0]
|
||||
return self.file.create_entity("IfcGeometricRepresentationSubContext", **{
|
||||
"ContextIdentifier": self.settings["subcontext"],
|
||||
"ContextType": self.settings["context"],
|
||||
"ParentContext": parent,
|
||||
"TargetView": self.settings["target_view"],
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcGeometricRepresentationSubContext",
|
||||
**{
|
||||
"ContextIdentifier": self.settings["subcontext"],
|
||||
"ContextType": self.settings["context"],
|
||||
"ParentContext": parent,
|
||||
"TargetView": self.settings["target_view"],
|
||||
}
|
||||
)
|
||||
|
||||
def create_origin(self):
|
||||
self.origin = self.file.createIfcAxis2Placement3D(
|
||||
|
||||
@@ -20,8 +20,5 @@ class Data:
|
||||
"ContextIdentifier": subcontext.ContextIdentifier,
|
||||
"TargetView": subcontext.TargetView,
|
||||
}
|
||||
cls.contexts[int(context.id())] = {
|
||||
"ContextType": context.ContextType,
|
||||
"HasSubContexts": subcontexts
|
||||
}
|
||||
cls.contexts[int(context.id())] = {"ContextType": context.ContextType, "HasSubContexts": subcontexts}
|
||||
cls.is_loaded = True
|
||||
|
||||
@@ -14,8 +14,10 @@ class Usecase:
|
||||
# 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 self.settings["ifc_class"] == "IfcQuantityCount" and self.settings["cost_item"].Controls:
|
||||
count = 0
|
||||
for rel in self.settings["cost_item"].Controls:
|
||||
quantity[3] += len(rel.RelatedObjects)
|
||||
count += len(rel.RelatedObjects)
|
||||
quantity[3] = count
|
||||
quantities = list(self.settings["cost_item"].CostQuantities or [])
|
||||
quantities.append(quantity)
|
||||
self.settings["cost_item"].CostQuantities = quantities
|
||||
|
||||
@@ -11,6 +11,10 @@ class Usecase:
|
||||
values = list(self.settings["parent"].CostValues or [])
|
||||
values.append(value)
|
||||
self.settings["parent"].CostValues = values
|
||||
elif self.settings["parent"].is_a("IfcConstructionResource"):
|
||||
values = list(self.settings["parent"].BaseCosts or [])
|
||||
values.append(value)
|
||||
self.settings["parent"].BaseCosts = values
|
||||
elif self.settings["parent"].is_a("IfcCostValue"):
|
||||
values = list(self.settings["parent"].Components or [])
|
||||
values.append(value)
|
||||
|
||||
@@ -9,7 +9,8 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
||||
if self.settings["prop_name"]:
|
||||
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
||||
for product in self.settings["products"]:
|
||||
ifcopenshell.api.run(
|
||||
"control.assign_control",
|
||||
@@ -17,8 +18,12 @@ class Usecase:
|
||||
related_object=product,
|
||||
relating_control=self.settings["cost_item"],
|
||||
)
|
||||
self.add_quantity_from_related_object(product)
|
||||
self.settings["cost_item"].CostQuantities = list(self.quantities)
|
||||
if self.settings["prop_name"]:
|
||||
self.add_quantity_from_related_object(product)
|
||||
if self.settings["prop_name"]:
|
||||
self.settings["cost_item"].CostQuantities = list(self.quantities)
|
||||
else:
|
||||
self.update_cost_item_count()
|
||||
|
||||
def add_quantity_from_related_object(self, element):
|
||||
if not element.is_a("IfcObject"):
|
||||
@@ -33,3 +38,21 @@ class Usecase:
|
||||
for prop in qto.Quantities:
|
||||
if prop.is_a("IfcPhysicalSimpleQuantity") and prop.Name.lower() == self.settings["prop_name"].lower():
|
||||
self.quantities.add(prop)
|
||||
|
||||
def update_cost_item_count(self):
|
||||
# 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 not self.settings["cost_item"].CostQuantities:
|
||||
return ifcopenshell.api.run(
|
||||
"cost.add_cost_item_quantity",
|
||||
self.file,
|
||||
cost_item=self.settings["cost_item"],
|
||||
ifc_class="IfcQuantityCount",
|
||||
)
|
||||
if len(self.settings["cost_item"].CostQuantities) == 1:
|
||||
quantity = self.settings["cost_item"].CostQuantities[0]
|
||||
if quantity.is_a("IfcQuantityCount"):
|
||||
count = 0
|
||||
for rel in self.settings["cost_item"].Controls:
|
||||
count += len(rel.RelatedObjects)
|
||||
quantity[3] = count
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"cost_item": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for cost_value in self.settings["cost_item"].CostValues or []:
|
||||
ifcopenshell.api.run(
|
||||
"cost.remove_cost_value", self.file, parent=self.settings["cost_item"], cost_value=cost_value
|
||||
)
|
||||
|
||||
resources = []
|
||||
for rel in self.settings["cost_item"].Controls or []:
|
||||
for related_object in rel.RelatedObjects:
|
||||
if related_object.is_a("IfcConstructionResource"):
|
||||
resources.append(related_object)
|
||||
elif related_object.is_a("IfcTask"):
|
||||
for rel2 in related_object.OperatesOn or []:
|
||||
for related_object2 in rel2.RelatedObjects:
|
||||
if related_object2.is_a("IfcConstructionResource"):
|
||||
resources.append(related_object2)
|
||||
|
||||
total_cost = 0
|
||||
for resource in resources:
|
||||
cost = self.get_cost(resource)
|
||||
quantity = self.get_quantity(resource)
|
||||
if not cost or not quantity:
|
||||
continue
|
||||
total_cost += cost * quantity
|
||||
|
||||
if total_cost:
|
||||
cost_value = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=self.settings["cost_item"])
|
||||
cost_value.AppliedValue = self.file.createIfcMonetaryMeasure(total_cost)
|
||||
|
||||
def get_cost(self, resource):
|
||||
total = 0
|
||||
for cost_value in resource.BaseCosts or []:
|
||||
total += cost_value.AppliedValue.wrappedValue if cost_value.AppliedValue else 0
|
||||
return total
|
||||
|
||||
def get_quantity(self, resource):
|
||||
total = 0
|
||||
if resource.BaseQuantity:
|
||||
return resource.BaseQuantity[3]
|
||||
if resource.Usage and resource.Usage.ScheduleWork:
|
||||
# For now we assume either hourly or daily depending on how duration is stored
|
||||
duration = ifcopenshell.util.date.ifc2datetime(resource.Usage.ScheduleWork)
|
||||
if duration.days:
|
||||
return duration.days
|
||||
return duration.seconds / 60 / 60
|
||||
@@ -1,8 +1,139 @@
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.cost
|
||||
|
||||
|
||||
class Data:
|
||||
class CostValueTrait:
|
||||
@classmethod
|
||||
def load_cost_values(cls, root_element, data):
|
||||
data["CostValues"] = []
|
||||
data["CategoryValues"] = {}
|
||||
data["UnitBasisValueComponent"] = None
|
||||
data["UnitBasisUnitSymbol"] = None
|
||||
data["TotalAppliedValue"] = 0.0
|
||||
data["TotalCost"] = 0.0
|
||||
if root_element.is_a("IfcCostItem"):
|
||||
values = root_element.CostValues
|
||||
elif root_element.is_a("IfcConstructionResource"):
|
||||
values = root_element.BaseCosts
|
||||
for cost_value in values or []:
|
||||
cls.load_cost_value(root_element, data, cost_value)
|
||||
data["CostValues"].append(cost_value.id())
|
||||
data["TotalAppliedValue"] += cls.cost_values[cost_value.id()]["AppliedValue"]
|
||||
if cost_value.UnitBasis:
|
||||
cost_value_data = cls.cost_values[cost_value.id()]
|
||||
data["UnitBasisValueComponent"] = cost_value_data["UnitBasis"]["ValueComponent"]
|
||||
data["UnitBasisUnitSymbol"] = cost_value_data["UnitBasis"]["UnitSymbol"]
|
||||
if data["UnitBasisValueComponent"]:
|
||||
data["TotalCost"] = data["TotalCostQuantity"] / data["UnitBasisValueComponent"] * data["TotalAppliedValue"]
|
||||
else:
|
||||
data["TotalCost"] = data["TotalCostQuantity"] * data["TotalAppliedValue"]
|
||||
|
||||
@classmethod
|
||||
def load_cost_value(cls, root_element, root_element_data, cost_value):
|
||||
value_data = cost_value.get_info()
|
||||
del value_data["AppliedValue"]
|
||||
if value_data["UnitBasis"]:
|
||||
data = cost_value.UnitBasis.get_info()
|
||||
data["ValueComponent"] = data["ValueComponent"].wrappedValue
|
||||
data["UnitComponent"] = data["UnitComponent"].id()
|
||||
data["UnitSymbol"] = ifcopenshell.util.unit.get_unit_symbol(cost_value.UnitBasis.UnitComponent)
|
||||
value_data["UnitBasis"] = data
|
||||
if value_data["ApplicableDate"]:
|
||||
value_data["ApplicableDate"] = ifcopenshell.util.date.ifc2datetime(value_data["ApplicableDate"])
|
||||
if value_data["FixedUntilDate"]:
|
||||
value_data["FixedUntilDate"] = ifcopenshell.util.date.ifc2datetime(value_data["FixedUntilDate"])
|
||||
value_data["Components"] = [c.id() for c in value_data["Components"] or []]
|
||||
value_data["AppliedValue"] = cls.calculate_applied_value(root_element, cost_value)
|
||||
|
||||
if cost_value.Category not in [None, "*"]:
|
||||
root_element_data["CategoryValues"].setdefault(cost_value.Category, 0)
|
||||
root_element_data["CategoryValues"][cost_value.Category] += value_data["AppliedValue"]
|
||||
|
||||
value_data["Formula"] = ifcopenshell.util.cost.serialise_cost_value(cost_value)
|
||||
|
||||
cls.cost_values[cost_value.id()] = value_data
|
||||
for component in cost_value.Components or []:
|
||||
cls.load_cost_value(root_element, root_element_data, component)
|
||||
|
||||
@classmethod
|
||||
def calculate_applied_value(cls, root_element, cost_value, category_filter=None):
|
||||
if cost_value.ArithmeticOperator and cost_value.Components:
|
||||
component_values = []
|
||||
for component in cost_value.Components:
|
||||
component_values.append(cls.calculate_applied_value(root_element, component, category_filter))
|
||||
if cost_value.ArithmeticOperator == "ADD":
|
||||
return sum(component_values)
|
||||
result = component_values.pop(0)
|
||||
if cost_value.ArithmeticOperator == "DIVIDE":
|
||||
for value in component_values:
|
||||
try:
|
||||
result /= value
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
elif cost_value.ArithmeticOperator == "MULTIPLY":
|
||||
for value in component_values:
|
||||
result *= value
|
||||
elif cost_value.ArithmeticOperator == "SUBTRACT":
|
||||
for value in component_values:
|
||||
result -= value
|
||||
return result
|
||||
if cost_value.Category is None:
|
||||
return cls.get_primitive_applied_value(cost_value.AppliedValue)
|
||||
elif cost_value.Category == "*":
|
||||
if root_element.IsNestedBy:
|
||||
return cls.sum_child_root_elements(root_element)
|
||||
else:
|
||||
return cls.get_primitive_applied_value(cost_value.AppliedValue)
|
||||
elif cost_value.Category:
|
||||
if root_element.IsNestedBy:
|
||||
return cls.sum_child_root_elements(root_element, category_filter=cost_value.Category)
|
||||
else:
|
||||
return cls.get_primitive_applied_value(cost_value.AppliedValue)
|
||||
return 0
|
||||
|
||||
@classmethod
|
||||
def sum_child_root_elements(cls, root_element, category_filter=None):
|
||||
result = 0
|
||||
for rel in root_element.IsNestedBy:
|
||||
for child_root_element in rel.RelatedObjects:
|
||||
if root_element.is_a("IfcCostItem"):
|
||||
values = child_root_element.CostValues
|
||||
elif root_element.is_a("IfcConstructionResource"):
|
||||
values = child_root_element.BaseCosts
|
||||
for child_cost_value in values or []:
|
||||
if category_filter and child_cost_value.Category != category_filter:
|
||||
continue
|
||||
child_applied_value = cls.calculate_applied_value(child_root_element, child_cost_value)
|
||||
child_quantity = cls.get_total_quantity(child_root_element)
|
||||
if child_cost_value.UnitBasis:
|
||||
value_component = child_cost_value.UnitBasis.ValueComponent.wrappedValue
|
||||
result += child_quantity / value_component * child_applied_value
|
||||
else:
|
||||
result += child_quantity * child_applied_value
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def get_total_quantity(cls, root_element):
|
||||
if root_element.is_a("IfcCostItem"):
|
||||
return sum([q[3] for q in root_element.CostQuantities or []]) or 1.0
|
||||
elif root_element.is_a("IfcConstructionResource"):
|
||||
return root_element.BaseQuantity[3] if root_element.BaseQuantity else 1.0
|
||||
|
||||
@classmethod
|
||||
def get_primitive_applied_value(cls, applied_value):
|
||||
if not applied_value:
|
||||
return 0.0
|
||||
elif isinstance(applied_value, float):
|
||||
return applied_value
|
||||
elif hasattr(applied_value, "wrappedValue") and isinstance(applied_value.wrappedValue, float):
|
||||
return applied_value.wrappedValue
|
||||
elif applied_value.is_a("IfcMeasureWithUnit"):
|
||||
return applied_value.ValueComponent
|
||||
assert False, "Applied value {applied_value} not implemented"
|
||||
|
||||
|
||||
class Data(CostValueTrait):
|
||||
is_loaded = False
|
||||
cost_schedules = {}
|
||||
cost_items = {}
|
||||
@@ -62,7 +193,7 @@ class Data:
|
||||
parametric_quantities.extend(quantities)
|
||||
cls.cost_items[cost_item.id()] = data
|
||||
cls.load_cost_item_quantities(cost_item, data, parametric_quantities)
|
||||
cls.load_cost_item_values(cost_item, data)
|
||||
cls.load_cost_values(cost_item, data)
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
@@ -103,120 +234,3 @@ class Data:
|
||||
else:
|
||||
data["Unit"] = None
|
||||
data["UnitSymbol"] = None
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_values(cls, cost_item, data):
|
||||
data["CostValues"] = []
|
||||
data["CategoryValues"] = {}
|
||||
data["UnitBasisValueComponent"] = None
|
||||
data["UnitBasisUnitSymbol"] = None
|
||||
data["TotalAppliedValue"] = 0.0
|
||||
data["TotalCost"] = 0.0
|
||||
for cost_value in cost_item.CostValues or []:
|
||||
cls.load_cost_item_value(cost_item, data, cost_value)
|
||||
data["CostValues"].append(cost_value.id())
|
||||
data["TotalAppliedValue"] += cls.cost_values[cost_value.id()]["AppliedValue"]
|
||||
if cost_value.UnitBasis:
|
||||
cost_value_data = cls.cost_values[cost_value.id()]
|
||||
data["UnitBasisValueComponent"] = cost_value_data["UnitBasis"]["ValueComponent"]
|
||||
data["UnitBasisUnitSymbol"] = cost_value_data["UnitBasis"]["UnitSymbol"]
|
||||
if data["UnitBasisValueComponent"]:
|
||||
data["TotalCost"] = (
|
||||
data["TotalCostQuantity"] / data["UnitBasisValueComponent"] * data["TotalAppliedValue"]
|
||||
)
|
||||
else:
|
||||
data["TotalCost"] = data["TotalCostQuantity"] * data["TotalAppliedValue"]
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_value(cls, cost_item, cost_item_data, cost_value):
|
||||
value_data = cost_value.get_info()
|
||||
del value_data["AppliedValue"]
|
||||
if value_data["UnitBasis"]:
|
||||
data = cost_value.UnitBasis.get_info()
|
||||
data["ValueComponent"] = data["ValueComponent"].wrappedValue
|
||||
data["UnitComponent"] = data["UnitComponent"].id()
|
||||
data["UnitSymbol"] = ifcopenshell.util.unit.get_unit_symbol(cost_value.UnitBasis.UnitComponent)
|
||||
value_data["UnitBasis"] = data
|
||||
if value_data["ApplicableDate"]:
|
||||
value_data["ApplicableDate"] = ifcopenshell.util.date.ifc2datetime(value_data["ApplicableDate"])
|
||||
if value_data["FixedUntilDate"]:
|
||||
value_data["FixedUntilDate"] = ifcopenshell.util.date.ifc2datetime(value_data["FixedUntilDate"])
|
||||
value_data["Components"] = [c.id() for c in value_data["Components"] or []]
|
||||
value_data["AppliedValue"] = cls.calculate_applied_value(cost_item, cost_value)
|
||||
|
||||
if cost_value.Category not in [None, "*"]:
|
||||
cost_item_data["CategoryValues"].setdefault(cost_value.Category, 0)
|
||||
cost_item_data["CategoryValues"][cost_value.Category] += value_data["AppliedValue"]
|
||||
|
||||
cls.cost_values[cost_value.id()] = value_data
|
||||
for component in cost_value.Components or []:
|
||||
cls.load_cost_item_value(cost_item, cost_item_data, component)
|
||||
|
||||
@classmethod
|
||||
def calculate_applied_value(cls, cost_item, cost_value, category_filter=None):
|
||||
if cost_value.ArithmeticOperator and cost_value.Components:
|
||||
component_values = []
|
||||
for component in cost_value.Components:
|
||||
component_values.append(cls.calculate_applied_value(cost_item, component, category_filter))
|
||||
if cost_value.ArithmeticOperator == "ADD":
|
||||
return sum(component_values)
|
||||
result = component_values.pop(0)
|
||||
if cost_value.ArithmeticOperator == "DIVIDE":
|
||||
for value in component_values:
|
||||
try:
|
||||
result /= value
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
elif cost_value.ArithmeticOperator == "MULTIPLY":
|
||||
for value in component_values:
|
||||
result *= value
|
||||
elif cost_value.ArithmeticOperator == "SUBTRACT":
|
||||
for value in component_values:
|
||||
result -= value
|
||||
return result
|
||||
if cost_value.Category is None:
|
||||
return cls.get_primitive_applied_value(cost_value.AppliedValue)
|
||||
elif cost_value.Category == "*":
|
||||
if cost_item.IsNestedBy:
|
||||
return cls.sum_child_cost_items(cost_item)
|
||||
else:
|
||||
return cls.get_primitive_applied_value(cost_value.AppliedValue)
|
||||
elif cost_value.Category:
|
||||
if cost_item.IsNestedBy:
|
||||
return cls.sum_child_cost_items(cost_item, category_filter=cost_value.Category)
|
||||
else:
|
||||
return cls.get_primitive_applied_value(cost_value.AppliedValue)
|
||||
return 0
|
||||
|
||||
@classmethod
|
||||
def sum_child_cost_items(cls, cost_item, category_filter=None):
|
||||
result = 0
|
||||
for rel in cost_item.IsNestedBy:
|
||||
for child_cost_item in rel.RelatedObjects:
|
||||
for child_cost_value in child_cost_item.CostValues or []:
|
||||
if category_filter and child_cost_value.Category != category_filter:
|
||||
continue
|
||||
child_applied_value = cls.calculate_applied_value(child_cost_item, child_cost_value)
|
||||
child_quantity = cls.get_total_quantity(child_cost_item)
|
||||
if child_cost_value.UnitBasis:
|
||||
value_component = child_cost_value.UnitBasis.ValueComponent.wrappedValue
|
||||
result += child_quantity / value_component * child_applied_value
|
||||
else:
|
||||
result += child_quantity * child_applied_value
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def get_total_quantity(cls, cost_item):
|
||||
return sum([q[3] for q in cost_item.CostQuantities or []]) or 1.0
|
||||
|
||||
@classmethod
|
||||
def get_primitive_applied_value(cls, applied_value):
|
||||
if not applied_value:
|
||||
return 0.0
|
||||
elif isinstance(applied_value, float):
|
||||
return applied_value
|
||||
elif hasattr(applied_value, "wrappedValue") and isinstance(applied_value.wrappedValue, float):
|
||||
return applied_value.wrappedValue
|
||||
elif applied_value.is_a("IfcMeasureWithUnit"):
|
||||
return applied_value.ValueComponent
|
||||
assert False, "Applied value {applied_value} not implemented"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.cost
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"cost_value": None, "formula": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
try:
|
||||
data = ifcopenshell.util.cost.unserialise_cost_value(self.settings["formula"], self.settings["cost_value"])
|
||||
except:
|
||||
return
|
||||
self.edit_cost_value(data)
|
||||
|
||||
def edit_cost_value(self, data, parent=None):
|
||||
ifc = data.get("ifc", None)
|
||||
if not ifc:
|
||||
ifc = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=parent)
|
||||
if "AppliedValue" in data:
|
||||
if data["AppliedValue"]:
|
||||
ifc.AppliedValue = self.file.createIfcMonetaryMeasure(data["AppliedValue"])
|
||||
else:
|
||||
ifc.AppliedValue = None
|
||||
ifc.Category = data["Category"] if "Category" in data else None
|
||||
ifc.ArithmeticOperator = data["ArithmeticOperator"] if "ArithmeticOperator" in data else None
|
||||
if "Components" in data:
|
||||
for component in data["Components"]:
|
||||
self.edit_cost_value(component, ifc)
|
||||
+4
@@ -13,6 +13,10 @@ class Usecase:
|
||||
values = list(self.settings["parent"].CostValues)
|
||||
values.remove(self.settings["cost_value"])
|
||||
self.settings["parent"].CostValues = values if values else None
|
||||
elif self.settings["parent"].is_a("IfcConstructionResource"):
|
||||
values = list(self.settings["parent"].BaseCosts)
|
||||
values.remove(self.settings["cost_value"])
|
||||
self.settings["parent"].BaseCosts = values if values else None
|
||||
elif self.settings["parent"].is_a("IfcCostValue"):
|
||||
components = list(self.settings["parent"].Components)
|
||||
components.remove(self.settings["cost_value"])
|
||||
@@ -19,7 +19,6 @@ class Usecase:
|
||||
if related_object in self.settings["products"]:
|
||||
self.quantities.remove(quantity)
|
||||
self.settings["cost_item"].CostQuantities = list(self.quantities)
|
||||
|
||||
for product in self.settings["products"]:
|
||||
ifcopenshell.api.run(
|
||||
"control.unassign_control",
|
||||
@@ -27,3 +26,15 @@ class Usecase:
|
||||
related_object=product,
|
||||
relating_control=self.settings["cost_item"],
|
||||
)
|
||||
self.update_cost_item_count()
|
||||
|
||||
def update_cost_item_count(self):
|
||||
# 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 len(self.settings["cost_item"].CostQuantities) == 1:
|
||||
quantity = self.settings["cost_item"].CostQuantities[0]
|
||||
if quantity.is_a("IfcQuantityCount"):
|
||||
count = 0
|
||||
for rel in self.settings["cost_item"].Controls:
|
||||
count += len(rel.RelatedObjects)
|
||||
quantity[3] = count
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
@@ -9,7 +10,6 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
id_attribute = "DocumentId" if self.file.schema == "IFC2X3" else "Identification"
|
||||
return self.file.create_entity("IfcDocumentInformation", **{
|
||||
id_attribute: ifcopenshell.guid.new(),
|
||||
"Name": "Unnamed"
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcDocumentInformation", **{id_attribute: ifcopenshell.guid.new(), "Name": "Unnamed"}
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
@@ -9,6 +10,4 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
id_attribute = "ItemReference" if self.file.schema == "IFC2X3" else "Identification"
|
||||
return self.file.create_entity("IfcDocumentReference", **{
|
||||
id_attribute: ifcopenshell.guid.new()
|
||||
})
|
||||
return self.file.create_entity("IfcDocumentReference", **{id_attribute: ifcopenshell.guid.new()})
|
||||
|
||||
@@ -34,8 +34,11 @@ class Usecase:
|
||||
):
|
||||
return self.settings["document"].DocumentInfoForObjects[0]
|
||||
|
||||
return self.file.create_entity("IfcRelAssociatesDocument", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
# TODO: owner history
|
||||
"RelatingDocument": self.settings["document"]
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcRelAssociatesDocument",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
# TODO: owner history
|
||||
"RelatingDocument": self.settings["document"],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"information": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"information": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"reference": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"reference": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -28,6 +28,6 @@ class Data:
|
||||
"ContextType": c.ContextType,
|
||||
"ContextIdentifier": c.ContextIdentifier,
|
||||
"TargetView": c.TargetView if c.is_a("IfcGeometricRepresentationSubContext") else "",
|
||||
}
|
||||
},
|
||||
}
|
||||
cls.products[product_id].append(rep_id)
|
||||
|
||||
@@ -8,7 +8,7 @@ import ifcopenshell.util.placement
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"product": None, "matrix": np.eye(4), "should_transform_children": False}
|
||||
self.settings = {"product": None, "matrix": np.eye(4), "is_si": True, "should_transform_children": False}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
@@ -17,31 +17,24 @@ class Usecase:
|
||||
return
|
||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||
|
||||
if not self.settings["is_si"]:
|
||||
self.settings["matrix"][0][3] *= self.unit_scale
|
||||
self.settings["matrix"][1][3] *= self.unit_scale
|
||||
self.settings["matrix"][2][3] *= self.unit_scale
|
||||
|
||||
children_settings = []
|
||||
if not self.settings["should_transform_children"]:
|
||||
children_settings = self.get_children_settings(self.settings["product"].ObjectPlacement)
|
||||
|
||||
placement_rel_to = None
|
||||
if hasattr(self.settings["product"], "ContainedInStructure") and self.settings["product"].ContainedInStructure:
|
||||
placement_rel_to = self.settings["product"].ContainedInStructure[0].RelatingStructure.ObjectPlacement
|
||||
elif hasattr(self.settings["product"], "Decomposes") and self.settings["product"].Decomposes:
|
||||
relating_object = self.settings["product"].Decomposes[0].RelatingObject
|
||||
placement_rel_to = relating_object.ObjectPlacement if hasattr(relating_object, "ObjectPlacement") else None
|
||||
elif hasattr(self.settings["product"], "VoidsElements") and self.settings["product"].VoidsElements:
|
||||
relating_object = self.settings["product"].VoidsElements[0].RelatingBuildingElement
|
||||
placement_rel_to = relating_object.ObjectPlacement if hasattr(relating_object, "ObjectPlacement") else None
|
||||
elif hasattr(self.settings["product"], "FillsVoids") and self.settings["product"].FillsVoids:
|
||||
relating_object = self.settings["product"].FillsVoids[0].RelatingOpeningElement
|
||||
placement_rel_to = relating_object.ObjectPlacement if hasattr(relating_object, "ObjectPlacement") else None
|
||||
elif hasattr(self.settings["product"], "ProjectsElements") and self.settings["product"].ProjectsElements:
|
||||
relating_object = self.settings["product"].ProjectsElements[0].RelatingElement
|
||||
placement_rel_to = relating_object.ObjectPlacement if hasattr(relating_object, "ObjectPlacement") else None
|
||||
|
||||
placement_rel_to = self.get_placement_rel_to()
|
||||
placement = self.file.createIfcLocalPlacement(placement_rel_to, self.get_relative_placement(placement_rel_to))
|
||||
old_placement = self.settings["product"].ObjectPlacement
|
||||
if old_placement and len(self.file.get_inverse(old_placement)) == 1:
|
||||
old_placement.PlacementRelTo = None
|
||||
if old_placement:
|
||||
self.settings["product"].ObjectPlacement = None
|
||||
inverses = self.file.get_inverse(old_placement)
|
||||
for inverse in inverses:
|
||||
ifcopenshell.util.element.replace_attribute(inverse, old_placement, placement)
|
||||
old_placement.PlacementRelTo = None
|
||||
ifcopenshell.util.element.remove_deep(self.file, old_placement)
|
||||
self.settings["product"].ObjectPlacement = placement
|
||||
|
||||
@@ -53,6 +46,22 @@ class Usecase:
|
||||
|
||||
return placement
|
||||
|
||||
def get_placement_rel_to(self):
|
||||
if getattr(self.settings["product"], "ContainedInStructure", None):
|
||||
return self.settings["product"].ContainedInStructure[0].RelatingStructure.ObjectPlacement
|
||||
elif getattr(self.settings["product"], "Decomposes", None):
|
||||
relating_object = self.settings["product"].Decomposes[0].RelatingObject
|
||||
return relating_object.ObjectPlacement if hasattr(relating_object, "ObjectPlacement") else None
|
||||
elif getattr(self.settings["product"], "VoidsElements", None):
|
||||
relating_object = self.settings["product"].VoidsElements[0].RelatingBuildingElement
|
||||
return relating_object.ObjectPlacement if hasattr(relating_object, "ObjectPlacement") else None
|
||||
elif getattr(self.settings["product"], "FillsVoids", None):
|
||||
relating_object = self.settings["product"].FillsVoids[0].RelatingOpeningElement
|
||||
return relating_object.ObjectPlacement if hasattr(relating_object, "ObjectPlacement") else None
|
||||
elif getattr(self.settings["product"], "ProjectsElements", None):
|
||||
relating_object = self.settings["product"].ProjectsElements[0].RelatingElement
|
||||
return relating_object.ObjectPlacement if hasattr(relating_object, "ObjectPlacement") else None
|
||||
|
||||
def get_children_settings(self, placement):
|
||||
if not placement:
|
||||
return []
|
||||
@@ -60,7 +69,7 @@ class Usecase:
|
||||
for referenced_placement in placement.ReferencedByPlacements:
|
||||
matrix = ifcopenshell.util.placement.get_local_placement(referenced_placement)
|
||||
for obj in referenced_placement.PlacesObject:
|
||||
results.append({"product": obj, "matrix": matrix, "should_transform_children": False})
|
||||
results.append({"product": obj, "matrix": matrix, "is_si": self.settings["is_si"], "should_transform_children": False})
|
||||
results.extend(self.get_children_settings(referenced_placement))
|
||||
return results
|
||||
|
||||
|
||||
@@ -11,10 +11,13 @@ class Usecase:
|
||||
if not source_crs:
|
||||
return
|
||||
projected_crs = self.file.create_entity("IfcProjectedCRS", **{"Name": ""})
|
||||
self.file.create_entity("IfcMapConversion", **{
|
||||
"SourceCRS": source_crs,
|
||||
"TargetCRS": projected_crs,
|
||||
"Eastings": 0,
|
||||
"Northings": 0,
|
||||
"OrthogonalHeight": 0,
|
||||
})
|
||||
self.file.create_entity(
|
||||
"IfcMapConversion",
|
||||
**{
|
||||
"SourceCRS": source_crs,
|
||||
"TargetCRS": projected_crs,
|
||||
"Eastings": 0,
|
||||
"Northings": 0,
|
||||
"OrthogonalHeight": 0,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import ifcopenshell.util.unit
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
@@ -8,7 +5,6 @@ class Usecase:
|
||||
"map_conversion": {},
|
||||
"projected_crs": {},
|
||||
"true_north": [],
|
||||
"map_unit": "",
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
@@ -20,39 +16,8 @@ class Usecase:
|
||||
setattr(map_conversion, name, value)
|
||||
for name, value in self.settings["projected_crs"].items():
|
||||
setattr(projected_crs, name, value)
|
||||
self.remove_existing_map_unit(projected_crs)
|
||||
self.set_map_unit(projected_crs)
|
||||
self.set_true_north()
|
||||
|
||||
def remove_existing_map_unit(self, projected_crs):
|
||||
if projected_crs.MapUnit and len(self.file.get_inverse(projected_crs.MapUnit)) == 1:
|
||||
# TODO: go deeper for conversion units
|
||||
self.file.remove(projected_crs.MapUnit)
|
||||
|
||||
def set_map_unit(self, projected_crs):
|
||||
if not self.settings["map_unit"]:
|
||||
return
|
||||
|
||||
if "METRE" in self.settings["map_unit"]:
|
||||
projected_crs.MapUnit = self.file.createIfcSIUnit(
|
||||
None,
|
||||
"LENGTHUNIT",
|
||||
ifcopenshell.util.unit.get_prefix(self.settings["map_unit"]),
|
||||
ifcopenshell.util.unit.get_unit_name(self.settings["map_unit"]),
|
||||
)
|
||||
return
|
||||
|
||||
value_component = self.file.create_entity(
|
||||
"IfcReal", **{"wrappedValue": ifcopenshell.util.unit.si_conversions[self.settings["map_unit"]]}
|
||||
)
|
||||
si_unit = self.file.createIfcSIUnit(None, "LENGTHUNIT", None, "METRE")
|
||||
projected_crs.MapUnit = self.file.createIfcConversionBasedUnit(
|
||||
self.file.createIfcDimensionalExponents(1, 0, 0, 0, 0, 0, 0),
|
||||
"LENGTHUNIT",
|
||||
self.settings["map_unit"],
|
||||
self.file.createIfcMeasureWithUnit(value_component, si_unit),
|
||||
)
|
||||
|
||||
def set_true_north(self):
|
||||
if self.settings["true_north"] == []:
|
||||
return
|
||||
|
||||
@@ -11,10 +11,9 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
element = self.file.create_entity("IfcGridAxis", **{
|
||||
"axis_tag": self.settings["axis_tag"],
|
||||
"SameSense": self.settings["same_sense"]
|
||||
})
|
||||
element = self.file.create_entity(
|
||||
"IfcGridAxis", **{"axis_tag": self.settings["axis_tag"], "SameSense": self.settings["same_sense"]}
|
||||
)
|
||||
axes = list(getattr(self.settings["grid"], self.settings["uvw_axes"]) or [])
|
||||
axes.append(element)
|
||||
setattr(self.settings["grid"], self.settings["uvw_axes"], axes)
|
||||
|
||||
@@ -10,8 +10,11 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
return self.file.create_entity("IfcGroup", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"Name": "Unnamed"
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcGroup",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"Name": "Unnamed",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -14,12 +14,15 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
if not self.settings["group"].IsGroupedBy:
|
||||
return self.file.create_entity("IfcRelAssignsToGroup", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingGroup": self.settings["group"]
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcRelAssignsToGroup",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingGroup": self.settings["group"],
|
||||
}
|
||||
)
|
||||
rel = self.settings["group"].IsGroupedBy[0]
|
||||
related_objects = set(rel.RelatedObjects) or set()
|
||||
related_objects.add(self.settings["product"])
|
||||
|
||||
@@ -21,4 +21,4 @@ class Data:
|
||||
data = group.get_info()
|
||||
del data["OwnerHistory"]
|
||||
cls.groups[group.id()] = data
|
||||
cls.is_loaded=True
|
||||
cls.is_loaded = True
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"group": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"group": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -6,6 +6,4 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
return self.file.create_entity("IfcPresentationLayerAssignment", **{
|
||||
"Name": "Unnamed"
|
||||
})
|
||||
return self.file.create_entity("IfcPresentationLayerAssignment", **{"Name": "Unnamed"})
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"layer": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"layer": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -7,10 +7,9 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
layers = list(self.settings["layer_set"].MaterialLayers or [])
|
||||
layer = self.file.create_entity("IfcMaterialLayer", **{
|
||||
"Material": self.settings["material"],
|
||||
"LayerThickness": 1.
|
||||
})
|
||||
layer = self.file.create_entity(
|
||||
"IfcMaterialLayer", **{"Material": self.settings["material"], "LayerThickness": 1.0}
|
||||
)
|
||||
layers.append(layer)
|
||||
self.settings["layer_set"].MaterialLayers = layers
|
||||
return layer
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase():
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"element": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"element": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
class Usecase():
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"constituent": None,
|
||||
"attributes": {},
|
||||
"material": None
|
||||
}
|
||||
self.settings = {"constituent": None, "attributes": {}, "material": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
class Usecase():
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"layer": None,
|
||||
"attributes": {},
|
||||
"material": None
|
||||
}
|
||||
self.settings = {"layer": None, "attributes": {}, "material": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
class Usecase():
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"profile": None,
|
||||
"attributes": {},
|
||||
"profile_attributes": {},
|
||||
"material": None
|
||||
}
|
||||
self.settings = {"profile": None, "attributes": {}, "profile_attributes": {}, "material": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -46,11 +46,14 @@ class Usecase:
|
||||
name = dummy_profile.attribute_name(i)
|
||||
if "Radius" in name and name != "RoundingRadius":
|
||||
dummy_profile[i] = None
|
||||
dummy_solid = self.dummy.create_entity("IfcExtrudedAreaSolid", **{
|
||||
"SweptArea": dummy_profile,
|
||||
"ExtrudedDirection": self.dummy.createIfcDirection((0., 0., 1.)),
|
||||
"Depth": 1
|
||||
})
|
||||
dummy_solid = self.dummy.create_entity(
|
||||
"IfcExtrudedAreaSolid",
|
||||
**{
|
||||
"SweptArea": dummy_profile,
|
||||
"ExtrudedDirection": self.dummy.createIfcDirection((0.0, 0.0, 1.0)),
|
||||
"Depth": 1,
|
||||
}
|
||||
)
|
||||
self.settings_2d = ifcopenshell.geom.settings()
|
||||
self.settings_2d.set(self.settings_2d.INCLUDE_CURVES, True)
|
||||
shape = ifcopenshell.geom.create_shape(self.settings_2d, dummy_solid)
|
||||
@@ -77,61 +80,61 @@ class Usecase:
|
||||
def get_bottom_left(self, shape):
|
||||
v = shape.verts
|
||||
x = [v[i] for i in range(0, len(v), 3)]
|
||||
y = [v[i+1] for i in range(0, len(v), 3)]
|
||||
y = [v[i + 1] for i in range(0, len(v), 3)]
|
||||
width = max(x) - min(x)
|
||||
height = max(y) - min(y)
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width/2, height/2, 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width / 2, height / 2, 0.0)))
|
||||
|
||||
def get_bottom_centre(self, shape):
|
||||
v = shape.verts
|
||||
y = [v[i+1] for i in range(0, len(v), 3)]
|
||||
y = [v[i + 1] for i in range(0, len(v), 3)]
|
||||
height = max(y) - min(y)
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0., height/2, 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0.0, height / 2, 0.0)))
|
||||
|
||||
def get_bottom_right(self, shape):
|
||||
v = shape.verts
|
||||
x = [v[i] for i in range(0, len(v), 3)]
|
||||
y = [v[i+1] for i in range(0, len(v), 3)]
|
||||
y = [v[i + 1] for i in range(0, len(v), 3)]
|
||||
width = max(x) - min(x)
|
||||
height = max(y) - min(y)
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width/2, height/2, 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width / 2, height / 2, 0.0)))
|
||||
|
||||
def get_mid_depth_left(self, shape):
|
||||
v = shape.verts
|
||||
x = [v[i] for i in range(0, len(v), 3)]
|
||||
width = max(x) - min(x)
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width/2, 0., 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width / 2, 0.0, 0.0)))
|
||||
|
||||
def get_mid_depth_centre(self, shape):
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0., 0., 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)))
|
||||
|
||||
def get_mid_depth_right(self, shape):
|
||||
v = shape.verts
|
||||
x = [v[i] for i in range(0, len(v), 3)]
|
||||
width = max(x) - min(x)
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width/2, 0., 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width / 2, 0.0, 0.0)))
|
||||
|
||||
def get_top_left(self, shape):
|
||||
v = shape.verts
|
||||
x = [v[i] for i in range(0, len(v), 3)]
|
||||
y = [v[i+1] for i in range(0, len(v), 3)]
|
||||
y = [v[i + 1] for i in range(0, len(v), 3)]
|
||||
width = max(x) - min(x)
|
||||
height = max(y) - min(y)
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width/2, -height/2, 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width / 2, -height / 2, 0.0)))
|
||||
|
||||
def get_top_centre(self, shape):
|
||||
v = shape.verts
|
||||
y = [v[i+1] for i in range(0, len(v), 3)]
|
||||
y = [v[i + 1] for i in range(0, len(v), 3)]
|
||||
height = max(y) - min(y)
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0., -height/2, 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0.0, -height / 2, 0.0)))
|
||||
|
||||
def get_top_right(self, shape):
|
||||
v = shape.verts
|
||||
x = [v[i] for i in range(0, len(v), 3)]
|
||||
y = [v[i+1] for i in range(0, len(v), 3)]
|
||||
y = [v[i + 1] for i in range(0, len(v), 3)]
|
||||
width = max(x) - min(x)
|
||||
height = max(y) - min(y)
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width/2, -height/2, 0.)))
|
||||
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width / 2, -height / 2, 0.0)))
|
||||
|
||||
def update_representation(self, element):
|
||||
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
|
||||
@@ -4,10 +4,11 @@ import ifcopenshell
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"material_list": None, "material": None}
|
||||
self.settings = {"material_list": None, "material_index": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
materials = [m for m in self.settings["material_list"].Materials if m != self.settings["material"]]
|
||||
materials = list(self.settings["material_list"].Materials)
|
||||
materials.pop(self.settings["material_index"])
|
||||
self.settings["material_list"].Materials = materials
|
||||
|
||||
@@ -7,7 +7,9 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
address = self.file.create_entity(self.settings["ifc_class"], "OFFICE")
|
||||
addresses = list(self.settings["assigned_object"].Addresses) if self.settings["assigned_object"].Addresses else []
|
||||
addresses = (
|
||||
list(self.settings["assigned_object"].Addresses) if self.settings["assigned_object"].Addresses else []
|
||||
)
|
||||
addresses.append(address)
|
||||
self.settings["assigned_object"].Addresses = addresses
|
||||
return address
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"address": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"address": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"organisation": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"organisation": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"person": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"person": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"role": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"role": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# Note: it is the intent for you to override these with your own functions
|
||||
users = {}
|
||||
|
||||
|
||||
def get_person(ifc):
|
||||
people = ifc.by_type("IfcPerson") or [None]
|
||||
return people [0]
|
||||
return people[0]
|
||||
|
||||
|
||||
def get_organisation(ifc):
|
||||
@@ -14,3 +15,20 @@ def get_organisation(ifc):
|
||||
def get_application(ifc):
|
||||
applications = ifc.by_type("IfcApplication") or [None]
|
||||
return applications[0]
|
||||
|
||||
|
||||
def get_user(ifc):
|
||||
person = get_person(ifc)
|
||||
organisation = get_organisation(ifc)
|
||||
if not person or not organisation:
|
||||
return
|
||||
key = f"{person.id()}-{organisation.id()}"
|
||||
user = users.get(key)
|
||||
if not user:
|
||||
for element in ifc.by_type("IfcPersonAndOrganization"):
|
||||
if element.ThePerson == person and element.TheOrganization == organisation:
|
||||
users[key] = element
|
||||
user = element
|
||||
if not user:
|
||||
return ifc.create_entity("IfcPersonAndOrganization", ThePerson=person, TheOrganization=organisation)
|
||||
return user
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import time
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
@@ -13,34 +14,20 @@ class Usecase:
|
||||
def execute(self):
|
||||
if not hasattr(self.settings["element"], "OwnerHistory"):
|
||||
return
|
||||
self.settings["person"] = ifcopenshell.api.owner.settings.get_person(self.file)
|
||||
self.settings["organisation"] = ifcopenshell.api.owner.settings.get_organisation(self.file)
|
||||
user = ifcopenshell.api.owner.settings.get_user(self.file)
|
||||
application = ifcopenshell.api.owner.settings.get_application(self.file)
|
||||
if not user or not application:
|
||||
return
|
||||
if not self.settings["element"].OwnerHistory:
|
||||
self.settings["element"].OwnerHistory = ifcopenshell.api.run(
|
||||
"owner.create_owner_history", self.file, **self.settings
|
||||
)
|
||||
return self.settings["element"].OwnerHistory
|
||||
if len(self.file.get_inverse(self.settings["element"].OwnerHistory)) > 1:
|
||||
old_history = self.settings["element"].OwnerHistory
|
||||
self.settings["element"].OwnerHistory = self.file.create_entity("IfcOwnerHistory")
|
||||
for i, attribute in enumerate(old_history):
|
||||
self.settings["element"].OwnerHistory[i] = attribute
|
||||
user = self.get_user()
|
||||
application = ifcopenshell.api.owner.settings.get_application(self.file)
|
||||
new = ifcopenshell.util.element.copy(self.file, self.settings["element"].OwnerHistory)
|
||||
self.settings["element"].OwnerHistory = new
|
||||
self.settings["element"].OwnerHistory.ChangeAction = "MODIFIED"
|
||||
self.settings["element"].OwnerHistory.LastModifiedDate = int(time.time())
|
||||
self.settings["element"].OwnerHistory.LastModifyingUser = user
|
||||
self.settings["element"].OwnerHistory.LastModifyingApplication = application
|
||||
return self.settings["element"].OwnerHistory
|
||||
|
||||
def get_user(self):
|
||||
for element in self.file.by_type("IfcPersonAndOrganization"):
|
||||
if (
|
||||
element.ThePerson == self.settings["person"]
|
||||
and element.TheOrganization == self.settings["organisation"]
|
||||
):
|
||||
return element
|
||||
return self.file.create_entity(
|
||||
"IfcPersonAndOrganization",
|
||||
**{"ThePerson": self.settings["person"], "TheOrganization": self.settings["organisation"]},
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class Usecase():
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"profile": None, "attributes": {}}
|
||||
|
||||
@@ -39,7 +39,7 @@ class Usecase:
|
||||
if value is None:
|
||||
prop.NominalValue = None
|
||||
else:
|
||||
primary_measure_type = self.get_primary_measure_type(prop.Name, previous_value=prop.NominalValue)
|
||||
primary_measure_type = self.get_primary_measure_type(prop.Name, old_value=prop.NominalValue, new_value=value)
|
||||
prop.NominalValue = self.file.create_entity(primary_measure_type, value)
|
||||
del self.settings["properties"][prop.Name]
|
||||
|
||||
@@ -48,7 +48,9 @@ class Usecase:
|
||||
for name, value in self.settings["properties"].items():
|
||||
if value is None:
|
||||
continue
|
||||
primary_measure_type = self.get_primary_measure_type(name)
|
||||
primary_measure_type = self.get_primary_measure_type(name, new_value=value)
|
||||
if hasattr(value, "is_a"):
|
||||
value = value.wrappedValue
|
||||
properties.append(
|
||||
self.file.create_entity(
|
||||
"IfcPropertySingleValue",
|
||||
@@ -71,11 +73,22 @@ class Usecase:
|
||||
elif hasattr(self.settings["pset"], "Properties"): # For IfcMaterialProperties
|
||||
return self.settings["pset"].Properties or []
|
||||
|
||||
def get_primary_measure_type(self, name, previous_value=None):
|
||||
if not self.pset_template:
|
||||
return previous_value.is_a() if previous_value else "IfcLabel"
|
||||
for prop_template in self.pset_template.HasPropertyTemplates:
|
||||
if prop_template.Name != name:
|
||||
continue
|
||||
return prop_template.PrimaryMeasureType or "IfcLabel"
|
||||
return previous_value.is_a() if previous_value else "IfcLabel"
|
||||
def get_primary_measure_type(self, name, old_value=None, new_value=None):
|
||||
if self.pset_template:
|
||||
for prop_template in self.pset_template.HasPropertyTemplates:
|
||||
if prop_template.Name != name:
|
||||
continue
|
||||
return prop_template.PrimaryMeasureType or "IfcLabel"
|
||||
if old_value:
|
||||
return old_value.is_a()
|
||||
elif new_value and hasattr(new_value, "is_a"):
|
||||
return new_value.is_a()
|
||||
elif new_value is not None:
|
||||
if isinstance(new_value, str):
|
||||
return "IfcLabel"
|
||||
elif isinstance(new_value, float):
|
||||
return "IfcReal"
|
||||
elif isinstance(new_value, bool):
|
||||
return "IfcBoolean"
|
||||
elif isinstance(new_value, int):
|
||||
return "IfcInteger"
|
||||
|
||||
@@ -9,13 +9,16 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
prop_template = self.file.create_entity("IfcSimplePropertyTemplate", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"Name": "NewProperty",
|
||||
"PrimaryMeasureType": "IfcLabel",
|
||||
"TemplateType": "P_SINGLEVALUE",
|
||||
"AccessState": "READWRITE"
|
||||
})
|
||||
prop_template = self.file.create_entity(
|
||||
"IfcSimplePropertyTemplate",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"Name": "NewProperty",
|
||||
"PrimaryMeasureType": "IfcLabel",
|
||||
"TemplateType": "P_SINGLEVALUE",
|
||||
"AccessState": "READWRITE",
|
||||
}
|
||||
)
|
||||
has_property_templates = list(self.settings["pset_template"].HasPropertyTemplates or [])
|
||||
has_property_templates.append(prop_template)
|
||||
self.settings["pset_template"].HasPropertyTemplates = has_property_templates
|
||||
|
||||
@@ -9,9 +9,12 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.file.create_entity("IfcPropertySetTemplate", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"Name": "New_Pset",
|
||||
"TemplateType": "PSET_TYPEDRIVENONLY",
|
||||
"ApplicableEntity": "IfcTypeObject"
|
||||
})
|
||||
self.file.create_entity(
|
||||
"IfcPropertySetTemplate",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"Name": "New_Pset",
|
||||
"TemplateType": "PSET_TYPEDRIVENONLY",
|
||||
"ApplicableEntity": "IfcTypeObject",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -29,6 +29,6 @@ class Data:
|
||||
"GlobalId": data["GlobalId"],
|
||||
"Name": data["Name"],
|
||||
"Description": data["Description"],
|
||||
"PrimaryMeasureType": data["PrimaryMeasureType"]
|
||||
"PrimaryMeasureType": data["PrimaryMeasureType"],
|
||||
}
|
||||
cls.is_loaded = True
|
||||
|
||||
@@ -4,9 +4,7 @@ import ifcopenshell.util.element
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"prop_template": None
|
||||
}
|
||||
self.settings = {"prop_template": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@ import ifcopenshell.util.element
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"pset_template": None
|
||||
}
|
||||
self.settings = {"pset_template": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -25,11 +25,12 @@ class Usecase:
|
||||
# https://forums.buildingsmart.org/t/what-are-allowed-to-be-root-level-construction-resources/3550
|
||||
if self.settings["parent_resource"]:
|
||||
ifcopenshell.api.run(
|
||||
"nest.assign_object", self.file, related_object=resource, relating_object=self.settings["parent_resource"]
|
||||
"nest.assign_object",
|
||||
self.file,
|
||||
related_object=resource,
|
||||
relating_object=self.settings["parent_resource"],
|
||||
)
|
||||
else:
|
||||
context = self.file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definition=resource, relating_context=context
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definition=resource, relating_context=context)
|
||||
return resource
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"resource": None, "ifc_class": "IfcQuantityCount"}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
quantity = self.file.create_entity(self.settings["ifc_class"], Name="Unnamed")
|
||||
quantity[3] = 0.0
|
||||
old_quantity = self.settings["resource"].BaseQuantity
|
||||
self.settings["resource"].BaseQuantity = quantity
|
||||
if old_quantity:
|
||||
ifcopenshell.util.element.remove_deep(self.file, old_quantity)
|
||||
return quantity
|
||||
@@ -1,5 +1,6 @@
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import math
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"resource": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.productivity = ifcopenshell.util.element.get_psets(self.settings["resource"]).get(
|
||||
"EPset_Productivity", None
|
||||
)
|
||||
if not self.productivity:
|
||||
return
|
||||
unit_consumed = self.get_unit_consumed()
|
||||
self.unit_produced_name = self.productivity.get("BaseQuantityProducedName", None)
|
||||
unit_produced = self.productivity.get("BaseQuantityProducedValue", None)
|
||||
total_produced = self.get_total_produced()
|
||||
if not unit_consumed or not unit_produced or not total_produced:
|
||||
return
|
||||
if not self.settings["resource"].Usage:
|
||||
ifcopenshell.api.run("resource.add_resource_time", self.file, resource=self.settings["resource"])
|
||||
if "T" in self.productivity.get("BaseQuantityConsumed", None):
|
||||
seconds = (unit_consumed.days * 24 * 60 * 60) + unit_consumed.seconds
|
||||
amount_worked = total_produced / unit_produced * seconds
|
||||
self.settings["resource"].Usage.ScheduleWork = f"PT{amount_worked / 60 / 60}H"
|
||||
else:
|
||||
days = unit_consumed.days + (unit_consumed.seconds / (24 * 60 * 60))
|
||||
amount_worked = total_produced / unit_produced * days
|
||||
self.settings["resource"].Usage.ScheduleWork = f"P{amount_worked}D"
|
||||
|
||||
def get_unit_consumed(self):
|
||||
duration = self.productivity.get("BaseQuantityConsumed", None)
|
||||
if not duration:
|
||||
return
|
||||
return ifcopenshell.util.date.ifc2datetime(duration)
|
||||
|
||||
def get_total_produced(self):
|
||||
total = 0
|
||||
for rel in self.settings["resource"].HasAssignments or []:
|
||||
if not rel.is_a("IfcRelAssignsToProcess"):
|
||||
continue
|
||||
for rel2 in rel.RelatingProcess.HasAssignments or []:
|
||||
if not rel2.is_a("IfcRelAssignsToProduct"):
|
||||
continue
|
||||
if self.unit_produced_name == "Count":
|
||||
total += 1
|
||||
else:
|
||||
psets = ifcopenshell.util.element.get_psets(rel2.RelatingProduct)
|
||||
for pset in psets.values():
|
||||
for name, value in pset.items():
|
||||
if name == self.unit_produced_name:
|
||||
total += float(value)
|
||||
return total
|
||||
@@ -1,17 +1,20 @@
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.date
|
||||
from ifcopenshell.api.cost.data import CostValueTrait
|
||||
|
||||
|
||||
class Data:
|
||||
class Data(CostValueTrait):
|
||||
is_loaded = False
|
||||
resources = {}
|
||||
resource_times = {}
|
||||
cost_values = {}
|
||||
|
||||
@classmethod
|
||||
def purge(cls):
|
||||
cls.is_loaded = False
|
||||
cls.resources = {}
|
||||
cls.resource_times = {}
|
||||
cls.cost_values = {}
|
||||
|
||||
@classmethod
|
||||
def load(cls, file):
|
||||
@@ -20,11 +23,12 @@ class Data:
|
||||
return
|
||||
cls.load_resources()
|
||||
cls.load_resource_times()
|
||||
cls.is_loaded=True
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def load_resources(cls):
|
||||
cls.resources = {}
|
||||
cls.cost_values = {}
|
||||
for resource in cls._file.by_type("IfcResource"):
|
||||
data = resource.get_info()
|
||||
del data["OwnerHistory"]
|
||||
@@ -40,6 +44,13 @@ class Data:
|
||||
data["HasContext"] = resource.HasContext[0].RelatingContext.id() if resource.HasContext else None
|
||||
if resource.Usage:
|
||||
data["Usage"] = data["Usage"].id()
|
||||
data["TotalCostQuantity"] = cls.get_total_quantity(resource)
|
||||
if resource.BaseQuantity:
|
||||
data["BaseQuantity"] = resource.BaseQuantity.get_info()
|
||||
del data["BaseQuantity"]["Unit"]
|
||||
if resource.BaseCosts:
|
||||
data["BaseCosts"] = [e.id() for e in resource.BaseCosts]
|
||||
cls.load_cost_values(resource, data)
|
||||
cls.resources[resource.id()] = data
|
||||
|
||||
@classmethod
|
||||
@@ -52,6 +63,6 @@ class Data:
|
||||
continue
|
||||
if "Start" in key or "Finish" in key or key == "StatusTime":
|
||||
data[key] = ifcopenshell.util.date.ifc2datetime(value)
|
||||
elif "Work" in key or key =="LevelingDelay":
|
||||
elif "Work" in key or key == "LevelingDelay":
|
||||
data[key] = ifcopenshell.util.date.ifc2datetime(value)
|
||||
cls.resource_times[resource_time.id()] = data
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"physical_quantity": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["physical_quantity"], name, value)
|
||||
@@ -18,10 +18,7 @@ class Usecase:
|
||||
and "ScheduleFinish" in self.settings["attributes"].keys()
|
||||
):
|
||||
del self.settings["attributes"]["ScheduleFinish"]
|
||||
if (
|
||||
self.settings["attributes"].get("ActualWork", None)
|
||||
and "ActualFinish" in self.settings["attributes"].keys()
|
||||
):
|
||||
if self.settings["attributes"].get("ActualWork", None) and "ActualFinish" in self.settings["attributes"].keys():
|
||||
del self.settings["attributes"]["ActualFinish"]
|
||||
|
||||
for name, value in self.settings["attributes"].items():
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"resource": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
old_quantity = self.settings["resource"].BaseQuantity
|
||||
self.settings["resource"].BaseQuantity = None
|
||||
if old_quantity:
|
||||
ifcopenshell.util.element.remove_deep(self.file, old_quantity)
|
||||
@@ -20,12 +20,16 @@ class Usecase:
|
||||
def copy_indirect_attributes(self, from_element, to_element):
|
||||
for inverse in self.file.get_inverse(from_element):
|
||||
if inverse.is_a("IfcRelDefinesByProperties"):
|
||||
# Properties must not be shared between objects for convenience of authoring
|
||||
inverse = ifcopenshell.util.element.copy(self.file, inverse)
|
||||
inverse.RelatedObjects = [to_element]
|
||||
pset = ifcopenshell.util.element.copy_deep(self.file, inverse.RelatingPropertyDefinition)
|
||||
inverse.RelatingPropertyDefinition = pset
|
||||
elif inverse.is_a("IfcRelAggregates") and inverse.RelatingObject == from_element:
|
||||
continue
|
||||
elif inverse.is_a("IfcRelFillsElement"):
|
||||
continue
|
||||
else:
|
||||
# TODO: Consider whether this general approach is good or not. Maybe it isn't.
|
||||
for i, value in enumerate(inverse):
|
||||
if value == from_element:
|
||||
new_inverse = ifcopenshell.util.element.copy(self.file, inverse)
|
||||
|
||||
@@ -14,10 +14,13 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
element = self.file.create_entity(self.settings["ifc_class"], **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file)
|
||||
})
|
||||
element = self.file.create_entity(
|
||||
self.settings["ifc_class"],
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
}
|
||||
)
|
||||
element.Name = self.settings["name"] or None
|
||||
if self.settings["predefined_type"]:
|
||||
if hasattr(element, "PredefinedType"):
|
||||
|
||||
@@ -13,5 +13,5 @@ class Data:
|
||||
cls.products[product_id] = {
|
||||
"type": product.is_a(),
|
||||
"PredefinedType": product.PredefinedType if hasattr(product, "PredefinedType") else None,
|
||||
"ObjectType": product.ObjectType if hasattr(product, "ObjectType") else None
|
||||
"ObjectType": product.ObjectType if hasattr(product, "ObjectType") else None,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
|
||||
@@ -25,7 +25,5 @@ class Usecase:
|
||||
work_plan.StartTime = ifcopenshell.util.date.datetime2ifc(self.settings["start_time"], "IfcDateTime")
|
||||
|
||||
context = self.file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definition=work_plan, relating_context=context
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definition=work_plan, relating_context=context)
|
||||
return work_plan
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import math
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"task": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.seconds_per_workday = self.calculate_seconds_per_workday()
|
||||
duration = self.calculate_max_resource_usage_duration()
|
||||
if duration:
|
||||
self.set_task_duration(duration)
|
||||
|
||||
def calculate_max_resource_usage_duration(self):
|
||||
max_duration = 0
|
||||
for rel in self.settings["task"].OperatesOn or []:
|
||||
for related_object in rel.RelatedObjects:
|
||||
if related_object.is_a("IfcConstructionResource"):
|
||||
duration = self.calculate_duration_in_days(related_object)
|
||||
if duration and duration > max_duration:
|
||||
max_duration = duration
|
||||
return max_duration
|
||||
|
||||
def set_task_duration(self, duration):
|
||||
if not self.settings["task"].TaskTime:
|
||||
ifcopenshell.api.run("sequence.add_task_time", self.file, task=self.settings["task"])
|
||||
self.settings["task"].TaskTime.ScheduleDuration = f"P{duration}D"
|
||||
|
||||
def calculate_seconds_per_workday(self):
|
||||
default_seconds_per_workday = 8 * 60 * 60
|
||||
work_schedule = self.get_work_schedule(self.settings["task"])
|
||||
if not work_schedule:
|
||||
return default_seconds_per_workday
|
||||
psets = ifcopenshell.util.element.get_psets(work_schedule)
|
||||
if (
|
||||
not psets
|
||||
or "Pset_WorkControlCommon" not in psets
|
||||
or "WorkDayDuration" not in psets["Pset_WorkControlCommon"]
|
||||
):
|
||||
return default_seconds_per_workday
|
||||
work_day_duration = ifcopenshell.util.date.ifc2datetime(psets["Pset_WorkControlCommon"]["WorkDayDuration"])
|
||||
return work_day_duration.seconds
|
||||
|
||||
def get_work_schedule(self, task):
|
||||
for rel in task.HasAssignments or []:
|
||||
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcWorkSchedule"):
|
||||
return rel.RelatingControl
|
||||
for rel in task.Nests or []:
|
||||
return self.get_work_schedule(rel.RelatingObject)
|
||||
|
||||
def calculate_duration_in_days(self, resource):
|
||||
if not resource.Usage or not resource.Usage.ScheduleWork:
|
||||
return
|
||||
schedule_usage = resource.Usage.ScheduleUsage or 1
|
||||
schedule_duration = ifcopenshell.util.date.ifc2datetime(resource.Usage.ScheduleWork)
|
||||
if self.is_hourly_work(resource.Usage.ScheduleWork):
|
||||
schedule_seconds = (schedule_duration.days * 24 * 60 * 60) + schedule_duration.seconds
|
||||
else:
|
||||
partial_days = schedule_duration.seconds / (24 * 60 * 60)
|
||||
schedule_seconds = (schedule_duration.days + partial_days) * self.seconds_per_workday
|
||||
return math.ceil((schedule_seconds / self.seconds_per_workday) / schedule_usage)
|
||||
|
||||
def is_hourly_work(self, schedule_work):
|
||||
return "T" in schedule_work
|
||||
@@ -142,8 +142,14 @@ class Data:
|
||||
for r in task.HasAssignments
|
||||
if r.is_a("IfcRelAssignsToProduct")
|
||||
]
|
||||
[data["Resources"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcResource")]) for r in task.OperatesOn]
|
||||
[data["Controls"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcControl")]) for r in task.OperatesOn]
|
||||
[
|
||||
data["Resources"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcResource")])
|
||||
for r in task.OperatesOn
|
||||
]
|
||||
[
|
||||
data["Controls"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcControl")])
|
||||
for r in task.OperatesOn
|
||||
]
|
||||
[data["Inputs"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcProduct")]) for r in task.OperatesOn]
|
||||
[data["IsPredecessorTo"].append(rel.id()) for rel in task.IsPredecessorTo or []]
|
||||
[data["IsSuccessorFrom"].append(rel.id()) for rel in task.IsSuccessorFrom or []]
|
||||
|
||||
@@ -55,13 +55,10 @@ class Usecase:
|
||||
elif "ScheduleFinish" in self.settings["attributes"].keys() and self.settings["task_time"].ScheduleStart:
|
||||
self.calculate_duration()
|
||||
|
||||
if (
|
||||
self.settings["task_time"].ScheduleDuration
|
||||
and (
|
||||
"ScheduleStart" in self.settings["attributes"].keys()
|
||||
or "ScheduleFinish" in self.settings["attributes"].keys()
|
||||
or "ScheduleDuration" in self.settings["attributes"].keys()
|
||||
)
|
||||
if self.settings["task_time"].ScheduleDuration and (
|
||||
"ScheduleStart" in self.settings["attributes"].keys()
|
||||
or "ScheduleFinish" in self.settings["attributes"].keys()
|
||||
or "ScheduleDuration" in self.settings["attributes"].keys()
|
||||
):
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", self.file, task=self.task)
|
||||
|
||||
|
||||
@@ -19,9 +19,5 @@ class Usecase:
|
||||
for rel in self.settings["work_schedule"].Controls:
|
||||
for related_object in rel.RelatedObjects:
|
||||
if related_object.is_a("IfcTask"):
|
||||
ifcopenshell.api.run(
|
||||
"sequence.remove_task",
|
||||
self.file,
|
||||
task=related_object
|
||||
)
|
||||
ifcopenshell.api.run("sequence.remove_task", self.file, task=related_object)
|
||||
self.file.remove(self.settings["work_schedule"])
|
||||
|
||||
@@ -15,6 +15,4 @@ class Usecase:
|
||||
self.file.remove(self.settings["rel_sequence"].TimeLag)
|
||||
else:
|
||||
self.settings["rel_sequence"].TimeLag = None
|
||||
ifcopenshell.api.run(
|
||||
"sequence.cascade_schedule", self.file, task=self.settings["rel_sequence"].RelatedProcess
|
||||
)
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", self.file, task=self.settings["rel_sequence"].RelatedProcess)
|
||||
|
||||
@@ -51,4 +51,5 @@ class Usecase:
|
||||
self.file,
|
||||
product=self.settings["product"],
|
||||
matrix=ifcopenshell.util.placement.get_local_placement(self.settings["product"].ObjectPlacement),
|
||||
is_si=False,
|
||||
)
|
||||
|
||||
@@ -46,5 +46,5 @@ class Data:
|
||||
"Name": element.Name,
|
||||
"LongName": element.LongName,
|
||||
"Decomposes": decomposes,
|
||||
"IsDecomposedBy": is_decomposed_by
|
||||
"IsDecomposedBy": is_decomposed_by,
|
||||
}
|
||||
|
||||
+9
-6
@@ -14,12 +14,15 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
if not self.settings["structural_analysis_model"].IsGroupedBy:
|
||||
return self.file.create_entity("IfcRelAssignsToGroup", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingGroup": self.settings["structural_analysis_model"]
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcRelAssignsToGroup",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingGroup": self.settings["structural_analysis_model"],
|
||||
}
|
||||
)
|
||||
rel = self.settings["structural_analysis_model"].IsGroupedBy[0]
|
||||
related_objects = set(rel.RelatedObjects) or set()
|
||||
related_objects.add(self.settings["product"])
|
||||
|
||||
@@ -144,8 +144,6 @@ class Data:
|
||||
|
||||
@classmethod
|
||||
def load_structural_connection(cls, product_id):
|
||||
cls.connects_structural_members = {}
|
||||
|
||||
connection = cls._file.by_id(product_id)
|
||||
data = connection.get_info()
|
||||
del data["OwnerHistory"]
|
||||
@@ -155,7 +153,9 @@ class Data:
|
||||
if connection.is_a("IfcStructuralCurveConnection"):
|
||||
data["Axis"] = data["Axis"].id() if data["Axis"] is not None else None
|
||||
if connection.is_a("IfcStructuralPointConnection"):
|
||||
data["ConditionCoordinateSystem"] = data["ConditionCoordinateSystem"].id() if data["ConditionCoordinateSystem"] is not None else None
|
||||
data["ConditionCoordinateSystem"] = (
|
||||
data["ConditionCoordinateSystem"].id() if data["ConditionCoordinateSystem"] is not None else None
|
||||
)
|
||||
|
||||
data["ConnectsStructuralMembers"] = []
|
||||
|
||||
@@ -238,7 +238,7 @@ class Data:
|
||||
data["Representation"] = data["Representation"].id() if data["Representation"] is not None else None
|
||||
if member.is_a("IfcStructuralCurveMember"):
|
||||
data["Axis"] = data["Axis"].id() if data["Axis"] is not None else None
|
||||
|
||||
|
||||
data["ConnectsStructuralActivities"] = []
|
||||
data["ConnectedBy"] = []
|
||||
|
||||
@@ -249,6 +249,5 @@ class Data:
|
||||
for rel in member.ConnectedBy or []:
|
||||
cls.load_connects_structural_member(rel)
|
||||
data["ConnectedBy"].append(rel.id())
|
||||
|
||||
|
||||
cls.members[member.id()] = data
|
||||
|
||||
+1
-4
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"structural_analysis_model": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"structural_analysis_model": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
+1
-4
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"condition": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"condition": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ class Usecase:
|
||||
ccs = self.file.createIfcAxis2Placement3D(point, None, None)
|
||||
self.settings["structural_item"].ConditionCoordinateSystem = ccs
|
||||
print(ccs)
|
||||
|
||||
|
||||
ccs = self.settings["structural_item"].ConditionCoordinateSystem
|
||||
print("use case")
|
||||
print(ccs)
|
||||
@@ -20,4 +20,4 @@ class Usecase:
|
||||
ccs.Axis = self.file.createIfcDirection(self.settings["axis"])
|
||||
if ccs.RefDirection and len(self.file.get_inverse(ccs.RefDirection)) == 1:
|
||||
self.file.remove(ccs.RefDirection)
|
||||
ccs.RefDirection = self.file.createIfcDirection(self.settings["ref_direction"])
|
||||
ccs.RefDirection = self.file.createIfcDirection(self.settings["ref_direction"])
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"structural_load": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"structural_load": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
-1
@@ -16,4 +16,3 @@ class Usecase:
|
||||
**{"connection": self.settings["relation"].RelatedStructuralConnection}
|
||||
)
|
||||
self.file.remove(self.settings["relation"])
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class Usecase:
|
||||
new_items = []
|
||||
removed_items = []
|
||||
for item in items:
|
||||
if not i.is_a("IfcStyledItem"):
|
||||
if not item.is_a("IfcStyledItem"):
|
||||
continue
|
||||
if self.has_proposed_style(item):
|
||||
return
|
||||
@@ -63,8 +63,8 @@ class Usecase:
|
||||
def get_styled_representation(self, definition_representation):
|
||||
representations = [
|
||||
r
|
||||
for r in definition_representation.Representations if r.is_a("IfcStyledRepresentation")
|
||||
and r.ContextOfItems == self.settings["context"]
|
||||
for r in definition_representation.Representations
|
||||
if r.is_a("IfcStyledRepresentation") and r.ContextOfItems == self.settings["context"]
|
||||
]
|
||||
if representations:
|
||||
return representations[0]
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"style": None,
|
||||
"surface_colour": [], # RGB
|
||||
"diffuse_colour": [], # RGB
|
||||
"transparency": 0,
|
||||
"external_definition": {
|
||||
"location": None,
|
||||
"identification": None,
|
||||
"name": "Name"
|
||||
},
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
#has_external_definition = None
|
||||
for element in self.file.traverse(self.settings["style"]):
|
||||
if element.is_a("IfcSurfaceStyleShading"):
|
||||
if element.SurfaceColour:
|
||||
self.update_colour_rgb(element.SurfaceColour, self.settings["surface_colour"])
|
||||
else:
|
||||
element.SurfaceColour = self.create_colour_rgb(self.settings["surface_colour"])
|
||||
element.Transparency = self.settings["transparency"]
|
||||
if element.is_a("IfcSurfaceStyleRendering"):
|
||||
if element.DiffuseColour:
|
||||
self.update_colour_rgb(element.DiffuseColour, self.settings["diffuse_colour"])
|
||||
else:
|
||||
element.DiffuseColour = self.create_colour_rgb(self.settings["diffuse_colour"])
|
||||
# TODO: Move to separate usecase
|
||||
#if element.is_a("IfcExternallyDefinedSurfaceStyle"):
|
||||
# element.Location = self.settings["location"]
|
||||
# element.Identification = self.settings["identification"]
|
||||
# element.Name = self.settings["name"]
|
||||
# has_external_definition = True
|
||||
#if not has_external_definition:
|
||||
# styles = list(self.settings["style"].Styles)
|
||||
# styles.append(self.create_externally_defined_surface_style())
|
||||
# self.settings["style"].Styles = styles
|
||||
return self.settings["style"]
|
||||
|
||||
def create_surface_style_rendering(self):
|
||||
return self.file.create_entity("IfcSurfaceStyleRendering", **{
|
||||
"SurfaceColour": self.create_colour_rgb(self.settings["surface_colour"]),
|
||||
"Transparency": self.settings["transparency"],
|
||||
"ReflectanceMethod": "NOTDEFINED",
|
||||
"DiffuseColour": self.create_colour_rgb(self.settings["diffuse_colour"])
|
||||
})
|
||||
|
||||
def create_externally_defined_surface_style(self):
|
||||
self.file.create_entity(
|
||||
"IfcExternallyDefinedSurfaceStyle", **{
|
||||
"Location": self.settings["location"],
|
||||
"Identification": self.settings["identification"],
|
||||
"Name": self.settings["name"],
|
||||
}
|
||||
)
|
||||
|
||||
def create_colour_rgb(self, colour):
|
||||
return self.file.createIfcColourRgb(None, colour[0], colour[1], colour[2])
|
||||
|
||||
def update_colour_rgb(self, element, colour):
|
||||
element[1] = colour[0]
|
||||
element[2] = colour[1]
|
||||
element[3] = colour[2]
|
||||
@@ -0,0 +1,45 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"style": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for key, value in self.settings["attributes"].items():
|
||||
if key == "SurfaceColour":
|
||||
self.edit_surface_colour(value)
|
||||
elif self.is_colour_or_factor(key):
|
||||
self.edit_colour_or_factor(key, value)
|
||||
else:
|
||||
setattr(self.settings["style"], key, value)
|
||||
|
||||
def edit_surface_colour(self, value):
|
||||
self.settings["style"].SurfaceColour[1] = value[0]
|
||||
self.settings["style"].SurfaceColour[2] = value[1]
|
||||
self.settings["style"].SurfaceColour[3] = value[2]
|
||||
|
||||
def is_colour_or_factor(self, name):
|
||||
return name in [
|
||||
"DiffuseColour",
|
||||
"TransmissionColour",
|
||||
"DiffuseTransmissionColour",
|
||||
"ReflectionColour",
|
||||
"SpecularColour",
|
||||
]
|
||||
|
||||
def edit_colour_or_factor(self, name, value):
|
||||
if isinstance(value, (list, tuple)):
|
||||
attribute = getattr(self.settings["style"], name)
|
||||
if not attribute or not attribute.is_a("IfcColourRgb"):
|
||||
colour = self.file.createIfcColourRgb(None, 0, 0, 0)
|
||||
setattr(self.settings["style"], name, colour)
|
||||
attribute = getattr(self.settings["style"], name)
|
||||
attribute[1] = value[0]
|
||||
attribute[2] = value[1]
|
||||
attribute[3] = value[2]
|
||||
else:
|
||||
existing_value = getattr(self.settings["style"], name)
|
||||
if existing_value and existing_value.id():
|
||||
self.file.remove(existing_value)
|
||||
setattr(self.settings["style"], name, self.file.createIfcNormalisedRatioMeasure(value))
|
||||
@@ -10,8 +10,11 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
return self.file.create_entity("IfcSystem", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"Name": "Unnamed"
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcSystem",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"Name": "Unnamed",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -14,12 +14,15 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
if not self.settings["system"].IsGroupedBy:
|
||||
return self.file.create_entity("IfcRelAssignsToGroup", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingGroup": self.settings["system"]
|
||||
})
|
||||
return self.file.create_entity(
|
||||
"IfcRelAssignsToGroup",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingGroup": self.settings["system"],
|
||||
}
|
||||
)
|
||||
rel = self.settings["system"].IsGroupedBy[0]
|
||||
related_objects = set(rel.RelatedObjects) or set()
|
||||
related_objects.add(self.settings["product"])
|
||||
|
||||
@@ -21,4 +21,4 @@ class Data:
|
||||
data = system.get_info()
|
||||
del data["OwnerHistory"]
|
||||
cls.systems[system.id()] = data
|
||||
cls.is_loaded=True
|
||||
cls.is_loaded = True
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"system": None,
|
||||
"attributes": {}
|
||||
}
|
||||
self.settings = {"system": None, "attributes": {}}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -5,9 +5,7 @@ import ifcopenshell.api
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"related_object": None
|
||||
}
|
||||
self.settings = {"related_object": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
|
||||
@@ -83,6 +83,10 @@ class Usecase:
|
||||
name = "{}inch".format(name_prefix + " " if name_prefix else "")
|
||||
elif data["raw"] == "FEET":
|
||||
name = "{}foot".format(name_prefix + " " if name_prefix else "")
|
||||
elif data["raw"] == "MILES":
|
||||
name = "{}mile".format(name_prefix + " " if name_prefix else "")
|
||||
elif data["raw"] == "THOU":
|
||||
name = "{}thou".format(name_prefix + " " if name_prefix else "")
|
||||
value_component = self.file.create_entity(
|
||||
"IfcReal", **{"wrappedValue": ifcopenshell.util.unit.si_conversions[name]}
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase():
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
self.settings = {"unit": None}
|
||||
|
||||
@@ -9,8 +9,18 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.file.create_entity("IfcRelFillsElement", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"RelatingOpeningElement": self.settings["opening"],
|
||||
"RelatedBuildingElement": self.settings["element"]
|
||||
})
|
||||
fills_voids = self.settings["element"].FillsVoids
|
||||
|
||||
if fills_voids:
|
||||
if fills_voids[0].RelatingOpeningElement == self.settings["opening"]:
|
||||
return
|
||||
self.file.remove(fills_voids[0])
|
||||
|
||||
self.file.create_entity(
|
||||
"IfcRelFillsElement",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"RelatingOpeningElement": self.settings["opening"],
|
||||
"RelatedBuildingElement": self.settings["element"],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -10,9 +10,19 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.file.create_entity("IfcRelVoidsElement", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatingBuildingElement": self.settings["element"],
|
||||
"RelatedOpeningElement": self.settings["opening"]
|
||||
})
|
||||
voids_elements = self.settings["opening"].VoidsElements
|
||||
|
||||
if voids_elements:
|
||||
if voids_elements[0].RelatingBuildingElement == self.settings["element"]:
|
||||
return
|
||||
self.file.remove(voids_elements[0])
|
||||
|
||||
self.file.create_entity(
|
||||
"IfcRelVoidsElement",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatingBuildingElement": self.settings["element"],
|
||||
"RelatedOpeningElement": self.settings["opening"],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -40,9 +40,9 @@ class Data:
|
||||
cls.fillings[filling_id] = {"Name": filling.Name, "FillsVoid": opening_id}
|
||||
cls.openings[opening_id]["HasFillings"].add(filling_id)
|
||||
return # See bug #1224
|
||||
#if not hasattr(product, "HasOpenings") or not product.HasOpenings:
|
||||
# if not hasattr(product, "HasOpenings") or not product.HasOpenings:
|
||||
# return
|
||||
#for rel_voids_element in product.HasOpenings:
|
||||
# for rel_voids_element in product.HasOpenings:
|
||||
# opening = rel_voids_element.RelatedOpeningElement
|
||||
# opening_id = int(opening.id())
|
||||
# fillings = []
|
||||
|
||||
@@ -9,15 +9,8 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
to_remove = [] # See bug #1224
|
||||
for rel in self.file.by_type("IfcRelVoidsElement"):
|
||||
if rel.RelatedOpeningElement == self.settings["opening"]:
|
||||
to_remove.append(rel)
|
||||
break
|
||||
for rel in self.file.by_type("IfcRelFillsElement"):
|
||||
if rel.RelatingOpeningElement == self.settings["opening"]:
|
||||
to_remove.append(rel)
|
||||
break
|
||||
for rel in self.settings["opening"].VoidsElements:
|
||||
self.file.remove(rel)
|
||||
for rel in self.settings["opening"].HasFillings:
|
||||
self.file.remove(rel)
|
||||
ifcopenshell.api.run("root.remove_product", self.file, product=self.settings["opening"])
|
||||
for element in to_remove:
|
||||
self.file.remove(element)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user