From 6a06607f3faa5000b0c7186f9fe1477b3331c277 Mon Sep 17 00:00:00 2001 From: HassanEmam Date: Fri, 29 Oct 2021 11:16:47 +0100 Subject: [PATCH] BlenderBIM: Import Resources for XER files (#1841) * P6XML Parser failing on calendar type * add work plan references a get_person which is not an attribute. modified to get_user to work * Initial support for Primavera XER files * IFC4D impl XER calendars exceptions and work time * merged updats * refactoring code for the 4D model to avoid duplicate code * Assign process in the api module was missing an atrribute QuantityIn Process * Merged changes from master * refactoring * resolved conflicts * refactoring code for IFC4D * refactoring code for IFC4D * refactoring code for IFC4D * Reverted the changes to IfcRelAssignsToProcess usecase * Changed the class to be more discriptive from Utils to ScheduleIfcGenerator * reverted changes to add_work_plan and Makefile * Added resource parsing support for Primavera XER * added relative path for importing common as it was failing in BlenderBIM * Initial support for Primavera XER files * merged updats * Assign process in the api module was missing an atrribute QuantityIn Process * Merged changes from master * refactoring * resolved conflicts * refactoring code for IFC4D * refactoring code for IFC4D * Reverted the changes to IfcRelAssignsToProcess usecase * Changed the class to be more discriptive from Utils to ScheduleIfcGenerator * reverted changes to add_work_plan and Makefile * Added resource parsing support for Primavera XER * added relative path for importing common as it was failing in BlenderBIM * deleted repetitive classes for P6XER import Co-authored-by: Dion Moult --- .../bim/module/sequence/operator.py | 22 ---------- src/ifc4d/ifc4d/common.py | 41 ++++++++++++++++++- src/ifc4d/ifc4d/msp2ifc.py | 4 +- src/ifc4d/ifc4d/p62ifc.py | 4 +- src/ifc4d/ifc4d/p6xer2ifc.py | 26 ++++++++++-- 5 files changed, 66 insertions(+), 31 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/sequence/operator.py b/src/blenderbim/blenderbim/bim/module/sequence/operator.py index 499984d456..2c27aabbdf 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/operator.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/operator.py @@ -1120,28 +1120,6 @@ class ImportP6XER(bpy.types.Operator, ImportHelper): return {"FINISHED"} -class ImportP6XER(bpy.types.Operator, ImportHelper): - bl_idname = "import_p6xer.bim" - bl_label = "Import P6 XER" - bl_options = {"REGISTER", "UNDO"} - filename_ext = ".xer" - filter_glob: bpy.props.StringProperty(default="*.xer", options={"HIDDEN"}) - - def execute(self, context): - from ifc4d.p6xer2ifc import P6XER2Ifc - - self.file = IfcStore.get_file() - start = time.time() - p6xer2ifc = P6XER2Ifc() - p6xer2ifc.xer = self.filepath - p6xer2ifc.file = self.file - p6xer2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None - p6xer2ifc.execute() - Data.load(IfcStore.get_file()) - print("Import finished in {:.2f} seconds".format(time.time() - start)) - return {"FINISHED"} - - class ImportMSP(bpy.types.Operator, ImportHelper): bl_idname = "import_msp.bim" bl_label = "Import MSP" diff --git a/src/ifc4d/ifc4d/common.py b/src/ifc4d/ifc4d/common.py index 80f6c40016..b764b69aa5 100644 --- a/src/ifc4d/ifc4d/common.py +++ b/src/ifc4d/ifc4d/common.py @@ -7,7 +7,8 @@ from datetime import datetime, timedelta, date class ScheduleIfcGenerator: - def __init__(self, file, work_plan, project, calendars, wbs, root_activites, activities, relationships): + def __init__(self, file, work_plan, project, calendars, wbs, + root_activites, activities, relationships, resources): self.file = file self.work_plan = work_plan self.project = project @@ -16,6 +17,7 @@ class ScheduleIfcGenerator: self.root_activites = root_activites self.activities = activities self.relationships = relationships + self.resources = resources self.day_map = { "Monday": 1, "Tuesday": 2, @@ -35,6 +37,7 @@ class ScheduleIfcGenerator: self.create_calendars() self.create_tasks(work_schedule) self.create_rel_sequences() + self.create_resources() def create_work_schedule(self): return ifcopenshell.api.run( @@ -278,9 +281,43 @@ class ScheduleIfcGenerator: "sequence.assign_lag_time", self.file, rel_sequence=rel_sequence, - lag_value=datetime.timedelta(days=lag / float(calendar["HoursPerDay"])), + lag_value=timedelta(days=lag / float(calendar["HoursPerDay"])), duration_type="WORKTIME", ) + + + def create_resources(self): + + for id, resource in self.resources.items(): + + parent = self.resources.get(resource.get("ParentObjectId")) + if parent: + if not parent.get("ifc"): + parent["ifc"] = ifcopenshell.api.run( + "resource.add_resource", + self.file, + **{"ifc_class": "IfcCrewResource", + "name": parent['Name']} + ) + if parent: + resource["ifc"] = ifcopenshell.api.run( + "resource.add_resource", + self.file, + **{"parent_resource": parent["ifc"] if parent else None, + "ifc_class": "IfcCrewResource", + "name": resource['Name'] + } + ) + else: + resource["ifc"] = ifcopenshell.api.run( + "resource.add_resource", + self.file, + **{ "ifc_class": "IfcCrewResource", + "name": resource['Name'] + } + ) + + def create_boilerplate_ifc(self): self.file = ifcopenshell.file(schema="IFC4") diff --git a/src/ifc4d/ifc4d/msp2ifc.py b/src/ifc4d/ifc4d/msp2ifc.py index 243499879e..8b600e375c 100644 --- a/src/ifc4d/ifc4d/msp2ifc.py +++ b/src/ifc4d/ifc4d/msp2ifc.py @@ -23,7 +23,7 @@ import ifcopenshell import ifcopenshell.api import ifcopenshell.util.date import xml.etree.ElementTree as ET -from common import ScheduleIfcGenerator +from .common import ScheduleIfcGenerator class MSP2Ifc: @@ -42,7 +42,7 @@ class MSP2Ifc: def execute(self): self.parse_xml() ifcCreator = ScheduleIfcGenerator(self.file, self.work_plan, self.project, self.calendars, - self.wbs, self.root_activites, self.activities, self.relationships) + self.wbs, self.root_activites, self.activities, self.relationships, None) ifcCreator.create_ifc() #self.create_ifc() diff --git a/src/ifc4d/ifc4d/p62ifc.py b/src/ifc4d/ifc4d/p62ifc.py index 30f616b89b..ee3f552c6b 100644 --- a/src/ifc4d/ifc4d/p62ifc.py +++ b/src/ifc4d/ifc4d/p62ifc.py @@ -23,7 +23,7 @@ import ifcopenshell import ifcopenshell.api import ifcopenshell.util.date import xml.etree.ElementTree as ET -from common import ScheduleIfcGenerator +from .common import ScheduleIfcGenerator class P62Ifc: def __init__(self): @@ -49,7 +49,7 @@ class P62Ifc: def execute(self): self.parse_xml() ifcCreator = ScheduleIfcGenerator(self.file, self.work_plan, self.project, self.calendars, - self.wbs, self.root_activites, self.activities, self.relationships) + self.wbs, self.root_activites, self.activities, self.relationships, None) ifcCreator.create_ifc() def parse_xml(self): diff --git a/src/ifc4d/ifc4d/p6xer2ifc.py b/src/ifc4d/ifc4d/p6xer2ifc.py index 2fa653da1c..75cf9c1cfd 100644 --- a/src/ifc4d/ifc4d/p6xer2ifc.py +++ b/src/ifc4d/ifc4d/p6xer2ifc.py @@ -21,7 +21,7 @@ import ifcopenshell import ifcopenshell.api import ifcopenshell.util.date from datetime import datetime, timedelta, date -from common import ScheduleIfcGenerator +from .common import ScheduleIfcGenerator class P6XER2Ifc(): @@ -47,6 +47,12 @@ class P6XER2Ifc(): "PR_FF": "FINISH_FINISH" } + RESOURCE_TYPES_MAPPING = { + 'RT_Labor': "LABOR", + 'RT_Mat': "MATERIAL", + 'RT_Equip': "EQUIPMENT" + } + def __init__(self): self.xer = None self.file = None @@ -58,6 +64,7 @@ class P6XER2Ifc(): self.root_activites = [] self.activities = {} self.relationships = {} + self.resources = {} self.day_map2 = { @@ -74,7 +81,7 @@ class P6XER2Ifc(): def execute(self): self.parse_xer() ifcCreator = ScheduleIfcGenerator(self.file, self.work_plan, self.project, self.calendars, - self.wbs, self.root_activites, self.activities, self.relationships) + self.wbs, self.root_activites, self.activities, self.relationships, self.resources) ifcCreator.create_ifc() # self.create_ifc() @@ -84,11 +91,11 @@ class P6XER2Ifc(): # for project in self.model.projects: # if not self.project.get("Name"): self.project["Name"] = self.model.projects._projects[0].proj_short_name - print(self.project, type(self.model.projects._projects)) self.parse_calendar_xer() self.parse_wbs_xer() self.parse_activity_xer() self.parse_relationship_xer() + self.parse_resource_xer() #work_schedule = self.create_work_schedule() #self.create_tasks(work_schedule) @@ -160,6 +167,19 @@ class P6XER2Ifc(): } + def parse_resource_xer(self): + for rsrc in self.model.resources: + self.resources[rsrc.rsrc_id] = { + "Name": rsrc.rsrc_name, + "Code": rsrc.rsrc_short_name, + "ParentObjectId": rsrc.parent_rsrc_id, + "Type": self.RESOURCE_TYPES_MAPPING[rsrc.rsrc_type], + "ifc": None, + "rel": None, + } + print(dir(self.model.resources._rsrcs[0]), self.model.resources._rsrcs[0].rsrc_title_name) + + # TODO: add support for resources