Skip to content
This repository was archived by the owner on Nov 24, 2024. It is now read-only.

Commit ee0f7f1

Browse files
committed
You can now import an IFC work schedule from a P6 XML export
1 parent dca2e58 commit ee0f7f1

4 files changed

Lines changed: 143 additions & 129 deletions

File tree

src/blenderbim/blenderbim/bim/module/sequence/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
operator.AssignProduct,
4242
operator.UnassignProduct,
4343
operator.GenerateGanttChart,
44+
operator.ImportP6,
4445
prop.WorkPlan,
4546
prop.BIMWorkPlanProperties,
4647
prop.Task,
@@ -56,13 +57,19 @@
5657
)
5758

5859

60+
def menu_func_import(self, context):
61+
self.layout.operator(operator.ImportP6.bl_idname, text="P6 (.xml)")
62+
63+
5964
def register():
6065
bpy.types.Scene.BIMWorkPlanProperties = bpy.props.PointerProperty(type=prop.BIMWorkPlanProperties)
6166
bpy.types.Scene.BIMWorkScheduleProperties = bpy.props.PointerProperty(type=prop.BIMWorkScheduleProperties)
6267
bpy.types.Scene.BIMWorkCalendarProperties = bpy.props.PointerProperty(type=prop.BIMWorkCalendarProperties)
68+
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
6369

6470

6571
def unregister():
6672
del bpy.types.Scene.BIMWorkPlanProperties
6773
del bpy.types.Scene.BIMWorkScheduleProperties
6874
del bpy.types.Scene.BIMWorkCalendarProperties
75+
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)

src/blenderbim/blenderbim/bim/module/sequence/operator.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import os
22
import bpy
33
import json
4+
import time
45
import pystache
56
import webbrowser
67
import ifcopenshell.api
78
from datetime import datetime
89
from dateutil import parser
910
from blenderbim.bim.ifc import IfcStore
11+
from bpy_extras.io_utils import ImportHelper
1012
from ifcopenshell.api.sequence.data import Data
1113

1214

@@ -808,3 +810,23 @@ class DisableEditingWorkCalendar(bpy.types.Operator):
808810
def execute(self, context):
809811
context.scene.BIMWorkCalendarProperties.active_work_calendar_id = 0
810812
return {"FINISHED"}
813+
814+
815+
class ImportP6(bpy.types.Operator, ImportHelper):
816+
bl_idname = "import_p6.bim"
817+
bl_label = "Import P6"
818+
filename_ext = ".xml"
819+
filter_glob: bpy.props.StringProperty(default="*.xml", options={"HIDDEN"})
820+
821+
def execute(self, context):
822+
from ifcp6.p62ifc import P62Ifc
823+
self.file = IfcStore.get_file()
824+
start = time.time()
825+
p62ifc = P62Ifc()
826+
p62ifc.xml = self.filepath
827+
p62ifc.file = self.file
828+
p62ifc.work_plan = self.file.by_type("IfcWorkPlan")[0]
829+
p62ifc.execute()
830+
Data.load(IfcStore.get_file())
831+
print("Import finished in {:.2f} seconds".format(time.time() - start))
832+
return {"FINISHED"}

src/blenderbim/p6_to_ifc.py

Lines changed: 0 additions & 129 deletions
This file was deleted.

