From 0453db7745de40dc3de328ba02597fa7c6c88b26 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 12 Sep 2021 16:02:08 +1000 Subject: [PATCH] You can now filter imported objects by IFC class when loading a project --- src/blenderbim/blenderbim/bim/import_ifc.py | 2 + .../blenderbim/bim/module/project/operator.py | 12 +++++- .../blenderbim/bim/module/project/prop.py | 5 +++ .../blenderbim/bim/module/project/ui.py | 2 +- .../test/bim/module/project/test_operator.py | 40 +++++++++++++++++++ 5 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 6e344744bb..33b380d821 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -561,6 +561,8 @@ class IfcImporter: print("Done creating geometry") def create_products(self): + if self.ifc_import_settings.has_filter and not self.iterator_elements: + return if self.ifc_import_settings.should_use_cpu_multiprocessing: iterator = ifcopenshell.geom.iterator( self.settings, diff --git a/src/blenderbim/blenderbim/bim/module/project/operator.py b/src/blenderbim/blenderbim/bim/module/project/operator.py index 6c47fd84e7..06a81bc1f4 100644 --- a/src/blenderbim/blenderbim/bim/module/project/operator.py +++ b/src/blenderbim/blenderbim/bim/module/project/operator.py @@ -558,6 +558,8 @@ class LoadProjectElements(bpy.types.Operator): settings.has_filter = self.props.filter_mode != "NONE" if self.props.filter_mode == "DECOMPOSITION": settings.elements = self.get_decomposition_elements() + elif self.props.filter_mode == "IFC_CLASS": + settings.elements = self.get_ifc_class_elements() settings.logger.info("Starting import") ifc_importer = import_ifc.IfcImporter(settings) ifc_importer.execute() @@ -581,4 +583,12 @@ class LoadProjectElements(bpy.types.Operator): for container in containers: for rel in container.ContainsElements: elements.update(rel.RelatedElements) - return list(elements) + return elements + + def get_ifc_class_elements(self): + elements = set() + for filter_category in self.props.filter_categories: + if not filter_category.is_selected: + continue + elements.update(self.file.by_type(filter_category.name, include_subtypes=False)) + return elements diff --git a/src/blenderbim/blenderbim/bim/module/project/prop.py b/src/blenderbim/blenderbim/bim/module/project/prop.py index d4e450ae52..6acb2ce4f4 100644 --- a/src/blenderbim/blenderbim/bim/module/project/prop.py +++ b/src/blenderbim/blenderbim/bim/module/project/prop.py @@ -43,6 +43,11 @@ def update_filter_mode(self, context): new.name = "{}/{}".format(element.is_a(), element.Name or "Unnamed") new.ifc_definition_id = element.id() new.total_elements = sum([len(r.RelatedElements) for r in element.ContainsElements]) + elif self.filter_mode == "IFC_CLASS": + for ifc_class in sorted(list(set([e.is_a() for e in file.by_type("IfcElement")]))): + new = self.filter_categories.add() + new.name = ifc_class + new.total_elements = len(file.by_type(ifc_class, include_subtypes=False)) class LibraryElement(PropertyGroup): diff --git a/src/blenderbim/blenderbim/bim/module/project/ui.py b/src/blenderbim/blenderbim/bim/module/project/ui.py index f29ae76b4b..4bb0105c83 100644 --- a/src/blenderbim/blenderbim/bim/module/project/ui.py +++ b/src/blenderbim/blenderbim/bim/module/project/ui.py @@ -47,7 +47,7 @@ class BIM_PT_project(Panel): row.prop(pprops, "collection_mode") row = self.layout.row() row.prop(pprops, "filter_mode") - if pprops.filter_mode == "DECOMPOSITION": + if pprops.filter_mode != "NONE": self.layout.template_list( "BIM_UL_filter_categories", "", diff --git a/src/blenderbim/test/bim/module/project/test_operator.py b/src/blenderbim/test/bim/module/project/test_operator.py index d086df6197..806e4b4542 100644 --- a/src/blenderbim/test/bim/module/project/test_operator.py +++ b/src/blenderbim/test/bim/module/project/test_operator.py @@ -95,6 +95,46 @@ class TestLoadProjectElements(test.bim.bootstrap.NewFile): And the object "IfcWall/Wall" does not exist """ + @test.bim.bootstrap.scenario + def test_loading_objects_filtered_by_ifc_class(self): + return """ + Given I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc')" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "IFC_CLASS" + Then "scene.BIMProjectProperties.filter_categories['IfcWall'].total_elements" is "1" + And "scene.BIMProjectProperties.filter_categories['IfcSlab'].total_elements" is "1" + When I set "scene.BIMProjectProperties.filter_categories['IfcSlab'].is_selected" to "True" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" + And the object "IfcSlab/Slab" is an "IfcSlab" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcBuildingStorey/Level 1" does not exist + And the object "IfcWall/Wall" does not exist + """ + + @test.bim.bootstrap.scenario + def test_loading_no_objects_due_to_filter(self): + return """ + Given I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc')" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "IFC_CLASS" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" does not exist + And the object "IfcBuilding/My Building" does not exist + And the object "IfcBuildingStorey/Ground Floor" does not exist + And the object "IfcBuildingStorey/Level 1" does not exist + And the object "IfcSlab/Slab" does not exist + And the object "IfcWall/Wall" does not exist + """ + + class TestUnloadProject(test.bim.bootstrap.NewFile): @test.bim.bootstrap.scenario def test_unloading_a_project(self):