This commit is contained in:
Andrej730
2024-05-23 12:02:37 +05:00
parent 4d9f47b3a7
commit 073e471305
8 changed files with 188 additions and 113 deletions
@@ -23,6 +23,7 @@ import ifccsv
import logging import logging
import tempfile import tempfile
import ifcopenshell import ifcopenshell
import ifcopenshell.util.selector
import blenderbim.tool as tool import blenderbim.tool as tool
import blenderbim.bim.module.drawing.scheduler as scheduler import blenderbim.bim.module.drawing.scheduler as scheduler
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
@@ -19,6 +19,7 @@
import bpy import bpy
import blenderbim.tool as tool import blenderbim.tool as tool
import ifcopenshell import ifcopenshell
import ifcopenshell.util.resource
def refresh(): def refresh():
@@ -139,7 +140,7 @@ class ResourceData:
return results return results
@classmethod @classmethod
def active_resource_ids(cls): def active_resource_ids(cls) -> list[int]:
obj = bpy.context.active_object obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
if not element: if not element:
+78 -33
View File
@@ -18,42 +18,57 @@
# ############################################################################ # # ############################################################################ #
from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union, Iterable
def load_resources(resource): if TYPE_CHECKING:
import bpy
import ifcopenshell
import blenderbim.tool as tool
def load_resources(resource: tool.Resource) -> None:
resource.load_resources() resource.load_resources()
def add_resource(tool_ifc, resource_tool, ifc_class, parent_resource=None): def add_resource(
tool_ifc: tool.Ifc,
resource_tool: tool.Resource,
ifc_class,
parent_resource: Optional[ifcopenshell.entity_instance] = None,
) -> None:
tool_ifc.run("resource.add_resource", ifc_class=ifc_class, parent_resource=parent_resource) tool_ifc.run("resource.add_resource", ifc_class=ifc_class, parent_resource=parent_resource)
resource_tool.load_resources() resource_tool.load_resources()
def disable_editing_resource(resource_tool): def disable_editing_resource(resource_tool: tool.Resource) -> None:
resource_tool.disable_editing_resource() resource_tool.disable_editing_resource()
def disable_resource_editing_ui(resource_tool): def disable_resource_editing_ui(resource_tool: tool.Resource) -> None:
resource_tool.disable_resource_editing_ui() resource_tool.disable_resource_editing_ui()
def enable_editing_resource(resource_tool, resource): def enable_editing_resource(resource_tool: tool.Resource, resource) -> None:
resource_tool.enable_editing_resource(resource) resource_tool.enable_editing_resource(resource)
resource_tool.load_resource_attributes(resource) resource_tool.load_resource_attributes(resource)
def edit_resource(ifc, resource_tool, resource): def edit_resource(ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None:
attributes = resource_tool.get_resource_attributes() attributes = resource_tool.get_resource_attributes()
ifc.run("resource.edit_resource", resource=resource, attributes=attributes) ifc.run("resource.edit_resource", resource=resource, attributes=attributes)
resource_tool.load_resource_properties() resource_tool.load_resource_properties()
resource_tool.disable_editing_resource() resource_tool.disable_editing_resource()
def remove_resource(ifc, resource_tool, resource=None): def remove_resource(ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None:
ifc.run("resource.remove_resource", resource=resource) ifc.run("resource.remove_resource", resource=resource)
resource_tool.load_resources() resource_tool.load_resources()
def enable_editing_resource_time(ifc_tool, resource_tool, resource): def enable_editing_resource_time(
ifc_tool, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance
) -> None:
resource_time = resource_tool.get_resource_time(resource) resource_time = resource_tool.get_resource_time(resource)
if resource_time is None: if resource_time is None:
resource_time = ifc_tool.run("resource.add_resource_time", resource=resource) resource_time = ifc_tool.run("resource.add_resource_time", resource=resource)
@@ -61,17 +76,21 @@ def enable_editing_resource_time(ifc_tool, resource_tool, resource):
resource_tool.load_resource_time_attributes(resource_time) resource_tool.load_resource_time_attributes(resource_time)
def edit_resource_time(ifc, resource_tool, resource_time): def edit_resource_time(
ifc: tool.Ifc, resource_tool: tool.Resource, resource_time: ifcopenshell.entity_instance
) -> None:
attributes = resource_tool.get_resource_time_attributes() attributes = resource_tool.get_resource_time_attributes()
ifc.run("resource.edit_resource_time", resource_time=resource_time, attributes=attributes) ifc.run("resource.edit_resource_time", resource_time=resource_time, attributes=attributes)
resource_tool.disable_editing_resource() resource_tool.disable_editing_resource()
def disable_editing_resource_time(resource_tool): def disable_editing_resource_time(resource_tool: tool.Resource) -> None:
resource_tool.disable_editing_resource() resource_tool.disable_editing_resource()
def calculate_resource_work(ifc, resource_tool, resource): def calculate_resource_work(
ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance
) -> None:
if resource_tool.get_task_assignments(resource): if resource_tool.get_task_assignments(resource):
ifc.run("resource.calculate_resource_work", resource=resource) ifc.run("resource.calculate_resource_work", resource=resource)
else: else:
@@ -81,92 +100,112 @@ def calculate_resource_work(ifc, resource_tool, resource):
resource_tool.load_resources() resource_tool.load_resources()
def enable_editing_resource_costs(resource_tool, resource): def enable_editing_resource_costs(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None:
resource_tool.enable_editing_resource_costs(resource) resource_tool.enable_editing_resource_costs(resource)
resource_tool.disable_editing_resource_cost_value() resource_tool.disable_editing_resource_cost_value()
def disable_editing_resource_cost_value(resource_tool): def disable_editing_resource_cost_value(resource_tool: tool.Resource) -> None:
resource_tool.disable_editing_resource_cost_value() resource_tool.disable_editing_resource_cost_value()
def enable_editing_resource_cost_value(resource_tool, cost_value): def enable_editing_resource_cost_value(resource_tool: tool.Resource, cost_value: ifcopenshell.entity_instance) -> None:
resource_tool.enable_editing_cost_value_attributes(cost_value) resource_tool.enable_editing_cost_value_attributes(cost_value)
resource_tool.load_cost_value_attributes(cost_value) resource_tool.load_cost_value_attributes(cost_value)
def enable_editing_resource_cost_value_formula(resource_tool, cost_value): def enable_editing_resource_cost_value_formula(
resource_tool: tool.Resource, cost_value: ifcopenshell.entity_instance
) -> None:
resource_tool.enable_editing_resource_cost_value_formula(cost_value) resource_tool.enable_editing_resource_cost_value_formula(cost_value)
def edit_resource_cost_value_formula(ifc, resource_tool, cost_value): def edit_resource_cost_value_formula(
ifc: tool.Ifc, resource_tool: tool.Resource, cost_value: ifcopenshell.entity_instance
) -> None:
formula = resource_tool.get_resource_cost_value_formula() formula = resource_tool.get_resource_cost_value_formula()
ifc.run("cost.edit_cost_value_formula", cost_value=cost_value, formula=formula) ifc.run("cost.edit_cost_value_formula", cost_value=cost_value, formula=formula)
resource_tool.disable_editing_resource_cost_value() resource_tool.disable_editing_resource_cost_value()
def edit_resource_cost_value(ifc, resource_tool, cost_value): def edit_resource_cost_value(
ifc: tool.Ifc, resource_tool: tool.Resource, cost_value: ifcopenshell.entity_instance
) -> None:
attributes = resource_tool.get_resource_cost_value_attributes() attributes = resource_tool.get_resource_cost_value_attributes()
ifc.run("cost.edit_cost_value", cost_value=cost_value, attributes=attributes) ifc.run("cost.edit_cost_value", cost_value=cost_value, attributes=attributes)
resource_tool.disable_editing_resource_cost_value() resource_tool.disable_editing_resource_cost_value()
def enable_editing_resource_base_quantity(resource_tool, resource): def enable_editing_resource_base_quantity(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None:
resource_tool.enable_editing_resource_base_quantity(resource) resource_tool.enable_editing_resource_base_quantity(resource)
def add_resource_quantity(ifc, ifc_class, resource): def add_resource_quantity(ifc: tool.Ifc, ifc_class: str, resource: ifcopenshell.entity_instance) -> None:
ifc.run("resource.add_resource_quantity", resource=resource, ifc_class=ifc_class) ifc.run("resource.add_resource_quantity", resource=resource, ifc_class=ifc_class)
def remove_resource_quantity(ifc, resource): def remove_resource_quantity(ifc: tool.Ifc, resource: ifcopenshell.entity_instance) -> None:
ifc.run("resource.remove_resource_quantity", resource=resource) ifc.run("resource.remove_resource_quantity", resource=resource)
def enable_editing_resource_quantity(resource_tool, resource_quantity=None): def enable_editing_resource_quantity(
resource_tool: tool.Resource, resource_quantity: ifcopenshell.entity_instance
) -> None:
resource_tool.enable_editing_resource_quantity(resource_quantity) resource_tool.enable_editing_resource_quantity(resource_quantity)
def disable_editing_resource_quantity(resource_tool): def disable_editing_resource_quantity(resource_tool: tool.Resource) -> None:
resource_tool.disable_editing_resource_quantity() resource_tool.disable_editing_resource_quantity()
def edit_resource_quantity(resource_tool, ifc, physical_quantity=None): def edit_resource_quantity(
resource_tool: tool.Resource, ifc: tool.Ifc, physical_quantity: ifcopenshell.entity_instance
) -> None:
attributes = resource_tool.get_resource_quantity_attributes() attributes = resource_tool.get_resource_quantity_attributes()
ifc.run("resource.edit_resource_quantity", physical_quantity=physical_quantity, attributes=attributes) ifc.run("resource.edit_resource_quantity", physical_quantity=physical_quantity, attributes=attributes)
resource_tool.disable_editing_resource_quantity() resource_tool.disable_editing_resource_quantity()
def import_resources(resource_tool, file_path): def import_resources(resource_tool: tool.Resource, file_path: str) -> None:
resource_tool.import_resources(file_path) resource_tool.import_resources(file_path)
resource_tool.load_resources() resource_tool.load_resources()
def expand_resource(resource_tool, resource): def expand_resource(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None:
resource_tool.expand_resource(resource) resource_tool.expand_resource(resource)
resource_tool.load_resources() resource_tool.load_resources()
def contract_resource(resource_tool, resource): def contract_resource(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None:
resource_tool.contract_resource(resource) resource_tool.contract_resource(resource)
resource_tool.load_resources() resource_tool.load_resources()
def assign_resource(ifc, spatial, resource=None, products=None): def assign_resource(
ifc: tool.Ifc,
spatial: tool.Spatial,
resource: ifcopenshell.entity_instance,
products: Optional[Iterable[ifcopenshell.entity_instance]] = None,
) -> None:
if not products: if not products:
products = spatial.get_selected_products() products = spatial.get_selected_products()
for product in products: for product in products:
rel = ifc.run("resource.assign_resource", relating_resource=resource, related_object=product) rel = ifc.run("resource.assign_resource", relating_resource=resource, related_object=product)
def unassign_resource(ifc, spatial, resource=None, products=None): def unassign_resource(
ifc: tool.Ifc,
spatial: tool.Spatial,
resource: ifcopenshell.entity_instance,
products: Optional[Iterable[ifcopenshell.entity_instance]] = None,
) -> None:
if not products: if not products:
products = spatial.get_selected_products() products = spatial.get_selected_products()
for product in products: for product in products:
ifc.run("resource.unassign_resource", relating_resource=resource, related_object=product) ifc.run("resource.unassign_resource", relating_resource=resource, related_object=product)
def edit_productivity_pset(ifc, resource_tool): def edit_productivity_pset(ifc: tool.Ifc, resource_tool: tool.Resource) -> None:
resource = resource_tool.get_highlighted_resource() resource = resource_tool.get_highlighted_resource()
if resource is None: if resource is None:
return return
@@ -178,7 +217,9 @@ def edit_productivity_pset(ifc, resource_tool):
ifc.run("pset.edit_pset", pset=pset, properties=resource_tool.get_productivity_attributes()) ifc.run("pset.edit_pset", pset=pset, properties=resource_tool.get_productivity_attributes())
def add_usage_constraint(ifc, resource_tool, resource=None, reference_path=None): def add_usage_constraint(
ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance, reference_path: str
) -> None:
metric = resource_tool.has_metric_constraint(resource, "Usage") metric = resource_tool.has_metric_constraint(resource, "Usage")
if metric: if metric:
return print("Must remove existing metric first") return print("Must remove existing metric first")
@@ -198,7 +239,9 @@ def add_usage_constraint(ifc, resource_tool, resource=None, reference_path=None)
ifc.run("constraint.assign_constraint", products=[resource], constraint=objective) ifc.run("constraint.assign_constraint", products=[resource], constraint=objective)
def remove_usage_constraint(ifc, resource_tool, resource, reference_path): def remove_usage_constraint(
ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance, reference_path: str
) -> None:
constraints = resource_tool.get_constraints(resource) constraints = resource_tool.get_constraints(resource)
for constraint in constraints: for constraint in constraints:
metrics = resource_tool.get_metrics(constraint) metrics = resource_tool.get_metrics(constraint)
@@ -210,10 +253,12 @@ def remove_usage_constraint(ifc, resource_tool, resource, reference_path):
ifc.run("constraint.remove_constraint", constraint=constraint) ifc.run("constraint.remove_constraint", constraint=constraint)
def go_to_resource(resource_tool, resource): def go_to_resource(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None:
resource_tool.go_to_resource(resource) resource_tool.go_to_resource(resource)
def calculate_resource_usage(ifc, resource_tool, resource): def calculate_resource_usage(
ifc: tool.Resource, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance
) -> None:
ifc.run("resource.calculate_resource_usage", resource=resource) ifc.run("resource.calculate_resource_usage", resource=resource)
resource_tool.load_resources() resource_tool.load_resources()
+2 -2
View File
@@ -7,7 +7,7 @@ import ifcopenshell.util.cost
import ifcopenshell.util.unit import ifcopenshell.util.unit
import blenderbim.bim.helper import blenderbim.bim.helper
import json import json
from typing import Optional, Any, Generator from typing import Optional, Any, Generator, Union
class Cost(blenderbim.core.tool.Cost): class Cost(blenderbim.core.tool.Cost):
@@ -149,7 +149,7 @@ class Cost(blenderbim.core.tool.Cost):
return blenderbim.bim.helper.export_attributes(props.cost_item_attributes) return blenderbim.bim.helper.export_attributes(props.cost_item_attributes)
@classmethod @classmethod
def get_active_cost_item(cls): def get_active_cost_item(cls) -> Union[ifcopenshell.entity_instance, None]:
props = bpy.context.scene.BIMCostProperties props = bpy.context.scene.BIMCostProperties
if not props.active_cost_item_id: if not props.active_cost_item_id:
return None return None
+48 -45
View File
@@ -33,10 +33,12 @@ import ifcopenshell.util.cost
import ifcopenshell.util.resource import ifcopenshell.util.resource
import blenderbim.bim.schema import blenderbim.bim.schema
import ifcopenshell.util.constraint import ifcopenshell.util.constraint
from typing import Any, Union
class Resource(blenderbim.core.tool.Resource): class Resource(blenderbim.core.tool.Resource):
@classmethod @classmethod
def load_resources(cls): def load_resources(cls) -> None:
def create_new_resource_li(resource, level_index): def create_new_resource_li(resource, level_index):
new = bpy.context.scene.BIMResourceTreeProperties.resources.add() new = bpy.context.scene.BIMResourceTreeProperties.resources.add()
new.ifc_definition_id = resource.id() new.ifc_definition_id = resource.id()
@@ -66,42 +68,44 @@ class Resource(blenderbim.core.tool.Resource):
props.is_editing = True props.is_editing = True
@classmethod @classmethod
def load_resource_properties(cls): def load_resource_properties(cls) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
tprops = bpy.context.scene.BIMResourceTreeProperties tprops = bpy.context.scene.BIMResourceTreeProperties
props.is_resource_update_enabled = False props.is_resource_update_enabled = False
for item in tprops.resources: for item in tprops.resources:
resource = tool.Ifc.get().by_id(item.ifc_definition_id) resource = tool.Ifc.get().by_id(item.ifc_definition_id)
item.name = resource.Name if resource.Name else "Unnamed" item.name = resource.Name if resource.Name else "Unnamed"
item.schedule_usage = resource.Usage.ScheduleUsage if (resource.Usage and resource.Usage.ScheduleUsage) else 0 item.schedule_usage = (
resource.Usage.ScheduleUsage if (resource.Usage and resource.Usage.ScheduleUsage) else 0
)
props.is_resource_update_enabled = True props.is_resource_update_enabled = True
@classmethod @classmethod
def disable_editing_resource(cls): def disable_editing_resource(cls) -> None:
bpy.context.scene.BIMResourceProperties.active_resource_id = 0 bpy.context.scene.BIMResourceProperties.active_resource_id = 0
bpy.context.scene.BIMResourceProperties.active_resource_time_id = 0 bpy.context.scene.BIMResourceProperties.active_resource_time_id = 0
@classmethod @classmethod
def disable_resource_editing_ui(cls): def disable_resource_editing_ui(cls) -> None:
bpy.context.scene.BIMResourceProperties.is_editing = False bpy.context.scene.BIMResourceProperties.is_editing = False
@classmethod @classmethod
def load_resource_attributes(cls, resource): def load_resource_attributes(cls, resource: ifcopenshell.entity_instance) -> None:
blenderbim.bim.helper.import_attributes2(resource, bpy.context.scene.BIMResourceProperties.resource_attributes) blenderbim.bim.helper.import_attributes2(resource, bpy.context.scene.BIMResourceProperties.resource_attributes)
@classmethod @classmethod
def enable_editing_resource(cls, resource): def enable_editing_resource(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
props.active_resource_id = resource.id() props.active_resource_id = resource.id()
props.resource_attributes.clear() props.resource_attributes.clear()
props.editing_resource_type = "ATTRIBUTES" props.editing_resource_type = "ATTRIBUTES"
@classmethod @classmethod
def get_resource_attributes(cls): def get_resource_attributes(cls) -> dict[str, Any]:
return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMResourceProperties.resource_attributes) return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMResourceProperties.resource_attributes)
@classmethod @classmethod
def enable_editing_resource_time(cls, resource): def enable_editing_resource_time(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
props.resource_time_attributes.clear() props.resource_time_attributes.clear()
props.active_resource_time_id = resource.Usage.id() props.active_resource_time_id = resource.Usage.id()
@@ -109,11 +113,11 @@ class Resource(blenderbim.core.tool.Resource):
props.editing_resource_type = "USAGE" props.editing_resource_type = "USAGE"
@classmethod @classmethod
def get_resource_time(cls, resource): def get_resource_time(cls, resource: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
return resource.Usage if resource.Usage else None return resource.Usage or None
@classmethod @classmethod
def load_resource_time_attributes(cls, resource_time): def load_resource_time_attributes(cls, resource_time: ifcopenshell.entity_instance) -> None:
def callback(name, prop, data): def callback(name, prop, data):
if prop.data_type == "string": if prop.data_type == "string":
if isinstance(data[name], datetime): if isinstance(data[name], datetime):
@@ -128,7 +132,7 @@ class Resource(blenderbim.core.tool.Resource):
) )
@classmethod @classmethod
def get_resource_time_attributes(cls): def get_resource_time_attributes(cls) -> dict[str, Any]:
def callback(attributes, prop): def callback(attributes, prop):
if "Start" in prop.name or "Finish" in prop.name or prop.name == "StatusTime": if "Start" in prop.name or "Finish" in prop.name or prop.name == "StatusTime":
if prop.is_null: if prop.is_null:
@@ -147,20 +151,19 @@ class Resource(blenderbim.core.tool.Resource):
return blenderbim.bim.helper.export_attributes(props.resource_time_attributes, callback) return blenderbim.bim.helper.export_attributes(props.resource_time_attributes, callback)
@classmethod @classmethod
def enable_editing_resource_costs(cls, resource): def enable_editing_resource_costs(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
props.active_resource_id = resource.id() props.active_resource_id = resource.id()
props.editing_resource_type = "COSTS" props.editing_resource_type = "COSTS"
resource
@classmethod @classmethod
def disable_editing_resource_cost_value(cls): def disable_editing_resource_cost_value(cls) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
props.active_cost_value_id = 0 props.active_cost_value_id = 0
props.cost_value_editing_type = "" props.cost_value_editing_type = ""
@classmethod @classmethod
def enable_editing_resource_cost_value_formula(cls, cost_value): def enable_editing_resource_cost_value_formula(cls, cost_value: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
props.cost_value_attributes.clear() props.cost_value_attributes.clear()
props.active_cost_value_id = cost_value.id() props.active_cost_value_id = cost_value.id()
@@ -168,7 +171,7 @@ class Resource(blenderbim.core.tool.Resource):
props.cost_value_formula = ifcopenshell.util.cost.serialise_cost_value(cost_value) if cost_value else "" props.cost_value_formula = ifcopenshell.util.cost.serialise_cost_value(cost_value) if cost_value else ""
@classmethod @classmethod
def load_cost_value_attributes(cls, cost_value): def load_cost_value_attributes(cls, cost_value: ifcopenshell.entity_instance):
def callback(name, prop, data): def callback(name, prop, data):
if name == "AppliedValue": if name == "AppliedValue":
# TODO: for now, only support simple IfcValues (which are effectively IfcMonetaryMeasure) # TODO: for now, only support simple IfcValues (which are effectively IfcMonetaryMeasure)
@@ -221,7 +224,7 @@ class Resource(blenderbim.core.tool.Resource):
blenderbim.bim.helper.import_attributes2(cost_value, props.cost_value_attributes, callback) blenderbim.bim.helper.import_attributes2(cost_value, props.cost_value_attributes, callback)
@classmethod @classmethod
def enable_editing_cost_value_attributes(cls, cost_value): def enable_editing_cost_value_attributes(cls, cost_value: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
props.cost_value_attributes.clear() props.cost_value_attributes.clear()
props.active_cost_value_id = cost_value.id() props.active_cost_value_id = cost_value.id()
@@ -232,7 +235,7 @@ class Resource(blenderbim.core.tool.Resource):
return bpy.context.scene.BIMResourceProperties.cost_value_formula return bpy.context.scene.BIMResourceProperties.cost_value_formula
@classmethod @classmethod
def get_resource_cost_value_attributes(cls): def get_resource_cost_value_attributes(cls) -> dict[str, Any]:
def callback(attributes, prop): def callback(attributes, prop):
if prop.name == "UnitBasisValue": if prop.name == "UnitBasisValue":
if prop.is_null: if prop.is_null:
@@ -257,28 +260,28 @@ class Resource(blenderbim.core.tool.Resource):
) )
@classmethod @classmethod
def enable_editing_resource_base_quantity(cls, resource): def enable_editing_resource_base_quantity(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
props.active_resource_id = resource.id() props.active_resource_id = resource.id()
props.editing_resource_type = "QUANTITY" props.editing_resource_type = "QUANTITY"
@classmethod @classmethod
def enable_editing_resource_quantity(cls, resource_quantity): def enable_editing_resource_quantity(cls, resource_quantity: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
props.quantity_attributes.clear() props.quantity_attributes.clear()
props.is_editing_quantity = True props.is_editing_quantity = True
blenderbim.bim.helper.import_attributes2(resource_quantity, props.quantity_attributes) blenderbim.bim.helper.import_attributes2(resource_quantity, props.quantity_attributes)
@classmethod @classmethod
def disable_editing_resource_quantity(cls): def disable_editing_resource_quantity(cls) -> None:
bpy.context.scene.BIMResourceProperties.is_editing_quantity = False bpy.context.scene.BIMResourceProperties.is_editing_quantity = False
@classmethod @classmethod
def get_resource_quantity_attributes(cls): def get_resource_quantity_attributes(cls) -> dict[str, Any]:
return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMResourceProperties.quantity_attributes) return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMResourceProperties.quantity_attributes)
@classmethod @classmethod
def expand_resource(cls, resource): def expand_resource(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
contracted_resources = json.loads(props.contracted_resources) contracted_resources = json.loads(props.contracted_resources)
if not resource.id() in contracted_resources: if not resource.id() in contracted_resources:
@@ -287,14 +290,14 @@ class Resource(blenderbim.core.tool.Resource):
props.contracted_resources = json.dumps(contracted_resources) props.contracted_resources = json.dumps(contracted_resources)
@classmethod @classmethod
def contract_resource(cls, resource): def contract_resource(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
contracted_resources = json.loads(props.contracted_resources) contracted_resources = json.loads(props.contracted_resources)
contracted_resources.append(resource.id()) contracted_resources.append(resource.id())
props.contracted_resources = json.dumps(contracted_resources) props.contracted_resources = json.dumps(contracted_resources)
@classmethod @classmethod
def import_resources(cls, file_path): def import_resources(cls, file_path: str) -> None:
from ifc4d.csv2ifc import Csv2Ifc from ifc4d.csv2ifc import Csv2Ifc
start = time.time() start = time.time()
@@ -305,7 +308,7 @@ class Resource(blenderbim.core.tool.Resource):
print("Importing Resources CSV finished in {:.2f} seconds".format(time.time() - start)) print("Importing Resources CSV finished in {:.2f} seconds".format(time.time() - start))
@classmethod @classmethod
def get_highlighted_resource(cls): def get_highlighted_resource(cls) -> Union[ifcopenshell.entity_instance, None]:
resources = len(bpy.context.scene.BIMResourceTreeProperties.resources) resources = len(bpy.context.scene.BIMResourceTreeProperties.resources)
if resources and resources > bpy.context.scene.BIMResourceProperties.active_resource_index: if resources and resources > bpy.context.scene.BIMResourceProperties.active_resource_index:
return tool.Ifc.get().by_id( return tool.Ifc.get().by_id(
@@ -315,7 +318,7 @@ class Resource(blenderbim.core.tool.Resource):
) )
@classmethod @classmethod
def clear_productivity_data(cls, props): def clear_productivity_data(cls, props: bpy.types.PropertyGroup) -> None:
for duration_prop in props.quantity_consumed or []: for duration_prop in props.quantity_consumed or []:
if duration_prop.name == "BaseQuantityConsumed": if duration_prop.name == "BaseQuantityConsumed":
duration_prop.years = 0 duration_prop.years = 0
@@ -328,7 +331,7 @@ class Resource(blenderbim.core.tool.Resource):
props.quantity_produced_name = "" props.quantity_produced_name = ""
@classmethod @classmethod
def load_productivity_data(cls): def load_productivity_data(cls) -> None:
duration_props = None duration_props = None
for collection_prop in bpy.context.scene.BIMResourceProductivity.quantity_consumed: for collection_prop in bpy.context.scene.BIMResourceProductivity.quantity_consumed:
duration_props = collection_prop if collection_prop.name == "BaseQuantityConsumed" else None duration_props = collection_prop if collection_prop.name == "BaseQuantityConsumed" else None
@@ -358,7 +361,7 @@ class Resource(blenderbim.core.tool.Resource):
duration_props.seconds = durations_attributes["seconds"] duration_props.seconds = durations_attributes["seconds"]
@classmethod @classmethod
def get_productivity_attributes(cls): def get_productivity_attributes(cls) -> dict[str, Any]:
props = bpy.context.scene.BIMResourceProductivity props = bpy.context.scene.BIMResourceProductivity
productivity = {} productivity = {}
if props.quantity_consumed: if props.quantity_consumed:
@@ -370,7 +373,9 @@ class Resource(blenderbim.core.tool.Resource):
return productivity return productivity
@classmethod @classmethod
def get_productivity(cls, resource, should_inherit=False): def get_productivity(
cls, resource: ifcopenshell.entity_instance, should_inherit: bool = False
) -> ifcopenshell.util.resource.PRODUCTIVITY_PSET_DATA:
return ifcopenshell.util.resource.get_productivity(resource, should_inherit=should_inherit) return ifcopenshell.util.resource.get_productivity(resource, should_inherit=should_inherit)
@classmethod @classmethod
@@ -380,29 +385,29 @@ class Resource(blenderbim.core.tool.Resource):
return return
return tool.Ifc.run( return tool.Ifc.run(
"pset.edit_pset", "pset.edit_pset",
pset= tool.Ifc.get().by_id(productivity["id"]), pset=tool.Ifc.get().by_id(productivity["id"]),
properties=attributes, properties=attributes,
) )
@classmethod @classmethod
def get_constraints(cls, resource): def get_constraints(cls, resource: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
return ifcopenshell.util.constraint.get_constraints(product=resource) return ifcopenshell.util.constraint.get_constraints(product=resource)
@classmethod @classmethod
def get_metrics(cls, constraint): def get_metrics(cls, constraint: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
return ifcopenshell.util.constraint.get_metrics(constraint) return ifcopenshell.util.constraint.get_metrics(constraint)
@classmethod @classmethod
def get_metric_reference(cls, metric, is_deep=True): def get_metric_reference(cls, metric: ifcopenshell.entity_instance, is_deep: bool = True):
return ifcopenshell.util.constraint.get_metric_reference(metric, is_deep=is_deep) return ifcopenshell.util.constraint.get_metric_reference(metric, is_deep=is_deep)
@classmethod @classmethod
def has_metric_constraint(cls, resource, attribute): def has_metric_constraint(cls, resource: ifcopenshell.entity_instance, attribute):
metrics = ifcopenshell.util.constraint.get_metric_constraints(resource, attribute) metrics = ifcopenshell.util.constraint.get_metric_constraints(resource, attribute)
return True if metrics else False return True if metrics else False
@classmethod @classmethod
def run_edit_resource_time(cls, resource, attributes): def run_edit_resource_time(cls, resource: ifcopenshell.entity_instance, attributes: dict[str, Any]) -> None:
if not resource.Usage: if not resource.Usage:
tool.Ifc.run( tool.Ifc.run(
"resource.add_resource_time", "resource.add_resource_time",
@@ -411,7 +416,7 @@ class Resource(blenderbim.core.tool.Resource):
tool.Ifc.run("resource.edit_resource_time", resource_time=resource.Usage, attributes=attributes) tool.Ifc.run("resource.edit_resource_time", resource_time=resource.Usage, attributes=attributes)
@classmethod @classmethod
def go_to_resource(cls, resource): def go_to_resource(cls, resource: ifcopenshell.entity_instance) -> None:
def get_ancestors_ids(resource): def get_ancestors_ids(resource):
ids = [] ids = []
for rel in resource.Nests or []: for rel in resource.Nests or []:
@@ -427,24 +432,22 @@ class Resource(blenderbim.core.tool.Resource):
bpy.context.scene.BIMResourceProperties.contracted_resources = json.dumps(contracted_resources) bpy.context.scene.BIMResourceProperties.contracted_resources = json.dumps(contracted_resources)
cls.load_resources() cls.load_resources()
resource_props = bpy.context.scene.BIMResourceTreeProperties resource_props = bpy.context.scene.BIMResourceTreeProperties
expanded_resources = [item.ifc_definition_id for item in resource_props.resources] expanded_resources = [item.ifc_definition_id for item in resource_props.resources]
bpy.context.scene.BIMResourceProperties.active_resource_index = expanded_resources.index(resource.id()) bpy.context.scene.BIMResourceProperties.active_resource_index = expanded_resources.index(resource.id())
@classmethod @classmethod
def run_calculate_resource_usage(cls, resource): def run_calculate_resource_usage(cls, resource: ifcopenshell.entity_instance) -> None:
tool.Ifc.run("resource.calculate_resource_usage", resource=resource) tool.Ifc.run("resource.calculate_resource_usage", resource=resource)
@classmethod @classmethod
def get_task_assignments(cls, resource): def get_task_assignments(cls, resource: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
return ifcopenshell.util.resource.get_task_assignments(resource) return ifcopenshell.util.resource.get_task_assignments(resource)
@classmethod @classmethod
def get_nested_resources(cls, resource): def get_nested_resources(cls, resource: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
return ifcopenshell.util.resource.get_nested_resources(resource) return ifcopenshell.util.resource.get_nested_resources(resource)
@classmethod @classmethod
def is_attribute_locked(cls, resource, attribute): def is_attribute_locked(cls, resource: ifcopenshell.entity_instance, attribute) -> bool:
return ifcopenshell.util.constraint.is_attribute_locked(resource, attribute) return ifcopenshell.util.constraint.is_attribute_locked(resource, attribute)
+15 -3
View File
@@ -29,7 +29,7 @@ import ifcopenshell.util.selector
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.schema import ifcopenshell.util.schema
from statistics import mean from statistics import mean
from typing import Optional, Union from typing import Optional, Union, Literal
try: try:
from odf.namespaces import OFFICENS from odf.namespaces import OFFICENS
@@ -53,6 +53,14 @@ except:
pass # No Pandas support pass # No Pandas support
FILE_FORMAT = Literal[
"csv",
"ods",
"xlsx",
"pd",
]
class IfcCsv: class IfcCsv:
def __init__(self): def __init__(self):
self.headers = [] self.headers = []
@@ -66,7 +74,7 @@ class IfcCsv:
attributes, attributes,
headers=None, headers=None,
output=None, output=None,
format=None, format: FILE_FORMAT = None,
should_preserve_existing: bool = False, should_preserve_existing: bool = False,
include_global_id: bool = True, include_global_id: bool = True,
delimiter: str = ",", delimiter: str = ",",
@@ -392,7 +400,11 @@ class IfcCsv:
bool_true: str = "YES", bool_true: str = "YES",
bool_false: str = "NO", bool_false: str = "NO",
) -> None: ) -> None:
ext = table.split(".")[-1].lower() """
Args:
table: filepath to the table.
"""
ext: FILE_FORMAT = table.split(".")[-1].lower()
if ext == "csv": if ext == "csv":
self.import_csv(ifc_file, table, attributes, delimiter, null, empty, bool_true, bool_false) self.import_csv(ifc_file, table, attributes, delimiter, null, empty, bool_true, bool_false)
@@ -17,6 +17,7 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>. # along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell import ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.cost import ifcopenshell.util.cost
import ifcopenshell.util.unit import ifcopenshell.util.unit
import ifcopenshell.util.element import ifcopenshell.util.element
@@ -16,18 +16,24 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>. # along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell.util.cost
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.date import ifcopenshell.util.date
from typing import Union, Any
def get_productivity(resource, should_inherit=True): PRODUCTIVITY_PSET_DATA = Union[dict[str, Any], None]
def get_productivity(resource: ifcopenshell.entity_instance, should_inherit: bool = True) -> PRODUCTIVITY_PSET_DATA:
productivity = ifcopenshell.util.element.get_psets(resource).get("EPset_Productivity", None) productivity = ifcopenshell.util.element.get_psets(resource).get("EPset_Productivity", None)
if should_inherit and not productivity: if should_inherit and not productivity:
#Note: This is not part of the Schema - but it makes sense to inherit from parent # Note: This is not part of the Schema - but it makes sense to inherit from parent
productivity = get_parent_productivity(resource) productivity = get_parent_productivity(resource)
return productivity return productivity
def get_parent_productivity(resource):
def get_parent_productivity(resource: ifcopenshell.entity_instance) -> PRODUCTIVITY_PSET_DATA:
if not resource.Nests: if not resource.Nests:
return return
else: else:
@@ -36,34 +42,34 @@ def get_parent_productivity(resource):
return productivity return productivity
def get_unit_consumed(productivity): def get_unit_consumed(productivity: PRODUCTIVITY_PSET_DATA) -> Union[Any, None]:
duration = productivity.get("BaseQuantityConsumed", None) duration = productivity.get("BaseQuantityConsumed", None)
if not duration: if not duration:
return return
return ifcopenshell.util.date.ifc2datetime(duration) return ifcopenshell.util.date.ifc2datetime(duration)
def get_quantity_produced(productivity): def get_quantity_produced(productivity: PRODUCTIVITY_PSET_DATA) -> float:
if not productivity: if not productivity:
return 0 return 0.0
return productivity.get("BaseQuantityProducedValue", 0) return productivity.get("BaseQuantityProducedValue", 0.0)
def get_quantity_produced_name(productivity): def get_quantity_produced_name(productivity: PRODUCTIVITY_PSET_DATA):
if not productivity: if not productivity:
return "" return ""
return productivity.get("BaseQuantityProducedName", "") return productivity.get("BaseQuantityProducedName", "")
def get_total_quantity_produced(resource, quantity_name_in_process): def get_total_quantity_produced(resource: ifcopenshell.entity_instance, quantity_name_in_process: str) -> float:
def get_product_quantity(product, quantity_name): def get_product_quantity(product: ifcopenshell.entity_instance, quantity_name: str):
psets = ifcopenshell.util.element.get_psets(product) psets = ifcopenshell.util.element.get_psets(product)
for pset in psets.values(): for pset in psets.values():
for name, value in pset.items(): for name, value in pset.items():
if name == quantity_name: if name == quantity_name:
return float(value) return float(value)
total = 0 total = 0.0
products = get_parametric_resource_products(resource) products = get_parametric_resource_products(resource)
if quantity_name_in_process == "Count": if quantity_name_in_process == "Count":
total = len(products) total = len(products)
@@ -73,7 +79,7 @@ def get_total_quantity_produced(resource, quantity_name_in_process):
return total return total
def get_parametric_resource_products(resource): def get_parametric_resource_products(resource: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
products = [] products = []
for rel in resource.HasAssignments or []: for rel in resource.HasAssignments or []:
if not rel.is_a("IfcRelAssignsToProcess"): if not rel.is_a("IfcRelAssignsToProcess"):
@@ -84,14 +90,15 @@ def get_parametric_resource_products(resource):
products.append(rel2.RelatingProduct) products.append(rel2.RelatingProduct)
return products return products
def get_task_assignments(resource):
def get_task_assignments(resource: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
for rel in resource.HasAssignments or []: for rel in resource.HasAssignments or []:
if not rel.is_a("IfcRelAssignsToProcess"): if not rel.is_a("IfcRelAssignsToProcess"):
continue continue
return rel.RelatingProcess return rel.RelatingProcess
def get_resource_required_work(resource): def get_resource_required_work(resource: ifcopenshell.entity_instance) -> Union[str, None]:
productivity = get_productivity(resource) productivity = get_productivity(resource)
if productivity: if productivity:
quantity_produced = get_quantity_produced(productivity) quantity_produced = get_quantity_produced(productivity)
@@ -114,33 +121,38 @@ def get_resource_required_work(resource):
return iso_string return iso_string
def get_nested_resources(resource): def get_nested_resources(resource: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
return [object for rel in resource.IsNestedBy or [] for object in rel.RelatedObjects] return [object for rel in resource.IsNestedBy or [] for object in rel.RelatedObjects]
def get_cost(resource): def get_cost(resource: ifcopenshell.entity_instance) -> tuple[float, Union[str, None]]:
base_costs = getattr(resource, "BaseCosts", []) base_costs = getattr(resource, "BaseCosts", [])
costs = [ costs = (
ifcopenshell.util.cost.calculate_applied_value(resource, cost_value) [ifcopenshell.util.cost.calculate_applied_value(resource, cost_value) for cost_value in base_costs]
for cost_value in base_costs if base_costs
] if base_costs else [] else []
)
cost = sum(costs) cost = sum(costs)
unit_basis = next( unit_basis = (
(cost_value.UnitBasis for cost_value in base_costs if cost_value.UnitBasis), next((cost_value.UnitBasis for cost_value in base_costs if cost_value.UnitBasis), None) if base_costs else None
None )
) if base_costs else None unit = (
unit = unit_basis.UnitComponent.Name if unit_basis and unit_basis.UnitComponent.is_a("IfcConversionBasedUnit") else None unit_basis.UnitComponent.Name
if unit_basis and unit_basis.UnitComponent.is_a("IfcConversionBasedUnit")
else None
)
return cost, unit return cost, unit
def get_quantity(resource):
total = 0 def get_quantity(resource: ifcopenshell.entity_instance) -> float:
if resource.BaseQuantity: if resource.BaseQuantity:
return resource.BaseQuantity[3] return resource.BaseQuantity[3]
if resource.Usage and resource.Usage.ScheduleWork: if resource.Usage and resource.Usage.ScheduleWork:
duration = ifcopenshell.util.date.ifc2datetime(resource.Usage.ScheduleWork) duration = ifcopenshell.util.date.ifc2datetime(resource.Usage.ScheduleWork)
return duration.total_seconds() / 3600 return duration.total_seconds() / 3600
def get_parent_cost(resource):
def get_parent_cost(resource: ifcopenshell.entity_instance) -> Union[None, tuple[float, Union[str, None]]]:
if not resource.Nests: if not resource.Nests:
return return
else: else: