mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 10:11:46 +00:00
Basic implementation to bulk convert relevant IFC classes to a Brick model
This commit is contained in:
@@ -25,6 +25,7 @@ classes = (
|
|||||||
operator.AssignBrickReference,
|
operator.AssignBrickReference,
|
||||||
operator.CloseBrickProject,
|
operator.CloseBrickProject,
|
||||||
operator.ConvertBrickProject,
|
operator.ConvertBrickProject,
|
||||||
|
operator.ConvertIfcToBrick,
|
||||||
operator.LoadBrickProject,
|
operator.LoadBrickProject,
|
||||||
operator.RewindBrickClass,
|
operator.RewindBrickClass,
|
||||||
operator.ViewBrickClass,
|
operator.ViewBrickClass,
|
||||||
|
|||||||
@@ -141,3 +141,16 @@ class AddBrickFeed(bpy.types.Operator, Operator):
|
|||||||
source=[o for o in context.selected_objects if o != context.active_object][0],
|
source=[o for o in context.selected_objects if o != context.active_object][0],
|
||||||
destination=context.active_object,
|
destination=context.active_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ConvertIfcToBrick(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.convert_ifc_to_brick"
|
||||||
|
bl_label = "Convert IFC To Brick"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
props = context.scene.BIMBrickProperties
|
||||||
|
library = None
|
||||||
|
if props.libraries:
|
||||||
|
library = tool.Ifc.get().by_id(int(props.libraries))
|
||||||
|
core.convert_ifc_to_brick(tool.Brick, namespace=props.namespace, library=library)
|
||||||
|
|||||||
@@ -98,8 +98,9 @@ class BIM_PT_ifc_brickschema_references(Panel):
|
|||||||
row.prop(self.props, "libraries")
|
row.prop(self.props, "libraries")
|
||||||
row.operator("bim.convert_brick_project", text="", icon="ADD")
|
row.operator("bim.convert_brick_project", text="", icon="ADD")
|
||||||
|
|
||||||
row = self.layout.row()
|
row = self.layout.row(align=True)
|
||||||
row.operator("bim.assign_brick_reference", icon="ADD")
|
row.operator("bim.assign_brick_reference", icon="ADD")
|
||||||
|
row.operator("bim.convert_ifc_to_brick", icon="IMPORT")
|
||||||
|
|
||||||
if not BrickschemaReferencesData.data["references"]:
|
if not BrickschemaReferencesData.data["references"]:
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
|
|||||||
@@ -79,3 +79,11 @@ def add_brick_feed(ifc, brick, source=None, destination=None):
|
|||||||
source_element = ifc.get_entity(source)
|
source_element = ifc.get_entity(source)
|
||||||
destination_element = ifc.get_entity(destination)
|
destination_element = ifc.get_entity(destination)
|
||||||
brick.add_feed(brick.get_brick(source_element), brick.get_brick(destination_element))
|
brick.add_feed(brick.get_brick(source_element), brick.get_brick(destination_element))
|
||||||
|
|
||||||
|
|
||||||
|
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.run_add_brick(obj=obj, namespace=namespace, brick_class=brick_class, library=library)
|
||||||
|
|||||||
@@ -52,9 +52,11 @@ class Brick:
|
|||||||
def clear_project(cls): pass
|
def clear_project(cls): pass
|
||||||
def export_brick_attributes(cls, brick_uri): pass
|
def export_brick_attributes(cls, brick_uri): pass
|
||||||
def get_brick(cls, element): pass
|
def get_brick(cls, element): pass
|
||||||
|
def get_brick_class(cls, element): pass
|
||||||
def get_brick_path(cls): pass
|
def get_brick_path(cls): pass
|
||||||
def get_brick_path_name(cls): pass
|
def get_brick_path_name(cls): pass
|
||||||
def get_brickifc_project(cls): pass
|
def get_brickifc_project(cls): pass
|
||||||
|
def get_convertable_brick_objects_and_elements(cls): pass
|
||||||
def get_item_class(cls, item): pass
|
def get_item_class(cls, item): pass
|
||||||
def get_library_brick_reference(cls, library, brick_uri): pass
|
def get_library_brick_reference(cls, library, brick_uri): pass
|
||||||
def get_namespace(cls, uri): pass
|
def get_namespace(cls, uri): pass
|
||||||
@@ -62,6 +64,7 @@ class Brick:
|
|||||||
def import_brick_items(cls, brick_class): pass
|
def import_brick_items(cls, brick_class): pass
|
||||||
def load_brick_file(cls, filepath): pass
|
def load_brick_file(cls, filepath): pass
|
||||||
def pop_brick_breadcrumb(cls): pass
|
def pop_brick_breadcrumb(cls): pass
|
||||||
|
def run_add_brick(cls, obj=None, namespace=None, brick_class=None, library=None): pass
|
||||||
def run_assign_brick_reference(cls, obj=None, library=None, brick_uri=None): pass
|
def run_assign_brick_reference(cls, obj=None, library=None, brick_uri=None): pass
|
||||||
def select_browser_item(cls, item): pass
|
def select_browser_item(cls, item): pass
|
||||||
def set_active_brick_class(cls, brick_class): pass
|
def set_active_brick_class(cls, brick_class): pass
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import bpy
|
import bpy
|
||||||
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.brick
|
||||||
import blenderbim.core.tool
|
import blenderbim.core.tool
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
|
|
||||||
@@ -110,6 +112,10 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
if tool.Ifc.get_schema() != "IFC2X3" and "#" in rel.RelatingLibrary.Identification:
|
if tool.Ifc.get_schema() != "IFC2X3" and "#" in rel.RelatingLibrary.Identification:
|
||||||
return rel.RelatingLibrary.Identification
|
return rel.RelatingLibrary.Identification
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_brick_class(cls, element):
|
||||||
|
return ifcopenshell.util.brick.get_brick_type(element)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_brick_path(cls):
|
def get_brick_path(cls):
|
||||||
return BrickStore.path
|
return BrickStore.path
|
||||||
@@ -137,6 +143,15 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
if results:
|
if results:
|
||||||
return results[0][0].toPython()
|
return results[0][0].toPython()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_convertable_brick_objects_and_elements(cls):
|
||||||
|
results = []
|
||||||
|
for element in ifcopenshell.util.brick.get_brick_elements(tool.Ifc.get()):
|
||||||
|
obj = tool.Ifc.get_object(element)
|
||||||
|
if obj:
|
||||||
|
results.append((obj, element))
|
||||||
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_item_class(cls, item):
|
def get_item_class(cls, item):
|
||||||
query = BrickStore.graph.query(
|
query = BrickStore.graph.query(
|
||||||
@@ -229,6 +244,12 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
bpy.context.scene.BIMBrickProperties.brick_breadcrumbs.remove(last_index)
|
bpy.context.scene.BIMBrickProperties.brick_breadcrumbs.remove(last_index)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def run_add_brick(cls, obj=None, namespace=None, brick_class=None, library=None):
|
||||||
|
return blenderbim.core.brick.add_brick(
|
||||||
|
tool.Ifc, tool.Brick, obj=obj, namespace=namespace, brick_class=brick_class, library=library
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_assign_brick_reference(cls, obj=None, library=None, brick_uri=None):
|
def run_assign_brick_reference(cls, obj=None, library=None, brick_uri=None):
|
||||||
return blenderbim.core.brick.assign_brick_reference(
|
return blenderbim.core.brick.assign_brick_reference(
|
||||||
|
|||||||
@@ -96,3 +96,16 @@ Scenario: Add brick feed
|
|||||||
And additionally the object "IfcAirTerminalBox/Cube" is selected
|
And additionally the object "IfcAirTerminalBox/Cube" is selected
|
||||||
When I press "bim.add_brick_feed"
|
When I press "bim.add_brick_feed"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
|
Scenario: Convert IFC to brick
|
||||||
|
Given an empty IFC project
|
||||||
|
And I press "bim.load_brick_project(filepath='{cwd}/test/files/spaces.ttl')"
|
||||||
|
And I press "bim.convert_brick_project"
|
||||||
|
And I set "scene.BIMBrickProperties.namespace" to "http://example.org/digitaltwin#"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcUnitaryEquipment"
|
||||||
|
And I set "scene.BIMRootProperties.ifc_predefined_type" to "AIRHANDLER"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
When I press "bim.convert_ifc_to_brick"
|
||||||
|
Then nothing happens
|
||||||
|
|||||||
@@ -136,3 +136,18 @@ class TestAddBrickFeed:
|
|||||||
brick.get_brick("destination_element").should_be_called().will_return("destination_brick")
|
brick.get_brick("destination_element").should_be_called().will_return("destination_brick")
|
||||||
brick.add_feed("source_brick", "destination_brick").should_be_called()
|
brick.add_feed("source_brick", "destination_brick").should_be_called()
|
||||||
subject.add_brick_feed(ifc, brick, source="source", destination="destination")
|
subject.add_brick_feed(ifc, brick, source="source", destination="destination")
|
||||||
|
|
||||||
|
|
||||||
|
class TestConvertIfcToBrick:
|
||||||
|
def test_run(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("brick_class")
|
||||||
|
brick.run_add_brick(
|
||||||
|
obj="obj", namespace="namespace", brick_class="brick_class", library="library"
|
||||||
|
).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)
|
||||||
|
subject.convert_ifc_to_brick(brick, namespace="namespace", library="library")
|
||||||
|
|||||||
@@ -186,6 +186,13 @@ class TestGetBrick(NewFile):
|
|||||||
assert subject.get_brick(element) == "http://example.org/digitaltwin#globalid"
|
assert subject.get_brick(element) == "http://example.org/digitaltwin#globalid"
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetBrickClass(NewFile):
|
||||||
|
def test_run(self):
|
||||||
|
ifc = ifcopenshell.file()
|
||||||
|
element = ifc.createIfcAirTerminalBox()
|
||||||
|
assert subject.get_brick_class(element) == "https://brickschema.org/schema/Brick#TerminalUnit"
|
||||||
|
|
||||||
|
|
||||||
class TestGetBrickPath(NewFile):
|
class TestGetBrickPath(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
TestLoadBrickFile().test_run()
|
TestLoadBrickFile().test_run()
|
||||||
@@ -208,6 +215,17 @@ class TestGetBrickifcProject(NewFile):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetConvertableBrickObjectsAndElements(NewFile):
|
||||||
|
def test_run(self):
|
||||||
|
ifc = ifcopenshell.file()
|
||||||
|
tool.Ifc.set(ifc)
|
||||||
|
element = ifc.createIfcAirTerminalBox()
|
||||||
|
obj = bpy.data.objects.new("Object", None)
|
||||||
|
tool.Ifc.link(element, obj)
|
||||||
|
ifc.createIfcWall()
|
||||||
|
assert subject.get_convertable_brick_objects_and_elements() == [(obj, element)]
|
||||||
|
|
||||||
|
|
||||||
class TestGetItemClass(NewFile):
|
class TestGetItemClass(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
TestLoadBrickFile().test_run()
|
TestLoadBrickFile().test_run()
|
||||||
@@ -286,6 +304,11 @@ class TestPopBrickBreadcrumb(NewFile):
|
|||||||
assert bpy.context.scene.BIMBrickProperties.brick_breadcrumbs[0].name == "foo"
|
assert bpy.context.scene.BIMBrickProperties.brick_breadcrumbs[0].name == "foo"
|
||||||
|
|
||||||
|
|
||||||
|
class TestRunAddBrick(NewFile):
|
||||||
|
def test_nothing(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestRunAssignBrickReference(NewFile):
|
class TestRunAssignBrickReference(NewFile):
|
||||||
def test_nothing(self):
|
def test_nothing(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user