mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 14:41:25 +00:00
You can now add feed relationships in a Brick model from IFC elements
This commit is contained in:
@@ -21,6 +21,7 @@ from . import ui, prop, operator
|
|||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
operator.AddBrick,
|
operator.AddBrick,
|
||||||
|
operator.AddBrickFeed,
|
||||||
operator.AssignBrickReference,
|
operator.AssignBrickReference,
|
||||||
operator.CloseBrickProject,
|
operator.CloseBrickProject,
|
||||||
operator.ConvertBrickProject,
|
operator.ConvertBrickProject,
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ class AddBrick(bpy.types.Operator, Operator):
|
|||||||
props = context.scene.BIMBrickProperties
|
props = context.scene.BIMBrickProperties
|
||||||
library = None
|
library = None
|
||||||
if props.libraries:
|
if props.libraries:
|
||||||
library=tool.Ifc.get().by_id(int(props.libraries))
|
library = tool.Ifc.get().by_id(int(props.libraries))
|
||||||
core.add_brick(
|
core.add_brick(
|
||||||
tool.Ifc,
|
tool.Ifc,
|
||||||
tool.Brick,
|
tool.Brick,
|
||||||
@@ -127,3 +127,17 @@ class AddBrick(bpy.types.Operator, Operator):
|
|||||||
brick_class=props.brick_equipment_class,
|
brick_class=props.brick_equipment_class,
|
||||||
library=library,
|
library=library,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AddBrickFeed(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.add_brick_feed"
|
||||||
|
bl_label = "Add Brick Feed"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
core.add_brick_feed(
|
||||||
|
tool.Ifc,
|
||||||
|
tool.Brick,
|
||||||
|
source=[o for o in context.selected_objects if o != context.active_object][0],
|
||||||
|
destination=context.active_object,
|
||||||
|
)
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ class BIM_PT_brickschema(Panel):
|
|||||||
row.prop(self.props, "namespace", text="")
|
row.prop(self.props, "namespace", text="")
|
||||||
row.prop(self.props, "brick_equipment_class", text="")
|
row.prop(self.props, "brick_equipment_class", text="")
|
||||||
row.operator("bim.add_brick", text="", icon="ADD")
|
row.operator("bim.add_brick", text="", icon="ADD")
|
||||||
|
row.operator("bim.add_brick_feed", text="", icon="PLUGIN")
|
||||||
|
|
||||||
self.layout.template_list("BIM_UL_bricks", "", self.props, "bricks", self.props, "active_brick_index")
|
self.layout.template_list("BIM_UL_bricks", "", self.props, "bricks", self.props, "active_brick_index")
|
||||||
|
|
||||||
for attribute in BrickschemaData.data["attributes"]:
|
for attribute in BrickschemaData.data["attributes"]:
|
||||||
|
|||||||
@@ -73,3 +73,9 @@ def add_brick(ifc, brick, obj=None, namespace=None, brick_class=None, library=No
|
|||||||
brick_uri = brick.add_brick(product, namespace, brick_class)
|
brick_uri = brick.add_brick(product, namespace, brick_class)
|
||||||
if library:
|
if library:
|
||||||
brick.run_assign_brick_reference(obj=obj, library=library, brick_uri=brick_uri)
|
brick.run_assign_brick_reference(obj=obj, library=library, brick_uri=brick_uri)
|
||||||
|
|
||||||
|
|
||||||
|
def add_brick_feed(ifc, brick, source=None, destination=None):
|
||||||
|
source_element = ifc.get_entity(source)
|
||||||
|
destination_element = ifc.get_entity(destination)
|
||||||
|
brick.add_feed(brick.get_brick(source_element), brick.get_brick(destination_element))
|
||||||
|
|||||||
@@ -47,9 +47,11 @@ class Brick:
|
|||||||
def add_brick_breadcrumb(cls): pass
|
def add_brick_breadcrumb(cls): pass
|
||||||
def add_brickifc_project(cls, namespace): pass
|
def add_brickifc_project(cls, namespace): pass
|
||||||
def add_brickifc_reference(cls, brick, element, project): pass
|
def add_brickifc_reference(cls, brick, element, project): pass
|
||||||
|
def add_feed(cls, source, destination): pass
|
||||||
def clear_brick_browser(cls): pass
|
def clear_brick_browser(cls): pass
|
||||||
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_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
|
||||||
|
|||||||
@@ -79,6 +79,11 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_feed(cls, source, destination):
|
||||||
|
ns_brick = Namespace("https://brickschema.org/schema/Brick#")
|
||||||
|
BrickStore.graph.add((URIRef(source), ns_brick["feeds"], URIRef(destination)))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_brick_browser(cls):
|
def clear_brick_browser(cls):
|
||||||
bpy.context.scene.BIMBrickProperties.bricks.clear()
|
bpy.context.scene.BIMBrickProperties.bricks.clear()
|
||||||
@@ -96,6 +101,15 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
else:
|
else:
|
||||||
return {"Identification": brick_uri, "Name": brick_uri.split("#")[-1]}
|
return {"Identification": brick_uri, "Name": brick_uri.split("#")[-1]}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_brick(cls, element):
|
||||||
|
for rel in element.HasAssociations:
|
||||||
|
if rel.is_a("IfcRelAssociatesLibrary"):
|
||||||
|
if tool.Ifc.get_schema() == "IFC2X3" and "#" in rel.RelatingLibrary.ItemReference:
|
||||||
|
return rel.RelatingLibrary.ItemReference
|
||||||
|
if tool.Ifc.get_schema() != "IFC2X3" and "#" in rel.RelatingLibrary.Identification:
|
||||||
|
return rel.RelatingLibrary.Identification
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_brick_path(cls):
|
def get_brick_path(cls):
|
||||||
return BrickStore.path
|
return BrickStore.path
|
||||||
|
|||||||
@@ -74,3 +74,25 @@ Scenario: Add brick - with a brick IFC library
|
|||||||
And I set "scene.BIMBrickProperties.namespace" to "http://example.org/digitaltwin#"
|
And I set "scene.BIMBrickProperties.namespace" to "http://example.org/digitaltwin#"
|
||||||
When I press "bim.add_brick"
|
When I press "bim.add_brick"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
|
Scenario: Add brick feed
|
||||||
|
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"
|
||||||
|
And I press "bim.add_brick"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcAirTerminalBox"
|
||||||
|
And I set "scene.BIMRootProperties.ifc_predefined_type" to "VARIABLEFLOWPRESSUREDEPENDANT"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I press "bim.add_brick"
|
||||||
|
And the object "IfcUnitaryEquipment/Cube" is selected
|
||||||
|
And additionally the object "IfcAirTerminalBox/Cube" is selected
|
||||||
|
When I press "bim.add_brick_feed"
|
||||||
|
Then nothing happens
|
||||||
|
|||||||
@@ -126,3 +126,13 @@ class TestAddBrick:
|
|||||||
brick.add_brick("product", "namespace", "brick_class").should_be_called().will_return("brick_uri")
|
brick.add_brick("product", "namespace", "brick_class").should_be_called().will_return("brick_uri")
|
||||||
brick.run_assign_brick_reference(obj="obj", library="library", brick_uri="brick_uri").should_be_called()
|
brick.run_assign_brick_reference(obj="obj", library="library", brick_uri="brick_uri").should_be_called()
|
||||||
subject.add_brick(ifc, brick, obj="obj", namespace="namespace", brick_class="brick_class", library="library")
|
subject.add_brick(ifc, brick, obj="obj", namespace="namespace", brick_class="brick_class", library="library")
|
||||||
|
|
||||||
|
|
||||||
|
class TestAddBrickFeed:
|
||||||
|
def test_run(self, ifc, brick):
|
||||||
|
ifc.get_entity("source").should_be_called().will_return("source_element")
|
||||||
|
ifc.get_entity("destination").should_be_called().will_return("destination_element")
|
||||||
|
brick.get_brick("source_element").should_be_called().will_return("source_brick")
|
||||||
|
brick.get_brick("destination_element").should_be_called().will_return("destination_brick")
|
||||||
|
brick.add_feed("source_brick", "destination_brick").should_be_called()
|
||||||
|
subject.add_brick_feed(ifc, brick, source="source", destination="destination")
|
||||||
|
|||||||
@@ -121,6 +121,21 @@ class TestAddBrickifcReference(NewFile):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestAddFeed(NewFile):
|
||||||
|
def test_run(self):
|
||||||
|
BrickStore.graph = brickschema.Graph()
|
||||||
|
subject.add_feed("http://example.org/digitaltwin#source", "http://example.org/digitaltwin#destination")
|
||||||
|
assert list(
|
||||||
|
BrickStore.graph.triples(
|
||||||
|
(
|
||||||
|
URIRef("http://example.org/digitaltwin#source"),
|
||||||
|
URIRef("https://brickschema.org/schema/Brick#feeds"),
|
||||||
|
URIRef("http://example.org/digitaltwin#destination"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestClearBrickBrowser(NewFile):
|
class TestClearBrickBrowser(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
bpy.context.scene.BIMBrickProperties.bricks.add()
|
bpy.context.scene.BIMBrickProperties.bricks.add()
|
||||||
@@ -141,11 +156,34 @@ class TestClearProject(NewFile):
|
|||||||
|
|
||||||
class TestExportBrickAttributes(NewFile):
|
class TestExportBrickAttributes(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
assert subject.export_brick_attributes("http://example.org/digitaltwin#floor") == {"Identification": "http://example.org/digitaltwin#floor", "Name": "floor"}
|
assert subject.export_brick_attributes("http://example.org/digitaltwin#floor") == {
|
||||||
|
"Identification": "http://example.org/digitaltwin#floor",
|
||||||
|
"Name": "floor",
|
||||||
|
}
|
||||||
|
|
||||||
def test_run_ifc2x3(self):
|
def test_run_ifc2x3(self):
|
||||||
tool.Ifc.set(ifcopenshell.file(schema="IFC2X3"))
|
tool.Ifc.set(ifcopenshell.file(schema="IFC2X3"))
|
||||||
assert subject.export_brick_attributes("http://example.org/digitaltwin#floor") == {"ItemReference": "http://example.org/digitaltwin#floor", "Name": "floor"}
|
assert subject.export_brick_attributes("http://example.org/digitaltwin#floor") == {
|
||||||
|
"ItemReference": "http://example.org/digitaltwin#floor",
|
||||||
|
"Name": "floor",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetBrick(NewFile):
|
||||||
|
def test_run(self):
|
||||||
|
ifc = ifcopenshell.file()
|
||||||
|
element = ifc.createIfcChiller()
|
||||||
|
library = ifc.createIfcLibraryReference(Identification="http://example.org/digitaltwin#globalid")
|
||||||
|
ifc.createIfcRelAssociatesLibrary(RelatedObjects=[element], RelatingLibrary=library)
|
||||||
|
assert subject.get_brick(element) == "http://example.org/digitaltwin#globalid"
|
||||||
|
|
||||||
|
def test_run_ifc2x3(self):
|
||||||
|
ifc = ifcopenshell.file(schema="IFC2X3")
|
||||||
|
tool.Ifc.set(ifc)
|
||||||
|
element = ifc.createIfcEnergyConversionDevice()
|
||||||
|
library = ifc.createIfcLibraryReference(ItemReference="http://example.org/digitaltwin#globalid")
|
||||||
|
ifc.createIfcRelAssociatesLibrary(RelatedObjects=[element], RelatingLibrary=library)
|
||||||
|
assert subject.get_brick(element) == "http://example.org/digitaltwin#globalid"
|
||||||
|
|
||||||
|
|
||||||
class TestGetBrickPath(NewFile):
|
class TestGetBrickPath(NewFile):
|
||||||
@@ -180,7 +218,9 @@ class TestGetLibraryBrickReference(NewFile):
|
|||||||
def test_run(self):
|
def test_run(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
library = ifc.createIfcLibraryInformation()
|
library = ifc.createIfcLibraryInformation()
|
||||||
reference = ifc.createIfcLibraryReference(Identification="http://example.org/digitaltwin#floor", ReferencedLibrary=library)
|
reference = ifc.createIfcLibraryReference(
|
||||||
|
Identification="http://example.org/digitaltwin#floor", ReferencedLibrary=library
|
||||||
|
)
|
||||||
assert subject.get_library_brick_reference(library, "http://example.org/digitaltwin#floor") == reference
|
assert subject.get_library_brick_reference(library, "http://example.org/digitaltwin#floor") == reference
|
||||||
|
|
||||||
def test_run_ifc2x3(self):
|
def test_run_ifc2x3(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user