Add support to override COBie types/components selection

This commit is contained in:
Dion Moult
2020-08-21 11:38:43 +10:00
parent f64e0c9acc
commit 668edbc45e
4 changed files with 43 additions and 76 deletions
@@ -1334,8 +1334,12 @@ class ExecuteIfcCobie(bpy.types.Operator):
fh.setFormatter(logging.Formatter('%(asctime)s : %(levelname)s : %(message)s')) fh.setFormatter(logging.Formatter('%(asctime)s : %(levelname)s : %(message)s'))
logger = logging.getLogger('IFCtoCOBie') logger = logging.getLogger('IFCtoCOBie')
logger.addHandler(fh) logger.addHandler(fh)
parser = IfcCobieParser(logger) selector = ifcopenshell.util.selector.Selector()
parser.parse(bpy.context.scene.BIMProperties.cobie_ifc_file) 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': if self.file_format == 'xlsx':
from cobie import CobieXlsWriter from cobie import CobieXlsWriter
writer = CobieXlsWriter(parser, output) writer = CobieXlsWriter(parser, output)
@@ -1125,6 +1125,8 @@ class BIMProperties(PropertyGroup):
features_file: EnumProperty(items=getFeaturesFiles, name="Features File", update=refreshScenarios) features_file: EnumProperty(items=getFeaturesFiles, name="Features File", update=refreshScenarios)
scenario: EnumProperty(items=getScenarios, name="Scenario") scenario: EnumProperty(items=getScenarios, name="Scenario")
cobie_ifc_file: StringProperty(default='', name="COBie IFC File") 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_json_file: StringProperty(default='', name="Diff JSON File")
diff_old_file: StringProperty(default='', name="Diff Old IFC File") diff_old_file: StringProperty(default='', name="Diff Old IFC File")
diff_new_file: StringProperty(default='', name="Diff New IFC File") diff_new_file: StringProperty(default='', name="Diff New IFC File")
@@ -1586,6 +1586,11 @@ class BIM_PT_cobie(Panel):
row.prop(props, "cobie_ifc_file") row.prop(props, "cobie_ifc_file")
row.operator("bim.select_cobie_ifc_file", icon="FILE_FOLDER", text="") 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() row = layout.row()
op = row.operator('bim.execute_ifc_cobie', text='CSV') op = row.operator('bim.execute_ifc_cobie', text='CSV')
op.file_format = 'csv' op.file_format = 'csv'
+30 -74
View File
@@ -5,11 +5,13 @@ import os
import time import time
import argparse import argparse
import datetime import datetime
import ifcopenshell
import logging import logging
import ifcopenshell
import ifcopenshell.util.selector
class IfcCobieParser(): class IfcCobieParser():
def __init__(self, logger): def __init__(self, logger, selector):
self.selector = selector
self.logger = logger self.logger = logger
self.file = None self.file = None
self.contacts = {} self.contacts = {}
@@ -30,60 +32,6 @@ class IfcCobieParser():
self.attributes = {} self.attributes = {}
self.coordinates = {} self.coordinates = {}
self.issues = {} 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 = { self.picklists = {
'Category-Role': [], 'Category-Role': [],
'Category-Facility': [], 'Category-Facility': [],
@@ -101,8 +49,14 @@ class IfcCobieParser():
} }
self.default_date = (datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds = -2177452801)).isoformat() 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.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_contacts()
self.get_facilities() self.get_facilities()
self.get_floors() self.get_floors()
@@ -231,14 +185,7 @@ class IfcCobieParser():
def get_types(self): def get_types(self):
types = self.file.by_type('IfcTypeObject') types = self.file.by_type('IfcTypeObject')
for type in types: for type in self.type_assets:
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
# The responsibility matrix states to parse IfcMaterial and # The responsibility matrix states to parse IfcMaterial and
# IfcMaterialLayerSet too, but it doesn't make much sense, so I # IfcMaterialLayerSet too, but it doesn't make much sense, so I
# don't parse it. # don't parse it.
@@ -600,12 +547,8 @@ class IfcCobieParser():
return object.Name return object.Name
self.logger.error('The connected object relationship {} is not a component asset for {}'.format(key, connection)) self.logger.error('The connected object relationship {} is not a component asset for {}'.format(key, connection))
def is_object_a_component_asset(self, object): def is_object_a_component_asset(self, obj):
is_an_asset = False return obj in self.component_assets
for asset in self.component_assets:
if object.is_a(asset):
is_an_asset = True
return is_an_asset
def get_space_name_from_component(self, component): def get_space_name_from_component(self, component):
for relationship in component.ContainedInStructure: for relationship in component.ContainedInStructure:
@@ -1192,8 +1135,20 @@ if __name__ == '__main__':
'-f', '-f',
'--format', '--format',
type=str, type=str,
help='Choose which format to export in (csv/xlsx)', help='Choose which format to export in (csv/ods/xlsx)',
default='csv') 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()) args = vars(parser.parse_args())
print('Processing IFC file ...') print('Processing IFC file ...')
@@ -1204,8 +1159,9 @@ if __name__ == '__main__':
filemode='a', level=logging.DEBUG) filemode='a', level=logging.DEBUG)
logger = logging.getLogger('IFCtoCOBie') logger = logging.getLogger('IFCtoCOBie')
logger.info('Starting conversion') logger.info('Starting conversion')
parser = IfcCobieParser(logger) selector = ifcopenshell.util.selector.Selector()
parser.parse(args['input']) parser = IfcCobieParser(logger, selector)
parser.parse(args['input'], args['types'], args['components'])
print('Generating reports ...') print('Generating reports ...')