From 39960998de5396c7a793320f2b12a13beb3c2280 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 12 Jan 2022 15:39:43 +1100 Subject: [PATCH] Support type-based class checking for converting IFC2X3 models to Brickschema --- src/blenderbim/blenderbim/core/brick.py | 5 +--- src/blenderbim/test/core/test_brick.py | 6 ----- .../ifcopenshell/util/brick.py | 23 ++++++++++++------- .../test/util/test_brick.py | 13 ++++++++++- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/blenderbim/blenderbim/core/brick.py b/src/blenderbim/blenderbim/core/brick.py index 9557b74221..79f81d67c1 100644 --- a/src/blenderbim/blenderbim/core/brick.py +++ b/src/blenderbim/blenderbim/core/brick.py @@ -85,10 +85,7 @@ def add_brick_feed(ifc, brick, source=None, destination=None): def convert_ifc_to_brick(brick, namespace=None, library=None): for obj, element in brick.get_convertable_brick_objects_and_elements(): - brick_class = brick.get_brick_class(element) - if not brick_class: - continue - brick_uri = brick.add_brick(element, namespace, brick_class) + brick_uri = brick.add_brick(element, namespace, brick.get_brick_class(element)) if library: brick.run_assign_brick_reference(obj=obj, library=library, brick_uri=brick_uri) brick.run_refresh_brick_viewer() diff --git a/src/blenderbim/test/core/test_brick.py b/src/blenderbim/test/core/test_brick.py index 09cebb1d52..dd1a294ac8 100644 --- a/src/blenderbim/test/core/test_brick.py +++ b/src/blenderbim/test/core/test_brick.py @@ -150,12 +150,6 @@ class TestConvertIfcToBrick: brick.run_refresh_brick_viewer().should_be_called() subject.convert_ifc_to_brick(brick, namespace="namespace", library="library") - def test_not_converting_an_element_where_we_cannot_find_the_corresponding_brick_class(self, brick): - brick.get_convertable_brick_objects_and_elements().should_be_called().will_return([("obj", "element")]) - brick.get_brick_class("element").should_be_called().will_return(None) - brick.run_refresh_brick_viewer().should_be_called() - subject.convert_ifc_to_brick(brick, namespace="namespace", library="library") - class TestNewBrickFile: def test_run(self, brick): diff --git a/src/ifcopenshell-python/ifcopenshell/util/brick.py b/src/ifcopenshell-python/ifcopenshell/util/brick.py index 174d30aa51..9eb0ca9aa4 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/brick.py +++ b/src/ifcopenshell-python/ifcopenshell/util/brick.py @@ -1,5 +1,7 @@ import os import json +import ifcopenshell +import ifcopenshell.util.element cwd = os.path.dirname(os.path.realpath(__file__)) @@ -11,22 +13,27 @@ with open(os.path.join(cwd, "ifc4_to_brick.json")) as f: def get_brick_type(element): - predefined_type = getattr(element, "PredefinedType", None) result = None + predefined_type = ifcopenshell.util.element.get_predefined_type(element) if predefined_type: result = ifc4_to_brick_map.get(f"{element.is_a()}.{predefined_type}", None) if not result: result = ifc4_to_brick_map.get(element.is_a(), None) + if not result: + element_type = ifcopenshell.util.element.get_type(element) + if element_type: + ifc_type_class = element_type.is_a().replace("Type", "") + result = ifc4_to_brick_map.get(f"{ifc_type_class}.{predefined_type}", None) + if not result: + result = ifc4_to_brick_map.get(ifc_type_class, None) if result: return f"https://brickschema.org/schema/Brick#{result}" + # We choose equipment as a generic fallback + return f"https://brickschema.org/schema/Brick#Equipment" def get_brick_elements(ifc_file): - classes = {c.split(".")[0] for c in ifc4_to_brick_map.keys()} - elements = [] - for ifc_class in classes: - try: - elements += ifc_file.by_type(ifc_class) - except: - pass + elements = set(ifc_file.by_type("IfcDistributionElement")) + elements = elements.difference(ifc_file.by_type("IfcFlowSegment")) + elements = elements.difference(ifc_file.by_type("IfcFlowFitting")) return elements diff --git a/src/ifcopenshell-python/test/util/test_brick.py b/src/ifcopenshell-python/test/util/test_brick.py index 8f5f634da9..478872f8b4 100644 --- a/src/ifcopenshell-python/test/util/test_brick.py +++ b/src/ifcopenshell-python/test/util/test_brick.py @@ -1,5 +1,6 @@ import pytest import test.bootstrap +import ifcopenshell.api import ifcopenshell.util.brick as subject @@ -9,10 +10,20 @@ class TestGetBrickTypeIFC4(test.bootstrap.IFC4): assert subject.get_brick_type(element) == "https://brickschema.org/schema/Brick#TerminalUnit" element.PredefinedType = "CONSTANTFLOW" assert subject.get_brick_type(element) == "https://brickschema.org/schema/Brick#CAV" + element = self.file.createIfcEngine() + assert subject.get_brick_type(element) == "https://brickschema.org/schema/Brick#Equipment" + + +class TestGetBrickTypeIFC2X3(test.bootstrap.IFC2X3): + def test_run(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcFlowController") + type_element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcAirTerminalBoxType") + ifcopenshell.api.run("type.assign_type", self.file, related_object=element, relating_type=type_element) + assert subject.get_brick_type(element) == "https://brickschema.org/schema/Brick#TerminalUnit" class TestGetBrickElementsIFC4(test.bootstrap.IFC4): def test_run(self): element = self.file.createIfcAirTerminalBox() self.file.createIfcWall() - assert subject.get_brick_elements(self.file) == [element] + assert subject.get_brick_elements(self.file) == {element}