mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 02:31:09 +00:00
You can now store productivity rates and calculate resource work parametrically based on productivity
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
ISO-10303-21;
|
||||||
|
HEADER;
|
||||||
|
FILE_DESCRIPTION((),'2;1');
|
||||||
|
FILE_NAME('EPset_Productivity.ifc','2020-01-01T00:00:00',(),(),'EPset_Productivity','EPset_Productivity',$);
|
||||||
|
FILE_SCHEMA(('IFC4'));
|
||||||
|
ENDSEC;
|
||||||
|
DATA;
|
||||||
|
#1=IFCPROPERTYSETTEMPLATE('24XxTA2ED4o83uiZBG59D_',$,'EPset_Productivity','',.PSET_TYPEDRIVENOVERRIDE.,'IfcConstructionEquipmentResource,IfcLaborResource',(#2,#3,#4));
|
||||||
|
#2=IFCSIMPLEPROPERTYTEMPLATE('3mL27FQ4X4MQn5fiGqIt8x',$,'BaseQuantityConsumed','',.P_SINGLEVALUE.,'IfcDuration',$,$,$,$,$,.READWRITE.);
|
||||||
|
#3=IFCSIMPLEPROPERTYTEMPLATE('1DdJt5_Ar2mR4UDpO$98Ws',$,'BaseQuantityProducedName','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||||
|
#4=IFCSIMPLEPROPERTYTEMPLATE('2OZPZ$Onb2gOvW20q7gacH',$,'BaseQuantityProducedValue','',.P_SINGLEVALUE.,'IfcReal',$,$,$,$,$,.READWRITE.);
|
||||||
|
ENDSEC;
|
||||||
|
END-ISO-10303-21;
|
||||||
@@ -36,6 +36,7 @@ classes = (
|
|||||||
operator.EnableEditingResourceTime,
|
operator.EnableEditingResourceTime,
|
||||||
operator.EditResourceTime,
|
operator.EditResourceTime,
|
||||||
operator.DisableEditingResourceTime,
|
operator.DisableEditingResourceTime,
|
||||||
|
operator.CalculateResourceWork,
|
||||||
prop.Resource,
|
prop.Resource,
|
||||||
prop.BIMResourceProperties,
|
prop.BIMResourceProperties,
|
||||||
prop.BIMResourceTreeProperties,
|
prop.BIMResourceTreeProperties,
|
||||||
|
|||||||
@@ -371,3 +371,17 @@ class EditResourceTime(bpy.types.Operator):
|
|||||||
return True
|
return True
|
||||||
attributes[prop.name] = helper.parse_duration(prop.string_value)
|
attributes[prop.name] = helper.parse_duration(prop.string_value)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class CalculateResourceWork(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.calculate_resource_work"
|
||||||
|
bl_label = "Calculate Resource Work"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
resource: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
ifcopenshell.api.run("resource.calculate_resource_work", self.file, resource=self.file.by_id(self.resource))
|
||||||
|
Data.load(self.file)
|
||||||
|
bpy.ops.bim.load_resources()
|
||||||
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -75,13 +75,21 @@ class BIM_PT_resources(Panel):
|
|||||||
and Data.resources[self.tprops.resources[self.props.active_resource_index].ifc_definition_id]["type"]
|
and Data.resources[self.tprops.resources[self.props.active_resource_index].ifc_definition_id]["type"]
|
||||||
!= "IfcSubContractResource"
|
!= "IfcSubContractResource"
|
||||||
):
|
):
|
||||||
|
ifc_definition_id = self.tprops.resources[self.props.active_resource_index].ifc_definition_id
|
||||||
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
for ifc_class, icon in icon_map.items():
|
for ifc_class, icon in icon_map.items():
|
||||||
label = ifc_class.replace("Ifc", "").replace("Construction", "").replace("Resource", "")
|
label = ifc_class.replace("Ifc", "").replace("Construction", "").replace("Resource", "")
|
||||||
op = row.operator("bim.add_resource", text=label, icon=icon)
|
op = row.operator("bim.add_resource", text=label, icon=icon)
|
||||||
op.resource = self.tprops.resources[self.props.active_resource_index].ifc_definition_id
|
op.resource = ifc_definition_id
|
||||||
op.ifc_class = ifc_class
|
op.ifc_class = ifc_class
|
||||||
|
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.alignment = "RIGHT"
|
||||||
|
|
||||||
|
op = row.operator("bim.calculate_resource_work", text="", icon="TEMP")
|
||||||
|
op.resource = ifc_definition_id
|
||||||
|
|
||||||
self.layout.template_list(
|
self.layout.template_list(
|
||||||
"BIM_UL_resources",
|
"BIM_UL_resources",
|
||||||
"",
|
"",
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ classes = (
|
|||||||
operator.LoadTaskInputs,
|
operator.LoadTaskInputs,
|
||||||
operator.LoadTaskResources,
|
operator.LoadTaskResources,
|
||||||
operator.LoadTaskOutputs,
|
operator.LoadTaskOutputs,
|
||||||
operator.DeriveTaskDuration,
|
operator.CalculateTaskDuration,
|
||||||
prop.WorkPlan,
|
prop.WorkPlan,
|
||||||
prop.BIMWorkPlanProperties,
|
prop.BIMWorkPlanProperties,
|
||||||
prop.Task,
|
prop.Task,
|
||||||
|
|||||||
@@ -797,6 +797,7 @@ class AssignProduct(bpy.types.Operator):
|
|||||||
related_object=self.file.by_id(self.task),
|
related_object=self.file.by_id(self.task),
|
||||||
)
|
)
|
||||||
Data.load(self.file)
|
Data.load(self.file)
|
||||||
|
bpy.ops.bim.load_task_outputs()
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -825,6 +826,7 @@ class UnassignProduct(bpy.types.Operator):
|
|||||||
related_object=self.file.by_id(self.task),
|
related_object=self.file.by_id(self.task),
|
||||||
)
|
)
|
||||||
Data.load(self.file)
|
Data.load(self.file)
|
||||||
|
bpy.ops.bim.load_task_outputs()
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -2106,9 +2108,9 @@ class LoadTaskOutputs(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class DeriveTaskDuration(bpy.types.Operator):
|
class CalculateTaskDuration(bpy.types.Operator):
|
||||||
bl_idname = "bim.derive_task_duration"
|
bl_idname = "bim.calculate_task_duration"
|
||||||
bl_label = "Derive Task Duration"
|
bl_label = "Calculate Task Duration"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
task: bpy.props.IntProperty()
|
task: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ class BIM_PT_task_icom(Panel):
|
|||||||
row2 = col.row(align=True)
|
row2 = col.row(align=True)
|
||||||
row2.label(text="Resources")
|
row2.label(text="Resources")
|
||||||
|
|
||||||
op = row2.operator("bim.derive_task_duration", text="", icon="TIME")
|
op = row2.operator("bim.calculate_task_duration", text="", icon="TEMP")
|
||||||
op.task = task.ifc_definition_id
|
op.task = task.ifc_definition_id
|
||||||
|
|
||||||
total_resources = len(context.scene.BIMResourceTreeProperties.resources)
|
total_resources = len(context.scene.BIMResourceTreeProperties.resources)
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
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
|
||||||
|
seconds_worked = total_produced / unit_produced * unit_consumed
|
||||||
|
self.set_schedule_work(seconds_worked)
|
||||||
|
|
||||||
|
def get_unit_consumed(self):
|
||||||
|
duration = self.productivity.get("BaseQuantityConsumed", None)
|
||||||
|
if not duration:
|
||||||
|
return
|
||||||
|
return ifcopenshell.util.date.ifc2datetime(duration).seconds
|
||||||
|
|
||||||
|
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
|
||||||
|
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:
|
||||||
|
try:
|
||||||
|
total += float(value)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return total
|
||||||
|
|
||||||
|
def set_schedule_work(self, seconds):
|
||||||
|
if not self.settings["resource"].Usage:
|
||||||
|
ifcopenshell.api.run("resource.add_resource_time", self.file, resource=self.settings["resource"])
|
||||||
|
self.settings["resource"].Usage.ScheduleWork = f"PT{seconds / 60 / 60}H"
|
||||||
Reference in New Issue
Block a user