update BsDD to match new API

+ move Functions from operator to core/tool
This commit is contained in:
Christoph Mellueh
2024-01-10 15:15:28 +01:00
committed by Dion Moult
parent 27f6ac0575
commit e159151b44
9 changed files with 165 additions and 98 deletions
@@ -22,8 +22,8 @@ from . import ui, prop, operator
classes = (
operator.GetBSDDClassificationProperties,
operator.LoadBSDDDomains,
operator.SearchBSDDClassifications,
operator.SetActiveBSDDDomain,
operator.SearchBSDDClass,
operator.SetActiveBSDDDictionary,
prop.BSDDDomain,
prop.BSDDClassification,
prop.BSDDPset,
@@ -22,73 +22,39 @@ import bsdd
import json
import ifcopenshell
import blenderbim.tool as tool
from blenderbim.core import bsdd as core
from blenderbim.tool.bsdd import Bsdd
class LoadBSDDDomains(bpy.types.Operator):
bl_idname = "bim.load_bsdd_domains"
bl_label = "Load bSDD Domains"
bl_label = "Load bSDD Dictionaries"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMBSDDProperties
props.domains.clear()
client = bsdd.Client()
if props.load_preview_domains:
domains = client.Domain()
else:
domains = [d for d in client.Domain() if d["status"] == "Active"]
for domain in sorted(domains, key=lambda x: x["name"]):
new = props.domains.add()
new.name = domain["name"]
new.namespace_uri = domain["namespaceUri"]
new.default_language_code = domain["defaultLanguageCode"]
new.organization_name_owner = domain["organizationNameOwner"]
new.status = domain["status"]
new.version = domain["version"]
core.load_bsdd(context.scene.BIMBSDDProperties, bsdd.Client(), Bsdd)
return {"FINISHED"}
class SetActiveBSDDDomain(bpy.types.Operator):
class SetActiveBSDDDictionary(bpy.types.Operator):
bl_idname = "bim.set_active_bsdd_domain"
bl_label = "Load bSDD Domains"
bl_label = "Load bSDD Dictionary"
bl_options = {"REGISTER", "UNDO"}
name: bpy.props.StringProperty()
uri: bpy.props.StringProperty()
def execute(self, context):
props = context.scene.BIMBSDDProperties
props.active_domain = self.name
props.active_uri = self.uri
core.set_active_bsdd_dictionary(context, self.name, self.uri)
return {"FINISHED"}
class SearchBSDDClassifications(bpy.types.Operator):
class SearchBSDDClass(bpy.types.Operator):
bl_idname = "bim.search_bsdd_classifications"
bl_label = "Search bSDD Classifications"
bl_label = "Search bSDD Class"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMBSDDProperties
props.classifications.clear()
client = bsdd.Client()
related_ifc_entities = []
if len(props.keyword) < 3:
return {"FINISHED"}
if props.should_filter_ifc_class and context.active_object:
element = tool.Ifc.get_entity(context.active_object)
if element:
related_ifc_entities = [element.is_a()]
results = client.ClassificationSearchOpen(props.keyword, DomainNamespaceUris=[props.active_uri], RelatedIfcEntities=related_ifc_entities)
for result in sorted(results["classifications"], key=lambda x: x["referenceCode"]):
new = props.classifications.add()
new.name = result["name"]
new.reference_code = result["referenceCode"]
new.description = result.get("description", "")
new.namespace_uri = result["namespaceUri"]
new.domain_name = result["domainName"]
new.domain_namespace_uri = result["domainNamespaceUri"]
core.search_class(context, bsdd.Client(), tool.Bsdd, tool.Ifc)
return {"FINISHED"}
@@ -98,50 +64,5 @@ class GetBSDDClassificationProperties(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
bprops = context.scene.BIMBSDDProperties
bprops.classification_psets.clear()
bsdd_classification = bprops.classifications[bprops.active_classification_index]
client = bsdd.Client()
data = client.Classification(bsdd_classification.namespace_uri)
properties = data.get("classificationProperties", None)
if not properties:
return {"FINISHED"}
psets = {}
for prop in properties:
if prop.get("propertyDomainName") != "IFC":
continue
pset = prop.get("propertySet", None)
if not pset:
continue
psets.setdefault(pset, {})
predefined_value = prop.get("predefinedValue")
if predefined_value:
possible_values = [predefined_value]
else:
possible_values = prop.get("possibleValues", []) or []
possible_values = [v["value"] for v in possible_values]
psets[pset][prop["name"]] = {"data_type": prop["dataType"], "possible_values": possible_values}
data_type_map = {
"String": "string",
"Real": "float",
"Boolean": "boolean",
}
for pset_name, pset in psets.items():
new = bprops.classification_psets.add()
new.name = pset_name
for name, data in pset.items():
new2 = new.properties.add()
new2.name = name
if data["possible_values"]:
new2.enum_items = json.dumps(data["possible_values"])
new2.data_type = "enum"
else:
new2.data_type = data_type_map[data["data_type"]]
core.get_class_properties(context, bsdd.Client(), tool.Bsdd)
return {"FINISHED"}
@@ -33,7 +33,7 @@ from bpy.props import (
class BSDDDomain(PropertyGroup):
name: StringProperty(name="Name")
namespace_uri: StringProperty(name="URI")
uri: StringProperty(name="URI")
default_language_code: StringProperty(name="Language")
organization_name_owner: StringProperty(name="Organization")
status: StringProperty(name="Status")
@@ -44,7 +44,7 @@ class BSDDClassification(PropertyGroup):
name: StringProperty(name="Name")
reference_code: StringProperty(name="Reference Code")
description: StringProperty(name="Description")
namespace_uri: StringProperty(name="Namespace URI")
uri: StringProperty(name="Namespace URI")
domain_name: StringProperty(name="Domain Name")
domain_namespace_uri: StringProperty(name="Domain Namespace URI")
@@ -68,7 +68,7 @@ class BIM_UL_bsdd_domains(UIList):
row.label(text=f"{item.name} ({item.organization_name_owner})")
op = row.operator("bim.set_active_bsdd_domain", text="", icon="RESTRICT_SELECT_OFF")
op.name = item.name
op.uri = item.namespace_uri
op.uri = item.uri
class BIM_UL_bsdd_classifications(UIList):
@@ -107,13 +107,13 @@ class AddClassificationFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
props = context.scene.BIMBSDDProperties
domain = [d for d in props.domains if d.name == props.active_domain][0]
for element in tool.Ifc.get().by_type("IfcClassification"):
if element.Name == props.active_domain or element.Location == domain.namespace_uri:
if element.Name == props.active_domain or element.Location == domain.uri:
return
classification = ifcopenshell.api.run(
"classification.add_classification", tool.Ifc.get(), classification=props.active_domain
)
classification.Source = domain.organization_name_owner
classification.Location = domain.namespace_uri
classification.Location = domain.uri
classification.Edition = domain.version
@@ -418,7 +418,7 @@ class AddClassificationReferenceFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
identification=bsdd_classification.reference_code,
name=bsdd_classification.name,
)
reference.Location = bsdd_classification.namespace_uri
reference.Location = bsdd_classification.uri
for classification_pset in bprops.classification_psets:
is_pset = not classification_pset.name.startswith("Qto_")
+40
View File
@@ -0,0 +1,40 @@
def load_bsdd(props, client, bsdd):
props.domains.clear()
if props.load_preview_domains:
dictionaries = bsdd.get_dictionaries(client)
else:
dictionaries = bsdd.get_dictionaries(client, "Active")
if not props.load_preview_domains:
dictionaries = filter(lambda d: d["status"] == "Active", dictionaries)
for dictionary in sorted(dictionaries, key=lambda d: d["name"]):
new = props.domains.add()
bsdd.fill_dictionary_prop(new, dictionary)
def set_active_bsdd_dictionary(context, name, uri):
props = context.scene.BIMBSDDProperties
props.active_domain = name
props.active_uri = uri
def search_class(context, client, bsdd, ifc):
props = context.scene.BIMBSDDProperties
props.classifications.clear()
if len(props.keyword) < 3:
return
related_entities = bsdd.get_related_ifc_entities(props.keyword, props.should_filter_ifc_class,
context.active_object, ifc)
response: dict = client.search_class(props.keyword, dictionary_uris=[props.active_uri],
related_ifc_entities=related_entities)
classes = response.get("classes", [])
for _class in sorted(classes, key=lambda c: c["referenceCode"]):
bsdd.fill_class_prop(props.classifications.add(), _class)
def get_class_properties(context, client, bsdd):
bprops = context.scene.BIMBSDDProperties
data = bsdd.get_active_class_data(bprops, client)
pset_dict = bsdd.get_property_dict(data)
if pset_dict is None:
return
bsdd.create_classification_psets(bprops, pset_dict)
+14
View File
@@ -136,6 +136,20 @@ class Brick:
def clear_breadcrumbs(cls, split_screen=False): pass
class Bsdd:
def get_dictionaries(cls, client): pass
def fill_dictionary_prop(cls, prop, dictionary): pass
def get_related_ifc_entities(cls, keyword, filter_ifc_class, active_object, ifc): pass
def fill_class_prop(cls, prop, _class): pass
def get_active_class_data(cls, prop, client): pass
def get_property_dict(cls, class_data): pass
def create_classification_psets(cls, props, pset_dic): pass
@interface
class Collector:
def assign(cls, obj): pass
@@ -20,6 +20,7 @@ from blenderbim.tool.aggregate import Aggregate
from blenderbim.tool.blender import Blender
from blenderbim.tool.boundary import Boundary
from blenderbim.tool.brick import Brick
from blenderbim.tool.bsdd import Bsdd
from blenderbim.tool.cad import Cad
from blenderbim.tool.collector import Collector
from blenderbim.tool.context import Context
+91
View File
@@ -0,0 +1,91 @@
import blenderbim.core.tool
import json
class Bsdd(blenderbim.core.tool.Bsdd):
@classmethod
def get_dictionaries(cls, client, status=None) -> list:
response = client.get_dictionary()
dicts = response.get("dictionaries") or []
if status is not None:
dicts = filter(lambda d: d["status"] == status, dicts)
return dicts
@classmethod
def fill_dictionary_prop(cls, prop, dictionary):
prop.name = dictionary["name"]
prop.uri = dictionary["uri"]
prop.default_language_code = dictionary["defaultLanguageCode"]
prop.organization_name_owner = dictionary["organizationNameOwner"]
prop.status = dictionary["status"]
prop.version = dictionary["version"]
@classmethod
def get_related_ifc_entities(cls, keyword, filter_ifc_class: bool, active_object, ifc):
related_ifc_entities = []
if len(keyword) < 3:
return {"FINISHED"}
if filter_ifc_class and active_object:
element = ifc.get_entity(active_object)
if element:
related_ifc_entities = [element.is_a()]
return related_ifc_entities
@classmethod
def fill_class_prop(cls, prop, _class: dict):
prop.name = _class["name"]
prop.reference_code = _class["referenceCode"]
prop.description = _class.get("description", "")
prop.uri = _class["uri"]
prop.domain_name = _class["dictionaryName"]
prop.domain_namespace_uri = _class["dictionaryUri"]
@classmethod
def get_active_class_data(cls, prop, client):
prop.classification_psets.clear()
bsdd_classification = prop.classifications[prop.active_classification_index]
return client.get_class(bsdd_classification.uri)
@classmethod
def get_property_dict(cls, class_data: dict):
properties = class_data.get("classProperties", None)
if not properties:
return None
psets = {}
for prop in properties:
if prop.get("propertyDictionaryName") == "IFC":
continue
pset = prop.get("propertySet", None)
if not pset:
continue
psets.setdefault(pset, {})
predefined_value = prop.get("predefinedValue")
if predefined_value:
possible_values = [predefined_value]
else:
possible_values = prop.get("allowedValues", []) or []
possible_values = [v["value"] for v in possible_values]
psets[pset][prop["name"]] = {"data_type": prop["dataType"], "possible_values": possible_values}
return psets
@classmethod
def create_classification_psets(cls, props, pset_dict: dict):
data_type_map = {
"String": "string",
"Real": "float",
"Boolean": "boolean",
}
for pset_name, pset in pset_dict.items():
new = props.classification_psets.add()
new.name = pset_name
for name, data in pset.items():
new2 = new.properties.add()
new2.name = name
if data["possible_values"]:
new2.enum_items = json.dumps(data["possible_values"])
new2.data_type = "enum"
else:
new2.data_type = data_type_map[data["data_type"]]