BBIM: refactor gantt generation operator

This commit is contained in:
Sigma Dimensions
2023-01-20 11:26:32 +01:00
parent 893fd50b85
commit caf9034839
4 changed files with 81 additions and 57 deletions
@@ -464,62 +464,9 @@ class GenerateGanttChart(bpy.types.Operator):
work_schedule: bpy.props.IntProperty() work_schedule: bpy.props.IntProperty()
def execute(self, context): def execute(self, context):
self.file = IfcStore.get_file() core.generate_gantt_chart(tool.Sequence, work_schedule=tool.Ifc.get().by_id(self.work_schedule))
self.json = []
self.sequence_type_map = {
None: "FS",
"START_START": "SS",
"START_FINISH": "SF",
"FINISH_START": "FS",
"FINISH_FINISH": "FF",
"USERDEFINED": "FS",
"NOTDEFINED": "FS",
}
Data.load(self.file)
for task_id in Data.work_schedules[self.work_schedule]["RelatedObjects"]:
self.create_new_task_json(task_id)
with open(os.path.join(context.scene.BIMProperties.data_dir, "gantt", "index.html"), "w") as f:
with open(os.path.join(context.scene.BIMProperties.data_dir, "gantt", "index.mustache"), "r") as t:
f.write(pystache.render(t.read(), {"json_data": json.dumps(self.json)}))
webbrowser.open("file://" + os.path.join(context.scene.BIMProperties.data_dir, "gantt", "index.html"))
return {"FINISHED"} return {"FINISHED"}
def create_new_task_json(self, task_id):
task = self.file.by_id(task_id)
data = {
"pID": task.id(),
"pName": task.Name,
"pCaption": task.Name,
"pStart": task.TaskTime.ScheduleStart if task.TaskTime else "",
"pEnd": task.TaskTime.ScheduleFinish if task.TaskTime else "",
"pPlanStart": task.TaskTime.ScheduleStart if task.TaskTime else "",
"pPlanEnd": task.TaskTime.ScheduleFinish if task.TaskTime else "",
"pMile": 1 if task.IsMilestone else 0,
"pComp": 0,
"pGroup": 1 if task.IsNestedBy else 0,
"pParent": task.Nests[0].RelatingObject.id() if task.Nests else 0,
"pOpen": 1,
"pCost": 1,
"ifcduration": task.TaskTime.ScheduleDuration if task.TaskTime else "",
}
if task.TaskTime and task.TaskTime.IsCritical:
data["pClass"] = "gtaskred"
elif data["pGroup"]:
data["pClass"] = "ggroupblack"
elif data["pMile"]:
data["pClass"] = "gmilestone"
else:
data["pClass"] = "gtaskblue"
data["pDepend"] = ",".join(
[
"{}{}".format(rel.RelatingProcess.id(), self.sequence_type_map[rel.SequenceType])
for rel in task.IsSuccessorFrom or []
]
)
self.json.append(data)
for task_id in Data.tasks[task_id]["RelatedObjects"]:
self.create_new_task_json(task_id)
class AddWorkCalendar(bpy.types.Operator, tool.Ifc.Operator): class AddWorkCalendar(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_work_calendar" bl_idname = "bim.add_work_calendar"
@@ -1097,7 +1044,7 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
has_start, has_finish = bpy.context.scene.BIMWorkScheduleProperties.visualisation_start, bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish has_start, has_finish = bpy.context.scene.BIMWorkScheduleProperties.visualisation_start, bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish
return bool(has_start and has_finish) return bool(has_start and has_finish) and not "-" in (has_start, has_finish)
def execute(self, context): def execute(self, context):
core.visualise_work_schedule_date_range(tool.Sequence, work_schedule=tool.Ifc.get().by_id(self.work_schedule)) core.visualise_work_schedule_date_range(tool.Sequence, work_schedule=tool.Ifc.get().by_id(self.work_schedule))
@@ -1364,3 +1311,13 @@ class DisableEditingTaskAnimationColors(bpy.types.Operator):
def execute(self, context): def execute(self, context):
core.disable_editing_task_animation_colors(tool.Sequence) core.disable_editing_task_animation_colors(tool.Sequence)
return {"FINISHED"} return {"FINISHED"}
class CopyTask(bpy.types.Operator):
bl_idname = "bim.copy_task"
bl_label = "Copy Task"
bl_options = {"REGISTER", "UNDO"}
task: bpy.props.IntProperty()
def execute(self, context):
core.copy_task(tool.Ifc, tool.Sequence, task=tool.Ifc.get().by_id(self.task))
return {"FINISHED"}
+5 -1
View File
@@ -500,4 +500,8 @@ def visualise_work_schedule_date_range(sequence, work_schedule=None):
product_frames = sequence.get_animation_product_frames(work_schedule, settings) product_frames = sequence.get_animation_product_frames(work_schedule, settings)
sequence.load_task_animation_colors() sequence.load_task_animation_colors()
sequence.animate_objects(settings, product_frames) sequence.animate_objects(settings, product_frames)
sequence.add_text_animation_handler(settings) sequence.add_text_animation_handler(settings)
def generate_gantt_chart(sequence, work_schedule):
json = sequence.create_tasks_json(work_schedule)
sequence.generate_gantt_browser_chart(json)
+1 -1
View File
@@ -501,7 +501,7 @@ class Sequence:
def expand_task(cls, task): pass def expand_task(cls, task): pass
def find_related_output_tasks(cls, column): pass def find_related_output_tasks(cls, column): pass
def get_active_task(cls): pass def get_active_task(cls): pass
def get_active_work_schedule_id(cls): pass def get_active_work_schedule(cls): pass
def get_checked_tasks(cls): pass def get_checked_tasks(cls): pass
def get_direct_nested_tasks(cls, task):pass def get_direct_nested_tasks(cls, task):pass
def get_direct_task_outputs(cls, task): pass def get_direct_task_outputs(cls, task): pass
@@ -18,10 +18,13 @@
import bpy import bpy
import re import re
import os
import isodate import isodate
import ifcopenshell import ifcopenshell
import ifcopenshell.util.sequence import ifcopenshell.util.sequence
import ifcopenshell.util.date import ifcopenshell.util.date
import ifcopenshell.util.element
import ifcopenshell.util.unit
import json import json
import blenderbim.core.tool import blenderbim.core.tool
import blenderbim.tool as tool import blenderbim.tool as tool
@@ -30,6 +33,8 @@ import blenderbim.bim.module.sequence.helper as helper
from dateutil import parser from dateutil import parser
from datetime import datetime from datetime import datetime
import mathutils import mathutils
import pystache
import webbrowser
class Sequence(blenderbim.core.tool.Sequence): class Sequence(blenderbim.core.tool.Sequence):
@@ -1271,3 +1276,61 @@ class Sequence(blenderbim.core.tool.Sequence):
obj.data.BIMDateTextProperties.start = bpy.context.scene.BIMWorkScheduleProperties.visualisation_start obj.data.BIMDateTextProperties.start = bpy.context.scene.BIMWorkScheduleProperties.visualisation_start
obj.data.BIMDateTextProperties.finish = bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish obj.data.BIMDateTextProperties.finish = bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish
append_handler(animate_text_handler) append_handler(animate_text_handler)
@classmethod
def create_tasks_json(cls, work_schedule=None):
sequence_type_map = {
None: "FS",
"START_START": "SS",
"START_FINISH": "SF",
"FINISH_START": "FS",
"FINISH_FINISH": "FF",
"USERDEFINED": "FS",
"NOTDEFINED": "FS",
}
tasks_json = []
for task in ifcopenshell.util.sequence.get_root_tasks(work_schedule):
cls.create_new_task_json(task, tasks_json, sequence_type_map)
return tasks_json
@classmethod
def create_new_task_json(cls, task, json, type_map=None):
task_time = task.TaskTime
data = {
"pID": task.id(),
"pName": task.Name,
"pCaption": task.Name,
"pStart": task_time.ScheduleStart if task_time else "",
"pEnd": task_time.ScheduleFinish if task_time else "",
"pPlanStart": task_time.ScheduleStart if task_time else "",
"pPlanEnd": task_time.ScheduleFinish if task_time else "",
"pMile": 1 if task.IsMilestone else 0,
"pComp": 0,
"pGroup": 1 if task.IsNestedBy else 0,
"pParent": task.Nests[0].RelatingObject.id() if task.Nests else 0,
"pOpen": 1,
"pCost": 1,
"ifcduration": task_time.ScheduleDuration if task_time else "",
}
if task_time and task_time.IsCritical:
data["pClass"] = "gtaskred"
elif data["pGroup"]:
data["pClass"] = "ggroupblack"
elif data["pMile"]:
data["pClass"] = "gmilestone"
else:
data["pClass"] = "gtaskblue"
data["pDepend"] = ",".join([f"{rel.RelatingProcess.id()}{type_map[rel.SequenceType]}" for rel in task.IsSuccessorFrom or []])
json.append(data)
for nested_task in ifcopenshell.util.sequence.get_nested_tasks(task):
cls.create_new_task_json(nested_task, json, type_map)
@classmethod
def generate_gantt_browser_chart(cls, task_json):
with open(os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.html"), "w") as f:
with open(os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.mustache"), "r") as t:
f.write(pystache.render(t.read(), {"json_data": json.dumps(task_json)}))
webbrowser.open("file://" + os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.html"))