mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-10 22:16:41 +00:00
Merge pull request #3364 from IfcOpenShell/interface-to-interact-with-Brickschema
Interface to interact with brickschema PR #1
This commit is contained in:
@@ -95,3 +95,6 @@ src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
|
|||||||
|
|
||||||
# apple
|
# apple
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Brickschema
|
||||||
|
src/blenderbim/blenderbim/bim/schema/Brick.ttl
|
||||||
@@ -33,6 +33,9 @@ classes = (
|
|||||||
operator.RewindBrickClass,
|
operator.RewindBrickClass,
|
||||||
operator.ViewBrickClass,
|
operator.ViewBrickClass,
|
||||||
operator.ViewBrickItem,
|
operator.ViewBrickItem,
|
||||||
|
operator.UndoBrick,
|
||||||
|
operator.RedoBrick,
|
||||||
|
operator.SerializeBrick,
|
||||||
prop.Brick,
|
prop.Brick,
|
||||||
prop.BIMBrickProperties,
|
prop.BIMBrickProperties,
|
||||||
ui.BIM_PT_brickschema,
|
ui.BIM_PT_brickschema,
|
||||||
|
|||||||
@@ -110,7 +110,8 @@ class BrickschemaData:
|
|||||||
return []
|
return []
|
||||||
results = []
|
results = []
|
||||||
for alias, uri in BrickStore.graph.namespaces():
|
for alias, uri in BrickStore.graph.namespaces():
|
||||||
results.append((uri, f"{alias}: {uri}", ""))
|
# results.append((uri, f"{alias}: {uri}", ""))
|
||||||
|
results.append((uri, f"{alias}", ""))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -189,3 +189,24 @@ class RemoveBrick(bpy.types.Operator, Operator):
|
|||||||
library=tool.Ifc.get().by_id(int(props.libraries)) if props.libraries else None,
|
library=tool.Ifc.get().by_id(int(props.libraries)) if props.libraries else None,
|
||||||
brick_uri=props.bricks[props.active_brick_index].uri,
|
brick_uri=props.bricks[props.active_brick_index].uri,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class UndoBrick(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.undo_brick"
|
||||||
|
bl_label = "Undo Brick"
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
core.undo_brick(tool.Brick)
|
||||||
|
|
||||||
|
class RedoBrick(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.redo_brick"
|
||||||
|
bl_label = "Redo Brick"
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
core.redo_brick(tool.Brick)
|
||||||
|
|
||||||
|
class SerializeBrick(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.serialize_brick"
|
||||||
|
bl_label = "Serialize Brick"
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
core.serialize_brick(tool.Brick)
|
||||||
@@ -58,6 +58,13 @@ class BIM_PT_brickschema(Panel):
|
|||||||
row.operator("bim.add_brick_feed", text="", icon="PLUGIN")
|
row.operator("bim.add_brick_feed", text="", icon="PLUGIN")
|
||||||
row.operator("bim.remove_brick", text="", icon="X")
|
row.operator("bim.remove_brick", text="", icon="X")
|
||||||
|
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.operator("bim.undo_brick", icon="LOOP_BACK")
|
||||||
|
row.operator("bim.redo_brick", icon="LOOP_FORWARDS")
|
||||||
|
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.operator("bim.serialize_brick")
|
||||||
|
|
||||||
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"]:
|
||||||
|
|||||||
@@ -109,3 +109,14 @@ def remove_brick(ifc, brick, library=None, brick_uri=None):
|
|||||||
ifc.run("library.remove_reference", reference=reference)
|
ifc.run("library.remove_reference", reference=reference)
|
||||||
brick.remove_brick(brick_uri)
|
brick.remove_brick(brick_uri)
|
||||||
brick.run_refresh_brick_viewer()
|
brick.run_refresh_brick_viewer()
|
||||||
|
|
||||||
|
def undo_brick(brick):
|
||||||
|
brick.undo_brick()
|
||||||
|
brick.run_refresh_brick_viewer()
|
||||||
|
|
||||||
|
def redo_brick(brick):
|
||||||
|
brick.redo_brick()
|
||||||
|
brick.run_refresh_brick_viewer()
|
||||||
|
|
||||||
|
def serialize_brick(brick, file_name="BlenderBIMSerializeTest.ttl"):
|
||||||
|
brick.serialize_brick(file_name)
|
||||||
@@ -25,6 +25,7 @@ import blenderbim.tool as tool
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import brickschema
|
import brickschema
|
||||||
|
import brickschema.persistent
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from rdflib import Literal, URIRef, Namespace
|
from rdflib import Literal, URIRef, Namespace
|
||||||
from rdflib.namespace import RDF
|
from rdflib.namespace import RDF
|
||||||
@@ -32,14 +33,20 @@ except:
|
|||||||
# See #1860
|
# See #1860
|
||||||
print("Warning: brickschema not available.")
|
print("Warning: brickschema not available.")
|
||||||
|
|
||||||
|
# silence known rdflib_sqlalchemy TypeError warning
|
||||||
|
# see https://github.com/BrickSchema/Brick/issues/513#issuecomment-1558493675
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger("rdflib")
|
||||||
|
logger.setLevel(logging.ERROR)
|
||||||
|
|
||||||
class Brick(blenderbim.core.tool.Brick):
|
class Brick(blenderbim.core.tool.Brick):
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_brick(cls, namespace, brick_class):
|
def add_brick(cls, namespace, brick_class):
|
||||||
ns = Namespace(namespace)
|
ns = Namespace(namespace)
|
||||||
brick = ns[ifcopenshell.guid.expand(ifcopenshell.guid.new())]
|
brick = ns[ifcopenshell.guid.expand(ifcopenshell.guid.new())]
|
||||||
BrickStore.graph.add((brick, RDF.type, URIRef(brick_class)))
|
with BrickStore.graph.new_changeset("PROJECT") as cs:
|
||||||
BrickStore.graph.add((brick, URIRef("http://www.w3.org/2000/01/rdf-schema#label"), Literal("Unnamed")))
|
cs.add((brick, RDF.type, URIRef(brick_class)))
|
||||||
|
cs.add((brick, URIRef("http://www.w3.org/2000/01/rdf-schema#label"), Literal("Unnamed")))
|
||||||
return str(brick)
|
return str(brick)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -100,7 +107,7 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_project(cls):
|
def clear_project(cls):
|
||||||
BrickStore.graph = None
|
BrickStore.purge()
|
||||||
bpy.context.scene.BIMBrickProperties.active_brick_class == ""
|
bpy.context.scene.BIMBrickProperties.active_brick_class == ""
|
||||||
bpy.context.scene.BIMBrickProperties.brick_breadcrumbs.clear()
|
bpy.context.scene.BIMBrickProperties.brick_breadcrumbs.clear()
|
||||||
|
|
||||||
@@ -249,24 +256,24 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_brick_file(cls, filepath):
|
def load_brick_file(cls, filepath):
|
||||||
if not BrickStore.schema:
|
if not BrickStore.schema: # important check for running under test cases
|
||||||
BrickStore.schema = brickschema.Graph()
|
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
schema_path = os.path.join(cwd, "..", "bim", "schema", "Brick.ttl")
|
BrickStore.schema = os.path.join(cwd, "..", "bim", "schema", "Brick.ttl")
|
||||||
BrickStore.schema.load_file(schema_path)
|
BrickStore.graph = brickschema.persistent.VersionedGraphCollection("sqlite://")
|
||||||
BrickStore.graph = brickschema.Graph().load_file(filepath) + BrickStore.schema
|
with BrickStore.graph.new_changeset("SCHEMA") as cs:
|
||||||
|
cs.load_file(BrickStore.schema)
|
||||||
|
with BrickStore.graph.new_changeset("PROJECT") as cs:
|
||||||
|
cs.load_file(filepath)
|
||||||
BrickStore.path = filepath
|
BrickStore.path = filepath
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def new_brick_file(cls):
|
def new_brick_file(cls):
|
||||||
if not BrickStore.schema:
|
if not BrickStore.schema: # important check for running under test cases
|
||||||
BrickStore.schema = brickschema.Graph()
|
|
||||||
#BrickStore.schema = brickschema.persistent.VersionedGraphCollection("sqlite://")
|
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
schema_path = os.path.join(cwd, "..", "bim", "schema", "Brick.ttl")
|
BrickStore.schema = os.path.join(cwd, "..", "bim", "schema", "Brick.ttl")
|
||||||
BrickStore.schema.load_file(schema_path)
|
BrickStore.graph = brickschema.persistent.VersionedGraphCollection("sqlite://")
|
||||||
#BrickStore.schema.load_graph(schema_path)
|
with BrickStore.graph.new_changeset("SCHEMA") as cs:
|
||||||
BrickStore.graph = brickschema.Graph() + BrickStore.schema
|
cs.load_file(BrickStore.schema)
|
||||||
BrickStore.graph.bind("digitaltwin", Namespace("https://example.org/digitaltwin#"))
|
BrickStore.graph.bind("digitaltwin", Namespace("https://example.org/digitaltwin#"))
|
||||||
BrickStore.graph.bind("brick", Namespace("https://brickschema.org/schema/Brick#"))
|
BrickStore.graph.bind("brick", Namespace("https://brickschema.org/schema/Brick#"))
|
||||||
BrickStore.graph.bind("rdfs", Namespace("http://www.w3.org/2000/01/rdf-schema#"))
|
BrickStore.graph.bind("rdfs", Namespace("http://www.w3.org/2000/01/rdf-schema#"))
|
||||||
@@ -281,8 +288,10 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_brick(cls, brick_uri):
|
def remove_brick(cls, brick_uri):
|
||||||
for triple in BrickStore.graph.triples((URIRef(brick_uri), None, None)):
|
if(BrickStore.graph.triples((URIRef(brick_uri), None, None))):
|
||||||
BrickStore.graph.remove(triple)
|
with BrickStore.graph.new_changeset("PROJECT") as cs:
|
||||||
|
for triple in BrickStore.graph.triples((URIRef(brick_uri), None, None)):
|
||||||
|
cs.remove(triple)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_assign_brick_reference(cls, element=None, library=None, brick_uri=None):
|
def run_assign_brick_reference(cls, element=None, library=None, brick_uri=None):
|
||||||
@@ -308,14 +317,39 @@ class Brick(blenderbim.core.tool.Brick):
|
|||||||
def set_active_brick_class(cls, brick_class):
|
def set_active_brick_class(cls, brick_class):
|
||||||
bpy.context.scene.BIMBrickProperties.active_brick_class = brick_class
|
bpy.context.scene.BIMBrickProperties.active_brick_class = brick_class
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def undo_brick(cls):
|
||||||
|
if(len(BrickStore.graph.versions()) > 1):
|
||||||
|
BrickStore.graph.undo()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def redo_brick(cls):
|
||||||
|
with BrickStore.graph.conn() as conn:
|
||||||
|
redo_record = conn.execute(
|
||||||
|
"SELECT * from redos " "ORDER BY timestamp ASC LIMIT 1"
|
||||||
|
).fetchone()
|
||||||
|
if redo_record is not None:
|
||||||
|
BrickStore.graph.redo()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def serialize_brick(cls, file_name):
|
||||||
|
#temporary file path, could either be user selected for "save as" or use the BrickStore.path for simply "save"
|
||||||
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
dest = os.path.join(cwd, "..", "bim", "schema", file_name)
|
||||||
|
BrickStore.get_project().serialize(destination=dest, format="turtle")
|
||||||
|
|
||||||
class BrickStore:
|
class BrickStore:
|
||||||
schema = None
|
schema = None # this is now a os path
|
||||||
graph = None
|
path = None # file path if the project was loaded in
|
||||||
path = None
|
graph = None # this is the VersionedGraphCollection with 2 arbitrarily named graphs: "schema" and "project"
|
||||||
|
# "SCHEMA" holds the Brick.ttl metadata; "PROJECT" holds all the authored entities
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def purge():
|
def purge():
|
||||||
BrickStore.schema = None
|
BrickStore.schema = None
|
||||||
BrickStore.graph = None
|
BrickStore.graph = None
|
||||||
BrickStore.path = None
|
BrickStore.path = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_project(cls):
|
||||||
|
return BrickStore.graph.graph_at(graph="PROJECT")
|
||||||
@@ -307,10 +307,8 @@ class TestImportBrickItems(NewFile):
|
|||||||
class TestLoadBrickFile(NewFile):
|
class TestLoadBrickFile(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
# We stub the schema to make tests run faster
|
# We stub the schema to make tests run faster
|
||||||
BrickStore.schema = brickschema.Graph()
|
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
schema_path = os.path.join(cwd, "..", "files", "BrickStub.ttl")
|
BrickStore.schema = os.path.join(cwd, "..", "files", "BrickStub.ttl")
|
||||||
BrickStore.schema.load_file(schema_path)
|
|
||||||
|
|
||||||
# This is the actual test
|
# This is the actual test
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
@@ -322,10 +320,8 @@ class TestLoadBrickFile(NewFile):
|
|||||||
class TestNewBrickFile(NewFile):
|
class TestNewBrickFile(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
# We stub the schema to make tests run faster
|
# We stub the schema to make tests run faster
|
||||||
BrickStore.schema = brickschema.Graph()
|
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
schema_path = os.path.join(cwd, "..", "files", "BrickStub.ttl")
|
BrickStore.schema = os.path.join(cwd, "..", "files", "BrickStub.ttl")
|
||||||
BrickStore.schema.load_file(schema_path)
|
|
||||||
|
|
||||||
# This is the actual test
|
# This is the actual test
|
||||||
subject.new_brick_file()
|
subject.new_brick_file()
|
||||||
|
|||||||
Reference in New Issue
Block a user