src/ifcp6/ifcp6/p62ifc.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import ifcopenshell
2+
import ifcopenshell.api
3+
import ifcopenshell.util.date
4+
import xml.etree.ElementTree as ET
5+
from datetime import datetime
6+
7+
8+
class P62Ifc:
9+
def __init__(self):
10+
self.xml = None
11+
self.file = None
12+
self.work_plan = None
13+
self.project = {}
14+
self.wbs = {}
15+
self.activity = {}
16+
17+
def execute(self):
18+
self.parse_xml()
19+
self.create_ifc()
20+
21+
def parse_xml(self):
22+
tree = ET.parse(self.xml)
23+
ns = {"pr": "http://xmlns.oracle.com/Primavera/P6/V19.12/API/BusinessObjects"}
24+
root = tree.getroot()
25+
project = root.find("pr:Project", ns)
26+
self.project["Name"] = project.find("pr:Name", ns).text
27+
28+
for wbs in project.findall("pr:WBS", ns):
29+
self.wbs[wbs.find("pr:ObjectId", ns).text] = {
30+
"Name": wbs.find("pr:Name", ns).text,
31+
"Code": wbs.find("pr:Code", ns).text,
32+
"ParentObjectId": wbs.find("pr:ParentObjectId", ns).text,
33+
"ifc": None,
34+
"rel": None,
35+
"activities": [],
36+
}
37+
38+
for activity in project.findall("pr:Activity", ns):
39+
self.wbs[activity.find("pr:WBSObjectId", ns).text]["activities"].append(
40+
{
41+
"Name": activity.find("pr:Name", ns).text,
42+
"Identification": activity.find("pr:Id", ns).text,
43+
"StartDate": datetime.fromisoformat(activity.find("pr:StartDate", ns).text),
44+
"FinishDate": datetime.fromisoformat(activity.find("pr:FinishDate", ns).text),
45+
"Status": activity.find("pr:Status", ns).text,
46+
"ifc": None,
47+
}
48+
)
49+
50+
def get_wbs(self, wbs):
51+
return {"Name": wbs.find("pr:Name", ns).text, "subtasks": []}
52+
53+
def create_ifc(self):
54+
if not self.file:
55+
self.file = self.create_boilerplate_ifc()
56+
work_schedule = self.create_work_schedule()
57+
self.create_tasks(work_schedule)
58+
59+
def create_work_schedule(self):
60+
return ifcopenshell.api.run(
61+
"sequence.add_work_schedule", self.file, name=self.project["Name"], work_plan=self.work_plan
62+
)
63+
64+
def create_tasks(self, work_schedule):
65+
for wbs in self.wbs.values():
66+
self.create_task_from_wbs(wbs, work_schedule)
67+
68+
def create_task_from_wbs(self, wbs, work_schedule):
69+
wbs["ifc"] = ifcopenshell.api.run(
70+
"sequence.add_task",
71+
self.file,
72+
work_schedule=None if wbs["ParentObjectId"] else work_schedule,
73+
parent_task=self.wbs[wbs["ParentObjectId"]]["ifc"] if wbs["ParentObjectId"] else None,
74+
)
75+
ifcopenshell.api.run(
76+
"sequence.edit_task",
77+
self.file,
78+
task=wbs["ifc"],
79+
attributes={"Name": wbs["Name"], "Identification": wbs["Code"]},
80+
)
81+
for activity in wbs["activities"]:
82+
self.create_task_from_activity(activity, wbs, work_schedule)
83+
84+
def create_task_from_activity(self, activity, wbs, work_schedule):
85+
activity["ifc"] = ifcopenshell.api.run(
86+
"sequence.add_task",
87+
self.file,
88+
parent_task=wbs["ifc"],
89+
)
90+
ifcopenshell.api.run(
91+
"sequence.edit_task",
92+
self.file,
93+
task=activity["ifc"],
94+
attributes={
95+
"Name": activity["Name"],
96+
"Identification": activity["Identification"],
97+
"Status": activity["Status"],
98+
"IsMilestone": activity["StartDate"] == activity["FinishDate"],
99+
},
100+
)
101+
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=activity["ifc"])
102+
ifcopenshell.api.run(
103+
"sequence.edit_task_time",
104+
self.file,
105+
task_time=task_time,
106+
attributes={
107+
"ScheduleStart": activity["StartDate"],
108+
"ScheduleFinish": activity["FinishDate"],
109+
},
110+
)
111+
112+
def create_boilerplate_ifc(self):
113+
self.file = ifcopenshell.file(schema="IFC4")
114+
self.work_plan = self.file.create_entity("IfcWorkPlan")

0 commit comments

Comments
 (0)