From 64fe2e978e06f1555dd07182216837f2c1f5275b Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 16 May 2020 12:54:26 +1000 Subject: [PATCH] Bundle IFC Clash in Blender for clash detection for Windows and Linux --- src/ifcblenderexport/Makefile | 19 ++++++++++++++ .../blenderbim/bim/__init__.py | 2 ++ .../blenderbim/bim/operator.py | 26 +++++++++++++++++++ src/ifcblenderexport/blenderbim/bim/prop.py | 2 ++ src/ifcblenderexport/blenderbim/bim/ui.py | 25 ++++++++++++++++++ src/ifcclash/ifcclash.py | 19 +++++++++----- 6 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/ifcblenderexport/Makefile b/src/ifcblenderexport/Makefile index e9bbd6a471..b4bd3ff99f 100644 --- a/src/ifcblenderexport/Makefile +++ b/src/ifcblenderexport/Makefile @@ -163,6 +163,25 @@ endif cp -r dist/working/lark-parser-0.8.5/lark dist/blenderbim/libs/site/packages/ rm -rf dist/working +ifeq ($(PLATFORM), linux) + mkdir dist/working + cd dist/working && wget https://files.pythonhosted.org/packages/0c/fa/00d85f893b02289e2942849d97f8818dde8e2111182e825fb3a735677791/python_fcl-0.0.12-cp37-cp37m-manylinux1_x86_64.whl + cd dist/working && unzip python_fcl* + cp -r dist/working/fcl dist/blenderbim/libs/site/packages/ + rm -rf dist/working +endif + +ifeq ($(PLATFORM), win) + mkdir dist/working + cd dist/working && wget https://blenderbim.org/builds/fcl-py37-win.zip + cd dist/working && unzip fcl* + cp -r dist/working/fcl dist/blenderbim/libs/site/packages/ + rm -rf dist/working +endif + + cd dist/blenderbim/libs/site/packages/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcclash/collision.py + cd dist/blenderbim/libs/site/packages/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcclash/ifcclash.py + cd dist/blenderbim/libs/site/packages/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcdiff/ifcdiff.py cd dist/blenderbim/libs/site/packages/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifccsv/ifccsv.py diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 294683546d..ab62bace4d 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -96,6 +96,7 @@ if bpy is not None: operator.OpenView, operator.ActivateView, operator.ExecuteIfcDiff, + operator.ExecuteIfcClash, operator.AssignContext, operator.SwitchContext, operator.SetViewPreset1, @@ -168,6 +169,7 @@ if bpy is not None: ui.BIM_PT_document_information, ui.BIM_PT_search, ui.BIM_PT_ifccsv, + ui.BIM_PT_ifcclash, ui.BIM_PT_bcf, ui.BIM_PT_owner, ui.BIM_PT_context, diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 81fbeca274..084222c435 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -1153,6 +1153,32 @@ class ExecuteIfcDiff(bpy.types.Operator): return {'FINISHED'} +class ExecuteIfcClash(bpy.types.Operator): + bl_idname = 'bim.execute_ifc_clash' + bl_label = 'Execute IFC Clash' + filename_ext = '.json' + filepath: bpy.props.StringProperty(subtype='FILE_PATH') + + def invoke(self, context, event): + self.filepath = bpy.path.ensure_ext(bpy.data.filepath, '.json') + WindowManager = context.window_manager + WindowManager.fileselect_add(self) + return {'RUNNING_MODAL'} + + def execute(self, context): + import ifcclash + settings = ifcclash.IfcClashSettings() + self.filepath = bpy.path.ensure_ext(self.filepath, '.json') + settings.output = self.filepath + settings.logger = logging.getLogger('Clash') + settings.logger.setLevel(logging.DEBUG) + ifc_clasher = ifcclash.IfcClasher( + bpy.context.scene.BIMProperties.ifc_clash_a, bpy.context.scene.BIMProperties.ifc_clash_b, settings) + ifc_clasher.clash() + ifc_clasher.export() + return {'FINISHED'} + + class SelectBcfFile(bpy.types.Operator): bl_idname = "bim.select_bcf_file" bl_label = "Select BCF File" diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index fd3c1dacce..fe89b8702d 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -929,6 +929,8 @@ class BIMProperties(PropertyGroup): active_document_information_index: IntProperty(name='Active Document Information Index') document_references: CollectionProperty(name='Document References', type=DocumentReference) active_document_reference_index: IntProperty(name='Active Document Reference Index') + ifc_clash_a: StringProperty(name="IFC Clash A") + ifc_clash_b: StringProperty(name="IFC Clash B") class BCFProperties(PropertyGroup): diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index a4a156f8b7..00e6f8e80d 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -1272,3 +1272,28 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): row = layout.row() row.operator('bim.open_upstream', text='Visit Wiki').page = 'wiki' row.operator('bim.open_upstream', text='Visit Community').page = 'community' + + +class BIM_PT_ifcclash(Panel): + bl_label = "IFC Clash" + bl_idname = "BIM_PT_ifcclash" + bl_options = {'DEFAULT_CLOSED'} + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "scene" + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + scene = context.scene + props = scene.BIMProperties + + row = layout.row(align=True) + row.prop(props, 'ifc_clash_a') + + row = layout.row(align=True) + row.prop(props, 'ifc_clash_b') + + row = layout.row() + row.operator('bim.execute_ifc_clash') diff --git a/src/ifcclash/ifcclash.py b/src/ifcclash/ifcclash.py index ffc98e6e00..c8a9d9cc8f 100755 --- a/src/ifcclash/ifcclash.py +++ b/src/ifcclash/ifcclash.py @@ -62,6 +62,10 @@ class IfcClasher: 'penetration_depth': contact.raw.penetration_depth } + def export(self): + with open(self.settings.output, 'w', encoding='utf-8') as clashes_file: + json.dump(list(self.clashes.values()), clashes_file, indent=4) + def purge_elements(self, ab): # TODO: more filtering abilities for element in getattr(self, ab).by_type('IfcSpace'): @@ -146,6 +150,12 @@ class IfcClasher: element.ObjectPlacement.RelativePlacement.RefDirection.DirectionRatios = (1., 0., 0.) +class IfcClashSettings: + def __init__(self): + self.logger = None + self.output = 'clashes.json' + + if __name__ == '__main__': parser = argparse.ArgumentParser( description='Clashes geometry between two IFC files') @@ -165,11 +175,8 @@ if __name__ == '__main__': default='clashes.json') args = parser.parse_args() - class IfcClashSettings: - def __init__(self): - self.logger = None - settings = IfcClashSettings() + settings.output = args.output settings.logger = logging.getLogger('Clash') settings.logger.setLevel(logging.DEBUG) handler = logging.StreamHandler(sys.stdout) @@ -177,6 +184,4 @@ if __name__ == '__main__': settings.logger.addHandler(handler) ifc_clasher = IfcClasher(args.a, args.b, settings) ifc_clasher.clash() - - with open(args.output, 'w', encoding='utf-8') as clashes_file: - json.dump(list(ifc_clasher.clashes.values()), clashes_file, indent=4) + ifc_clasher.export()