From 668edbc45e4ed082142d615aa521c5d3cb4ae500 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 21 Aug 2020 11:38:43 +1000 Subject: [PATCH] Add support to override COBie types/components selection --- .../blenderbim/bim/operator.py | 8 +- src/ifcblenderexport/blenderbim/bim/prop.py | 2 + src/ifcblenderexport/blenderbim/bim/ui.py | 5 + src/ifccobie/cobie.py | 104 +++++------------- 4 files changed, 43 insertions(+), 76 deletions(-) diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 0b7754a476..9788979d74 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -1334,8 +1334,12 @@ class ExecuteIfcCobie(bpy.types.Operator): fh.setFormatter(logging.Formatter('%(asctime)s : %(levelname)s : %(message)s')) logger = logging.getLogger('IFCtoCOBie') logger.addHandler(fh) - parser = IfcCobieParser(logger) - parser.parse(bpy.context.scene.BIMProperties.cobie_ifc_file) + selector = ifcopenshell.util.selector.Selector() + parser = IfcCobieParser(logger, selector) + parser.parse( + bpy.context.scene.BIMProperties.cobie_ifc_file, + bpy.context.scene.BIMProperties.cobie_types, + bpy.context.scene.BIMProperties.cobie_components) if self.file_format == 'xlsx': from cobie import CobieXlsWriter writer = CobieXlsWriter(parser, output) diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 845c906099..38f3b18483 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -1125,6 +1125,8 @@ class BIMProperties(PropertyGroup): features_file: EnumProperty(items=getFeaturesFiles, name="Features File", update=refreshScenarios) scenario: EnumProperty(items=getScenarios, name="Scenario") cobie_ifc_file: StringProperty(default='', name="COBie IFC File") + cobie_types: StringProperty(default='.COBieType', name="COBie Types") + cobie_components: StringProperty(default='.COBie', name="COBie Components") diff_json_file: StringProperty(default='', name="Diff JSON File") diff_old_file: StringProperty(default='', name="Diff Old IFC File") diff_new_file: StringProperty(default='', name="Diff New IFC File") diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 12bff5c22b..d43d4ae19d 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -1586,6 +1586,11 @@ class BIM_PT_cobie(Panel): row.prop(props, "cobie_ifc_file") row.operator("bim.select_cobie_ifc_file", icon="FILE_FOLDER", text="") + row = layout.row() + row.prop(props, "cobie_types") + row = layout.row() + row.prop(props, "cobie_components") + row = layout.row() op = row.operator('bim.execute_ifc_cobie', text='CSV') op.file_format = 'csv' diff --git a/src/ifccobie/cobie.py b/src/ifccobie/cobie.py index 1c6d0dff21..ab5b395d6b 100755 --- a/src/ifccobie/cobie.py +++ b/src/ifccobie/cobie.py @@ -5,11 +5,13 @@ import os import time import argparse import datetime -import ifcopenshell import logging +import ifcopenshell +import ifcopenshell.util.selector class IfcCobieParser(): - def __init__(self, logger): + def __init__(self, logger, selector): + self.selector = selector self.logger = logger self.file = None self.contacts = {} @@ -30,60 +32,6 @@ class IfcCobieParser(): self.attributes = {} self.coordinates = {} self.issues = {} - self.type_assets = [ - 'IfcDoorStyle', - 'IfcBuildingElementProxyType', - 'IfcChimneyType', - 'IfcCoveringType', - 'IfcDoorType', - 'IfcFootingType', - 'IfcPileType', - 'IfcRoofType', - 'IfcShadingDeviceType', - 'IfcWindowType', - 'IfcDistributionControlElementType', - 'IfcDistributionChamberElementType', - 'IfcEnergyConversionDeviceType', - 'IfcFlowControllerType', - 'IfcFlowMovingDeviceType', - 'IfcFlowStorageDeviceType', - 'IfcFlowTerminalType', - 'IfcFlowTreatmentDeviceType', - 'IfcElementAssemblyType', - 'IfcBuildingElementPartType', - 'IfcDiscreteAccessoryType', - 'IfcMechanicalFastenerType', - 'IfcReinforcingElementType', - 'IfcVibrationIsolatorType', - 'IfcFurnishingElementType', - 'IfcGeographicElementType', - 'IfcTransportElementType', - 'IfcSpatialZoneType', - 'IfcWindowStyle', - ] - self.component_assets = [ - 'IfcBuildingElementProxy', - 'IfcChimney', - 'IfcCovering', - 'IfcDoor', - 'IfcShadingDevice', - 'IfcWindow', - 'IfcDistributionControlElement', - 'IfcDistributionChamberElement', - 'IfcEnergyConversionDevice', - 'IfcFlowController', - 'IfcFlowMovingDevice', - 'IfcFlowStorageDevice', - 'IfcFlowTerminal', - 'IfcFlowTreatmentDevice', - 'IfcDiscreteAccessory', - 'IfcTendon', - 'IfcTendonAnchor', - 'IfcVibrationIsolator', - 'IfcFurnishingElement', - 'IfcGeographicElement', - 'IfcTransportElement', - ] self.picklists = { 'Category-Role': [], 'Category-Facility': [], @@ -101,8 +49,14 @@ class IfcCobieParser(): } self.default_date = (datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds = -2177452801)).isoformat() - def parse(self, filename): + def parse(self, filename, type_query=None, component_query=None): + if type_query is None: + type_query = '.COBieType' + if component_query is None: + component_query = '.COBie' self.file = ifcopenshell.open(filename) + self.type_assets = self.selector.parse(self.file, type_query) + self.component_assets = self.selector.parse(self.file, component_query) self.get_contacts() self.get_facilities() self.get_floors() @@ -231,14 +185,7 @@ class IfcCobieParser(): def get_types(self): types = self.file.by_type('IfcTypeObject') - for type in types: - is_a_type_asset = False - for type_asset in self.type_assets: - if type.is_a(type_asset): - is_a_type_asset = True - if not is_a_type_asset: - self.logger.warning('A type which is not an asset was found for {}'.format(type)) - continue + for type in self.type_assets: # The responsibility matrix states to parse IfcMaterial and # IfcMaterialLayerSet too, but it doesn't make much sense, so I # don't parse it. @@ -600,12 +547,8 @@ class IfcCobieParser(): return object.Name self.logger.error('The connected object relationship {} is not a component asset for {}'.format(key, connection)) - def is_object_a_component_asset(self, object): - is_an_asset = False - for asset in self.component_assets: - if object.is_a(asset): - is_an_asset = True - return is_an_asset + def is_object_a_component_asset(self, obj): + return obj in self.component_assets def get_space_name_from_component(self, component): for relationship in component.ContainedInStructure: @@ -1192,8 +1135,20 @@ if __name__ == '__main__': '-f', '--format', type=str, - help='Choose which format to export in (csv/xlsx)', + help='Choose which format to export in (csv/ods/xlsx)', default='csv') + parser.add_argument( + '-c', + '--components', + type=str, + help='A custom selector for components. Defaults to COBie', + default='.COBie') + parser.add_argument( + '-t', + '--types', + type=str, + help='A custom selector for types. Defaults to COBieType', + default='.COBieType') args = vars(parser.parse_args()) print('Processing IFC file ...') @@ -1204,8 +1159,9 @@ if __name__ == '__main__': filemode='a', level=logging.DEBUG) logger = logging.getLogger('IFCtoCOBie') logger.info('Starting conversion') - parser = IfcCobieParser(logger) - parser.parse(args['input']) + selector = ifcopenshell.util.selector.Selector() + parser = IfcCobieParser(logger, selector) + parser.parse(args['input'], args['types'], args['components']) print('Generating reports ...')