mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Big bSDD overhaul for properties and classifications. See description.
* bSDD now supports a couple more args when querying the API. * Fetching properties via the classification UI has been removed * The bSDD dictionary selector has been merged into the classification source dropdown * The bSDD dictionary selector merged into the property set name dropdown * You can now search for properties in the bSDD directly when adding properties * You can browse properties via groups or classifications (based on assigned classifications) * You can browse properties via keyword (with some limitations due to the API) * You can selectively choose which properties you then want to add. Only basic support right now.
This commit is contained in:
@@ -20,15 +20,20 @@ import bpy
|
|||||||
from . import ui, prop, operator
|
from . import ui, prop, operator
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
operator.GetBSDDClassificationProperties,
|
operator.AddBSDDProperties,
|
||||||
|
operator.ImportBSDDClasses,
|
||||||
operator.LoadBSDDDictionaries,
|
operator.LoadBSDDDictionaries,
|
||||||
operator.SearchBSDDClass,
|
operator.SearchBSDDClassifications,
|
||||||
|
operator.SearchBSDDProperties,
|
||||||
prop.BSDDDictionary,
|
prop.BSDDDictionary,
|
||||||
prop.BSDDClassification,
|
prop.BSDDClassification,
|
||||||
|
prop.BSDDProperty,
|
||||||
prop.BSDDPset,
|
prop.BSDDPset,
|
||||||
prop.BIMBSDDProperties,
|
prop.BIMBSDDProperties,
|
||||||
ui.BIM_UL_bsdd_dictionaries,
|
|
||||||
ui.BIM_UL_bsdd_classifications,
|
ui.BIM_UL_bsdd_classifications,
|
||||||
|
ui.BIM_UL_bsdd_dictionaries,
|
||||||
|
ui.BIM_UL_bsdd_classes,
|
||||||
|
ui.BIM_UL_bsdd_properties,
|
||||||
ui.BIM_PT_bsdd,
|
ui.BIM_PT_bsdd,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import bsdd
|
import bsdd
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
|
import ifcopenshell.util.element
|
||||||
from bonsai.core import bsdd as core
|
from bonsai.core import bsdd as core
|
||||||
|
|
||||||
|
|
||||||
@@ -32,28 +33,73 @@ class LoadBSDDDictionaries(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class SearchBSDDClass(bpy.types.Operator):
|
class SearchBSDDClassifications(bpy.types.Operator):
|
||||||
bl_idname = "bim.search_bsdd_classifications"
|
bl_idname = "bim.search_bsdd_classifications"
|
||||||
bl_label = "Search bSDD Class"
|
bl_label = "Search bSDD Class"
|
||||||
bl_description = "Search for bSDD classes by the provided keyword"
|
bl_description = "Search for bSDD classes by the provided keyword"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
keyword = context.scene.BIMBSDDProperties.keyword
|
total = core.search_bsdd_class(tool.Bsdd, context.scene.BIMBSDDProperties.keyword)
|
||||||
classes_found = core.search_class(keyword, tool.Bsdd)
|
self.report({"INFO"}, f"{total} bSDD classes found.")
|
||||||
self.report({"INFO"}, f"{classes_found} bSDD classes found for '{keyword}'.")
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class GetBSDDClassificationProperties(bpy.types.Operator):
|
class ImportBSDDClasses(bpy.types.Operator):
|
||||||
bl_idname = "bim.get_bsdd_classification_properties"
|
bl_idname = "bim.import_bsdd_classes"
|
||||||
bl_label = "Search bSDD Class Properties"
|
bl_label = "Import bSDD Classes"
|
||||||
bl_description = "Search for bSDD class properties for the currently selected class"
|
bl_description = "Load bSDD classes that apply to the current element"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
obj: bpy.props.StringProperty()
|
||||||
|
obj_type: bpy.props.StringProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
pset_data = core.get_class_properties(tool.Bsdd)
|
props = tool.Bsdd.get_bsdd_props()
|
||||||
psets_found = len(pset_data)
|
core.import_bsdd_classes(tool.Bsdd, self.obj, self.obj_type)
|
||||||
props_found = sum(len(pset) for pset in pset_data.values())
|
self.report({"INFO"}, f"{len(props.classes)} bSDD classes found.")
|
||||||
self.report({"INFO"}, f"{psets_found} psets found ({props_found} props) for the active classification.")
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class SearchBSDDProperties(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.search_bsdd_properties"
|
||||||
|
bl_label = "Search bSDD Properties"
|
||||||
|
bl_description = "Search for bSDD properties that apply to the current element"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
obj: bpy.props.StringProperty()
|
||||||
|
obj_type: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
props = tool.Bsdd.get_bsdd_props()
|
||||||
|
core.search_bsdd_properties(tool.Bsdd, context.scene.BIMBSDDProperties.keyword, self.obj, self.obj_type)
|
||||||
|
self.report({"INFO"}, f"{len(props.properties)} bSDD properties found.")
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class AddBSDDProperties(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.add_bsdd_properties"
|
||||||
|
bl_label = "Add bSDD Properties"
|
||||||
|
bl_description = "Add selected bSDD properties"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
obj: bpy.props.StringProperty()
|
||||||
|
obj_type: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
self.file = tool.Ifc.get()
|
||||||
|
bprops = tool.Bsdd.get_bsdd_props()
|
||||||
|
|
||||||
|
psets = {}
|
||||||
|
for selected_property in bprops.selected_properties:
|
||||||
|
psets.setdefault(selected_property.metadata, {})[selected_property.name] = selected_property.get_value()
|
||||||
|
|
||||||
|
props = tool.Pset.get_pset_props(self.obj, self.obj_type)
|
||||||
|
ifc_definition_id = tool.Blender.get_obj_ifc_definition_id(self.obj, self.obj_type, context)
|
||||||
|
element = tool.Ifc.get().by_id(ifc_definition_id)
|
||||||
|
properties = {}
|
||||||
|
|
||||||
|
current_psets = ifcopenshell.util.element.get_psets(element, verbose=True)
|
||||||
|
for pset_name, properties in psets.items():
|
||||||
|
if pset := current_psets.get(pset_name, None):
|
||||||
|
pset = self.file.by_id(pset["id"])
|
||||||
|
else:
|
||||||
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name=pset_name)
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties=properties)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
import bonsai.tool as tool
|
||||||
from bpy.types import PropertyGroup
|
from bpy.types import PropertyGroup
|
||||||
from bonsai.bim.module.bsdd.data import BSDDData
|
from bonsai.bim.module.bsdd.data import BSDDData
|
||||||
from bonsai.bim.prop import Attribute, StrProperty
|
from bonsai.bim.prop import Attribute, StrProperty
|
||||||
@@ -30,6 +31,7 @@ from bpy.props import (
|
|||||||
FloatVectorProperty,
|
FloatVectorProperty,
|
||||||
CollectionProperty,
|
CollectionProperty,
|
||||||
)
|
)
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
def get_active_dictionary(self, context):
|
def get_active_dictionary(self, context):
|
||||||
@@ -42,6 +44,15 @@ def update_is_active(self: "BSDDDictionary", context: bpy.types.Context) -> None
|
|||||||
BSDDData.data["active_dictionary"] = BSDDData.active_dictionary()
|
BSDDData.data["active_dictionary"] = BSDDData.active_dictionary()
|
||||||
|
|
||||||
|
|
||||||
|
def update_is_selected(self: "BSDDProperty", context: bpy.types.Context) -> None:
|
||||||
|
tool.Bsdd.import_selected_properties()
|
||||||
|
|
||||||
|
|
||||||
|
def update_active_class_index(self: "BIMBSDDProperties", context: bpy.types.Context) -> None:
|
||||||
|
tool.Bsdd.import_class_properties()
|
||||||
|
BSDDData.data["active_dictionary"] = BSDDData.active_dictionary()
|
||||||
|
|
||||||
|
|
||||||
class BSDDDictionary(PropertyGroup):
|
class BSDDDictionary(PropertyGroup):
|
||||||
name: StringProperty(name="Name")
|
name: StringProperty(name="Name")
|
||||||
uri: StringProperty(name="URI")
|
uri: StringProperty(name="URI")
|
||||||
@@ -57,11 +68,21 @@ class BSDDDictionary(PropertyGroup):
|
|||||||
class BSDDClassification(PropertyGroup):
|
class BSDDClassification(PropertyGroup):
|
||||||
name: StringProperty(name="Name")
|
name: StringProperty(name="Name")
|
||||||
reference_code: StringProperty(name="Reference Code")
|
reference_code: StringProperty(name="Reference Code")
|
||||||
uri: StringProperty(name="Namespace URI")
|
uri: StringProperty(name="URI")
|
||||||
dictionary_name: StringProperty(name="Dictionary Name")
|
dictionary_name: StringProperty(name="Dictionary Name")
|
||||||
dictionary_namespace_uri: StringProperty(name="Dictionary Namespace URI")
|
dictionary_namespace_uri: StringProperty(name="Dictionary Namespace URI")
|
||||||
|
|
||||||
|
|
||||||
|
class BSDDProperty(PropertyGroup):
|
||||||
|
name: StringProperty(name="Name")
|
||||||
|
code: StringProperty(name="Code")
|
||||||
|
uri: StringProperty(name="URI")
|
||||||
|
pset: StringProperty(name="Pset")
|
||||||
|
is_selected: BoolProperty(
|
||||||
|
name="Is Selected", description="Select to add or edit this property", default=False, update=update_is_selected
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BSDDPset(PropertyGroup):
|
class BSDDPset(PropertyGroup):
|
||||||
name: StringProperty(name="Name")
|
name: StringProperty(name="Name")
|
||||||
properties: CollectionProperty(name="Properties", type=Attribute)
|
properties: CollectionProperty(name="Properties", type=Attribute)
|
||||||
@@ -75,6 +96,19 @@ class BIMBSDDProperties(PropertyGroup):
|
|||||||
active_dictionary_index: IntProperty(name="Active Dictionary Index")
|
active_dictionary_index: IntProperty(name="Active Dictionary Index")
|
||||||
classifications: CollectionProperty(name="Classifications", type=BSDDClassification)
|
classifications: CollectionProperty(name="Classifications", type=BSDDClassification)
|
||||||
active_classification_index: IntProperty(name="Active Classification Index")
|
active_classification_index: IntProperty(name="Active Classification Index")
|
||||||
|
property_filter_mode: EnumProperty(
|
||||||
|
name="Property Filter Mode",
|
||||||
|
items=[
|
||||||
|
("CLASS", "By Class", "Browse properties by class or group"),
|
||||||
|
("KEYWORD", "By Keyword", "Search properties directly using a keyword"),
|
||||||
|
],
|
||||||
|
default="CLASS",
|
||||||
|
)
|
||||||
|
classes: CollectionProperty(name="Classes", type=BSDDClassification)
|
||||||
|
active_class_index: IntProperty(name="Active Class Index", update=update_active_class_index)
|
||||||
|
properties: CollectionProperty(name="Properties", type=BSDDProperty)
|
||||||
|
active_property_index: IntProperty(name="Active Property Index")
|
||||||
|
selected_properties: CollectionProperty(name="Selected Properties", type=Attribute)
|
||||||
keyword: StringProperty(name="Keyword", description="Query for bsdd classes search, case and accent insensitive")
|
keyword: StringProperty(name="Keyword", description="Query for bsdd classes search, case and accent insensitive")
|
||||||
should_filter_ifc_class: BoolProperty(
|
should_filter_ifc_class: BoolProperty(
|
||||||
name="Filter Active IFC Class",
|
name="Filter Active IFC Class",
|
||||||
@@ -96,3 +130,7 @@ class BIMBSDDProperties(PropertyGroup):
|
|||||||
name="Load Test Dictionaries", description="Load dictionaries that are for testing only", default=False
|
name="Load Test Dictionaries", description="Load dictionaries that are for testing only", default=False
|
||||||
)
|
)
|
||||||
classification_psets: CollectionProperty(name="Classification Psets", type=BSDDPset)
|
classification_psets: CollectionProperty(name="Classification Psets", type=BSDDPset)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def active_class(self) -> Union[BSDDClassification, None]:
|
||||||
|
return tool.Blender.get_active_uilist_element(self.classes, self.active_class_index)
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class BIM_PT_bsdd(Panel):
|
|||||||
selected_dictionary = None
|
selected_dictionary = None
|
||||||
|
|
||||||
if selected_dictionary:
|
if selected_dictionary:
|
||||||
layout.label(text="Selected dictionary:")
|
layout.label(text="Selected Dictionary:")
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
row.label(text="Language")
|
row.label(text="Language")
|
||||||
@@ -92,3 +92,22 @@ class BIM_UL_bsdd_classifications(UIList):
|
|||||||
row.label(text=item.reference_code)
|
row.label(text=item.reference_code)
|
||||||
row.label(text=item.name)
|
row.label(text=item.name)
|
||||||
row.operator("bim.open_uri", text="", icon="URL").uri = item.uri
|
row.operator("bim.open_uri", text="", icon="URL").uri = item.uri
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_UL_bsdd_classes(UIList):
|
||||||
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
|
if item:
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.label(text=item.name)
|
||||||
|
row.operator("bim.open_uri", text="", icon="URL").uri = item.uri
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_UL_bsdd_properties(UIList):
|
||||||
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
|
if item:
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.label(text=item.name)
|
||||||
|
if item.pset:
|
||||||
|
row.label(text=item.pset)
|
||||||
|
row.operator("bim.open_uri", text="", icon="URL").uri = item.uri
|
||||||
|
row.prop(item, "is_selected", icon="CHECKBOX_HLT" if item.is_selected else "CHECKBOX_DEHLT", text="", emboss=False)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class ClassificationsData:
|
|||||||
cls.data["has_classification_file"] = cls.has_classification_file()
|
cls.data["has_classification_file"] = cls.has_classification_file()
|
||||||
cls.data["classifications"] = cls.classifications()
|
cls.data["classifications"] = cls.classifications()
|
||||||
cls.data["available_classifications"] = cls.available_classifications()
|
cls.data["available_classifications"] = cls.available_classifications()
|
||||||
|
cls.data["classification_source"] = cls.classification_source()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def has_classification_file(cls):
|
def has_classification_file(cls):
|
||||||
@@ -62,6 +63,19 @@ class ClassificationsData:
|
|||||||
return []
|
return []
|
||||||
return [(str(e.id()), e.Name, "") for e in IfcStore.classification_file.by_type("IfcClassification")]
|
return [(str(e.id()), e.Name, "") for e in IfcStore.classification_file.by_type("IfcClassification")]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def classification_source(cls):
|
||||||
|
items = [
|
||||||
|
("FILE", "IFC File", ""),
|
||||||
|
("MANUAL", "Manual Entry", ""),
|
||||||
|
]
|
||||||
|
bprops = tool.Bsdd.get_bsdd_props()
|
||||||
|
dictionaries = [(d.uri, f"bSDD: {d.name}", "") for d in bprops.dictionaries if d.is_active]
|
||||||
|
if dictionaries:
|
||||||
|
items.append(("BSDD", "All Active bSDDs", ""))
|
||||||
|
items.extend(dictionaries)
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
class ReferencesData:
|
class ReferencesData:
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -115,11 +115,12 @@ class AddClassificationFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = context.scene.BIMBSDDProperties
|
cprops = context.scene.BIMClassificationProperties
|
||||||
if props.active_dictionary == "ALL":
|
bprops = tool.Bsdd.get_bsdd_props()
|
||||||
dictionaries = [d.uri for d in props.dictionaries if d.is_active]
|
if cprops.classification_source == "BSDD":
|
||||||
|
dictionaries = [d.uri for d in bprops.dictionaries if d.is_active]
|
||||||
else:
|
else:
|
||||||
dictionaries = [props.active_dictionary]
|
dictionaries = [cprops.classification_source]
|
||||||
for uri in dictionaries:
|
for uri in dictionaries:
|
||||||
if not (dictionary := tool.Bsdd.get_dictionary(uri)):
|
if not (dictionary := tool.Bsdd.get_dictionary(uri)):
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ def get_classifications(self, context):
|
|||||||
return ClassificationReferencesData.data["classifications"]
|
return ClassificationReferencesData.data["classifications"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_classification_source(self, context):
|
||||||
|
if not ClassificationsData.is_loaded:
|
||||||
|
ClassificationsData.load()
|
||||||
|
return ClassificationsData.data["classification_source"]
|
||||||
|
|
||||||
|
|
||||||
class ClassificationReference(PropertyGroup):
|
class ClassificationReference(PropertyGroup):
|
||||||
name: StringProperty(name="Name")
|
name: StringProperty(name="Name")
|
||||||
identification: StringProperty(name="Identification")
|
identification: StringProperty(name="Identification")
|
||||||
@@ -54,15 +60,7 @@ class ClassificationReference(PropertyGroup):
|
|||||||
|
|
||||||
class BIMClassificationProperties(PropertyGroup):
|
class BIMClassificationProperties(PropertyGroup):
|
||||||
is_adding: BoolProperty(name="Is Adding", default=False)
|
is_adding: BoolProperty(name="Is Adding", default=False)
|
||||||
classification_source: EnumProperty(
|
classification_source: EnumProperty(items=get_classification_source, name="Classification Source")
|
||||||
items=[
|
|
||||||
("FILE", "IFC File", ""),
|
|
||||||
("BSDD", "buildingSMART Data Dictionary", ""),
|
|
||||||
("MANUAL", "Manual Entry", ""),
|
|
||||||
],
|
|
||||||
name="Classification Source",
|
|
||||||
default="FILE",
|
|
||||||
)
|
|
||||||
available_classifications: EnumProperty(items=get_available_classifications, name="Available Classifications")
|
available_classifications: EnumProperty(items=get_available_classifications, name="Available Classifications")
|
||||||
classification_attributes: CollectionProperty(name="Classification Attributes", type=Attribute)
|
classification_attributes: CollectionProperty(name="Classification Attributes", type=Attribute)
|
||||||
active_classification_id: IntProperty(name="Active Classification Id")
|
active_classification_id: IntProperty(name="Active Classification Id")
|
||||||
|
|||||||
@@ -54,10 +54,10 @@ class BIM_PT_classifications(Panel):
|
|||||||
|
|
||||||
if self.props.classification_source == "FILE":
|
if self.props.classification_source == "FILE":
|
||||||
self.draw_add_file_ui(context)
|
self.draw_add_file_ui(context)
|
||||||
elif self.props.classification_source == "BSDD":
|
|
||||||
self.draw_add_bsdd_ui(context)
|
|
||||||
elif self.props.classification_source == "MANUAL":
|
elif self.props.classification_source == "MANUAL":
|
||||||
self.draw_add_manual_ui(context)
|
self.draw_add_manual_ui(context)
|
||||||
|
else:
|
||||||
|
self.draw_add_bsdd_ui(context)
|
||||||
|
|
||||||
for classification in ClassificationsData.data["classifications"]:
|
for classification in ClassificationsData.data["classifications"]:
|
||||||
if self.props.active_classification_id == classification["id"]:
|
if self.props.active_classification_id == classification["id"]:
|
||||||
@@ -76,11 +76,6 @@ class BIM_PT_classifications(Panel):
|
|||||||
row.operator("bim.enable_adding_manual_classification", text="Add Classification", icon="ADD")
|
row.operator("bim.enable_adding_manual_classification", text="Add Classification", icon="ADD")
|
||||||
|
|
||||||
def draw_add_bsdd_ui(self, context):
|
def draw_add_bsdd_ui(self, context):
|
||||||
self.bprops = context.scene.BIMBSDDProperties
|
|
||||||
|
|
||||||
row = self.layout.row()
|
|
||||||
row.prop(self.bprops, "active_dictionary", text="")
|
|
||||||
|
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.operator("bim.add_classification_from_bsdd", icon="ADD")
|
row.operator("bim.add_classification_from_bsdd", icon="ADD")
|
||||||
|
|
||||||
@@ -139,10 +134,10 @@ class ReferenceUI:
|
|||||||
|
|
||||||
if self.sprops.classification_source == "FILE":
|
if self.sprops.classification_source == "FILE":
|
||||||
self.draw_add_file_ui(context)
|
self.draw_add_file_ui(context)
|
||||||
elif self.sprops.classification_source == "BSDD":
|
|
||||||
self.draw_add_bsdd_ui(context)
|
|
||||||
elif self.sprops.classification_source == "MANUAL":
|
elif self.sprops.classification_source == "MANUAL":
|
||||||
self.draw_add_manual_ui(context)
|
self.draw_add_manual_ui(context)
|
||||||
|
else:
|
||||||
|
self.draw_add_bsdd_ui(context)
|
||||||
|
|
||||||
def draw_add_manual_ui(self, context):
|
def draw_add_manual_ui(self, context):
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
@@ -158,17 +153,11 @@ class ReferenceUI:
|
|||||||
row.operator("bim.enable_adding_manual_classification_reference", text="Add Reference", icon="ADD")
|
row.operator("bim.enable_adding_manual_classification_reference", text="Add Reference", icon="ADD")
|
||||||
|
|
||||||
def draw_add_bsdd_ui(self, context):
|
def draw_add_bsdd_ui(self, context):
|
||||||
row = self.layout.row()
|
|
||||||
row.prop(self.bprops, "active_dictionary", text="")
|
|
||||||
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.prop(self.bprops, "keyword", text="")
|
row.prop(self.bprops, "keyword", text="")
|
||||||
|
row.prop(self.bprops, "should_filter_ifc_class", text="", icon="FILTER")
|
||||||
row.operator("bim.search_bsdd_classifications", text="", icon="VIEWZOOM")
|
row.operator("bim.search_bsdd_classifications", text="", icon="VIEWZOOM")
|
||||||
|
|
||||||
row = self.layout.row()
|
|
||||||
row.prop(self.bprops, "should_filter_ifc_class")
|
|
||||||
row.prop(self.bprops, "use_only_ifc_properties")
|
|
||||||
|
|
||||||
if len(self.bprops.classifications):
|
if len(self.bprops.classifications):
|
||||||
self.layout.template_list(
|
self.layout.template_list(
|
||||||
"BIM_UL_bsdd_classifications",
|
"BIM_UL_bsdd_classifications",
|
||||||
@@ -189,21 +178,6 @@ class ReferenceUI:
|
|||||||
)
|
)
|
||||||
op.obj = self.obj
|
op.obj = self.obj
|
||||||
op.obj_type = self.obj_type
|
op.obj_type = self.obj_type
|
||||||
row.operator("bim.get_bsdd_classification_properties", text="", icon="COPY_ID")
|
|
||||||
|
|
||||||
if len(self.bprops.classification_psets):
|
|
||||||
use_only_ifc_properties = self.bprops.use_only_ifc_properties
|
|
||||||
for pset in self.bprops.classification_psets:
|
|
||||||
properties = pset.properties
|
|
||||||
if use_only_ifc_properties:
|
|
||||||
properties = [p for p in properties if p.metadata == "IFC"]
|
|
||||||
if not properties:
|
|
||||||
continue
|
|
||||||
|
|
||||||
box = self.layout.box()
|
|
||||||
row = box.row()
|
|
||||||
row.label(text=pset.name, icon="COPY_ID")
|
|
||||||
bonsai.bim.helper.draw_attributes(properties, box)
|
|
||||||
|
|
||||||
def draw_add_file_ui(self, context):
|
def draw_add_file_ui(self, context):
|
||||||
if not self.data.data["active_classification_library"]:
|
if not self.data.data["active_classification_library"]:
|
||||||
|
|||||||
@@ -81,7 +81,24 @@ def get_pset_name(self, context):
|
|||||||
results = get_profile_pset_names(self, context)
|
results = get_profile_pset_names(self, context)
|
||||||
elif prop_type == "WorkSchedulePsetProperties":
|
elif prop_type == "WorkSchedulePsetProperties":
|
||||||
results = get_work_schedule_pset_names(self, context)
|
results = get_work_schedule_pset_names(self, context)
|
||||||
return [("BBIM_CUSTOM", "Custom Pset", "Create a property set without using a template."), None] + results
|
items = [("BBIM_CUSTOM", "Custom Pset", "Create a property set without using a template.")]
|
||||||
|
bprops = tool.Bsdd.get_bsdd_props()
|
||||||
|
dictionaries = [(d.uri, f"bSDD: {d.name}", "") for d in bprops.dictionaries if d.is_active]
|
||||||
|
if dictionaries:
|
||||||
|
items.extend(
|
||||||
|
[
|
||||||
|
None,
|
||||||
|
(
|
||||||
|
"BBIM_BSDD",
|
||||||
|
"All Data Dictionaries",
|
||||||
|
"Manage properties from all active buildingSMART Data Dictionaries",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
items.extend(dictionaries)
|
||||||
|
items.append(None)
|
||||||
|
items.extend(results)
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
def get_object_pset_name(self, context):
|
def get_object_pset_name(self, context):
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from __future__ import annotations
|
|||||||
import bpy
|
import bpy
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from bpy.types import Panel
|
from bpy.types import Panel
|
||||||
from bonsai.bim.helper import prop_with_search, get_display_value
|
from bonsai.bim.helper import prop_with_search, get_display_value, draw_attribute
|
||||||
from bonsai.bim.module.pset.data import (
|
from bonsai.bim.module.pset.data import (
|
||||||
ObjectPsetsData,
|
ObjectPsetsData,
|
||||||
ObjectQtosData,
|
ObjectQtosData,
|
||||||
@@ -256,11 +256,74 @@ class BIM_PT_object_psets(Panel):
|
|||||||
ObjectPsetsData.load()
|
ObjectPsetsData.load()
|
||||||
|
|
||||||
props = context.active_object.PsetProperties
|
props = context.active_object.PsetProperties
|
||||||
|
self.bprops = context.scene.BIMBSDDProperties
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
prop_with_search(row, props, "pset_name", text="")
|
prop_with_search(row, props, "pset_name", text="")
|
||||||
op = row.operator("bim.add_pset", icon="ADD", text="")
|
if props.pset_name != "BBIM_BSDD" and not props.pset_name.startswith(tool.Bsdd.identifier_url):
|
||||||
op.obj = context.active_object.name
|
op = row.operator("bim.add_pset", icon="ADD", text="")
|
||||||
op.obj_type = "Object"
|
op.obj = context.active_object.name
|
||||||
|
op.obj_type = "Object"
|
||||||
|
else:
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.prop(self.bprops, "property_filter_mode", text="")
|
||||||
|
if self.bprops.property_filter_mode == "CLASS":
|
||||||
|
row.prop(self.bprops, "should_filter_ifc_class", text="", icon="FILTER")
|
||||||
|
op = row.operator("bim.import_bsdd_classes", text="", icon="FILE_REFRESH")
|
||||||
|
op.obj = context.active_object.name
|
||||||
|
op.obj_type = "Object"
|
||||||
|
|
||||||
|
if len(self.bprops.classes):
|
||||||
|
self.layout.template_list(
|
||||||
|
"BIM_UL_bsdd_classes",
|
||||||
|
"",
|
||||||
|
self.bprops,
|
||||||
|
"classes",
|
||||||
|
self.bprops,
|
||||||
|
"active_class_index",
|
||||||
|
)
|
||||||
|
if len(self.bprops.properties):
|
||||||
|
self.layout.template_list(
|
||||||
|
"BIM_UL_bsdd_properties",
|
||||||
|
"",
|
||||||
|
self.bprops,
|
||||||
|
"properties",
|
||||||
|
self.bprops,
|
||||||
|
"active_property_index",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
row = self.layout.row()
|
||||||
|
row.label(text="No Results")
|
||||||
|
else:
|
||||||
|
row = self.layout.row()
|
||||||
|
row.label(text="No Results")
|
||||||
|
elif self.bprops.property_filter_mode == "KEYWORD":
|
||||||
|
row.prop(self.bprops, "keyword", text="")
|
||||||
|
op = row.operator("bim.search_bsdd_properties", text="", icon="VIEWZOOM")
|
||||||
|
op.obj = context.active_object.name
|
||||||
|
op.obj_type = "Object"
|
||||||
|
|
||||||
|
if len(self.bprops.properties):
|
||||||
|
self.layout.template_list(
|
||||||
|
"BIM_UL_bsdd_properties",
|
||||||
|
"",
|
||||||
|
self.bprops,
|
||||||
|
"properties",
|
||||||
|
self.bprops,
|
||||||
|
"active_property_index",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
row = self.layout.row()
|
||||||
|
row.label(text="No Results")
|
||||||
|
|
||||||
|
for selected_property in self.bprops.selected_properties:
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
# row.prop(selected_property, "metadata", text="")
|
||||||
|
draw_attribute(selected_property, row)
|
||||||
|
|
||||||
|
row = self.layout.row()
|
||||||
|
op = row.operator("bim.add_bsdd_properties", icon="ADD")
|
||||||
|
op.obj = context.active_object.name
|
||||||
|
op.obj_type = "Object"
|
||||||
|
|
||||||
global_props = tool.Pset.get_global_pset_props()
|
global_props = tool.Pset.get_global_pset_props()
|
||||||
if not props.active_pset_id and props.active_pset_name and props.active_pset_type == "PSET":
|
if not props.active_pset_id and props.active_pset_name and props.active_pset_type == "PSET":
|
||||||
|
|||||||
@@ -26,14 +26,12 @@ if TYPE_CHECKING:
|
|||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
|
|
||||||
|
|
||||||
def get_class_properties(bsdd: tool.Bsdd) -> dict[str, dict[str, Any]]:
|
def import_bsdd_classes(bsdd: tool.Bsdd, obj, obj_type) -> int:
|
||||||
bsdd.clear_class_psets()
|
return bsdd.import_classes(obj, obj_type)
|
||||||
data = bsdd.get_active_class_data()
|
|
||||||
pset_dict = bsdd.get_property_dict(data)
|
|
||||||
if pset_dict is None:
|
def search_bsdd_properties(bsdd: tool.Bsdd, keyword: str, obj, obj_type) -> int:
|
||||||
return {}
|
return bsdd.import_properties(obj, obj_type, keyword)
|
||||||
bsdd.create_class_psets(pset_dict)
|
|
||||||
return pset_dict
|
|
||||||
|
|
||||||
|
|
||||||
def load_bsdd(bsdd: tool.Bsdd) -> None:
|
def load_bsdd(bsdd: tool.Bsdd) -> None:
|
||||||
@@ -41,7 +39,7 @@ def load_bsdd(bsdd: tool.Bsdd) -> None:
|
|||||||
bsdd.create_dictionaries(bsdd.get_dictionaries())
|
bsdd.create_dictionaries(bsdd.get_dictionaries())
|
||||||
|
|
||||||
|
|
||||||
def search_class(keyword: str, bsdd: tool.Bsdd) -> int:
|
def search_bsdd_class(bsdd: tool.Bsdd, keyword: str) -> int:
|
||||||
bsdd.clear_classes()
|
bsdd.clear_classes()
|
||||||
related_entities = bsdd.get_related_ifc_entities()
|
related_entities = bsdd.get_related_ifc_entities()
|
||||||
return bsdd.search_class(keyword, related_entities)
|
return bsdd.search_class(keyword, related_entities)
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ import json
|
|||||||
import bsdd
|
import bsdd
|
||||||
import ifcopenshell.util.type
|
import ifcopenshell.util.type
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
import ifcopenshell.util.classification
|
||||||
from typing import Any, Union, Optional, TYPE_CHECKING
|
from typing import Any, Union, Optional, TYPE_CHECKING
|
||||||
|
|
||||||
|
|
||||||
class Bsdd(bonsai.core.tool.Bsdd):
|
class Bsdd(bonsai.core.tool.Bsdd):
|
||||||
|
identifier_url = "https://identifier.buildingsmart.org"
|
||||||
client = bsdd.Client()
|
client = bsdd.Client()
|
||||||
|
bsdd_classes: dict[str, dict] = {}
|
||||||
|
bsdd_properties: dict[str, dict] = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_bsdd_props(cls):
|
def get_bsdd_props(cls):
|
||||||
@@ -23,6 +27,10 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
|||||||
def clear_classes(cls) -> None:
|
def clear_classes(cls) -> None:
|
||||||
bpy.context.scene.BIMBSDDProperties.classifications.clear()
|
bpy.context.scene.BIMBSDDProperties.classifications.clear()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def clear_properties(cls) -> None:
|
||||||
|
bpy.context.scene.BIMBSDDProperties.properties.clear()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_dictionaries(cls) -> None:
|
def clear_dictionaries(cls) -> None:
|
||||||
bpy.context.scene.BIMBSDDProperties.dictionaries.clear()
|
bpy.context.scene.BIMBSDDProperties.dictionaries.clear()
|
||||||
@@ -94,10 +102,12 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
|||||||
return list(filter(lambda d: d["status"] in statuses, dicts))
|
return list(filter(lambda d: d["status"] in statuses, dicts))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_property_dict(cls, class_data: Union[bsdd.ClassContractV1, dict]) -> Union[dict[str, dict[str, Any]], None]:
|
def get_class_properties(
|
||||||
|
cls, class_data: Union[bsdd.ClassContractV1, dict]
|
||||||
|
) -> Union[dict[str, dict[str, Any]], None]:
|
||||||
properties = class_data.get("classProperties", None)
|
properties = class_data.get("classProperties", None)
|
||||||
if not properties:
|
if not properties:
|
||||||
return None
|
return {}
|
||||||
|
|
||||||
ifc_class = class_data.get("relatedIfcEntityNames") or ""
|
ifc_class = class_data.get("relatedIfcEntityNames") or ""
|
||||||
if ifc_class:
|
if ifc_class:
|
||||||
@@ -155,11 +165,12 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
|||||||
limit: int = 100,
|
limit: int = 100,
|
||||||
should_paginate: bool = True,
|
should_paginate: bool = True,
|
||||||
):
|
):
|
||||||
props = cls.get_bsdd_props()
|
cprops = bpy.context.scene.BIMClassificationProperties
|
||||||
|
bprops = cls.get_bsdd_props()
|
||||||
dictionary_uris = (
|
dictionary_uris = (
|
||||||
[d.uri for d in props.dictionaries if d.is_active]
|
[d.uri for d in bprops.dictionaries if d.is_active]
|
||||||
if props.active_dictionary == "ALL"
|
if cprops.classification_source == "BSDD"
|
||||||
else [props.active_dictionary]
|
else [cprops.classification_source]
|
||||||
)
|
)
|
||||||
for dictionary_uri in dictionary_uris:
|
for dictionary_uri in dictionary_uris:
|
||||||
for related_ifc_entity in related_ifc_entities or [None]:
|
for related_ifc_entity in related_ifc_entities or [None]:
|
||||||
@@ -174,7 +185,7 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
|||||||
dictionary_name = response.get("name", "")
|
dictionary_name = response.get("name", "")
|
||||||
dictionary_namespace_uri = response.get("uri", "")
|
dictionary_namespace_uri = response.get("uri", "")
|
||||||
for _class in sorted(response.get("classes", []), key=lambda c: c["referenceCode"]):
|
for _class in sorted(response.get("classes", []), key=lambda c: c["referenceCode"]):
|
||||||
prop = props.classifications.add()
|
prop = bprops.classifications.add()
|
||||||
prop.name = _class["name"]
|
prop.name = _class["name"]
|
||||||
prop.reference_code = _class["referenceCode"]
|
prop.reference_code = _class["referenceCode"]
|
||||||
prop.uri = _class["uri"]
|
prop.uri = _class["uri"]
|
||||||
@@ -198,3 +209,159 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def should_filter_ifc_class(cls) -> bool:
|
def should_filter_ifc_class(cls) -> bool:
|
||||||
return bpy.context.scene.BIMBSDDProperties.should_filter_ifc_class
|
return bpy.context.scene.BIMBSDDProperties.should_filter_ifc_class
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_bsdd_class(cls, uri: str) -> dict:
|
||||||
|
if not (bsdd_class := cls.bsdd_classes.get(uri, {})):
|
||||||
|
bsdd_class = cls.client.get_class(uri)
|
||||||
|
cls.bsdd_classes[uri] = bsdd_class
|
||||||
|
return bsdd_class
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_bsdd_property(cls, uri: str) -> dict:
|
||||||
|
if not (bsdd_property := cls.bsdd_properties.get(uri, {})):
|
||||||
|
bsdd_property = cls.client.get_property(uri, include_classes=True)
|
||||||
|
cls.bsdd_properties[uri] = bsdd_property
|
||||||
|
return bsdd_property
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def import_classes(cls, obj, obj_type) -> None:
|
||||||
|
pprops = tool.Pset.get_pset_props(obj, obj_type)
|
||||||
|
props = cls.get_bsdd_props()
|
||||||
|
props.classes.clear()
|
||||||
|
|
||||||
|
classes = set()
|
||||||
|
for obj in tool.Blender.get_selected_objects(include_active=True):
|
||||||
|
if element := tool.Ifc.get_entity(obj):
|
||||||
|
for reference in ifcopenshell.util.classification.get_references(element):
|
||||||
|
if (uri := reference.Location) and uri.startswith(cls.identifier_url):
|
||||||
|
classes.add((reference[1] or reference[2] or "Unnamed", uri))
|
||||||
|
|
||||||
|
dictionary_uris = (
|
||||||
|
[d.uri for d in props.dictionaries if d.is_active]
|
||||||
|
if pprops.pset_name == "BBIM_BSDD"
|
||||||
|
else [pprops.pset_name]
|
||||||
|
)
|
||||||
|
related_ifc_entities = cls.get_related_ifc_entities()
|
||||||
|
for dictionary_uri in dictionary_uris:
|
||||||
|
for related_ifc_entity in related_ifc_entities or [None]:
|
||||||
|
bsdd_classes = cls.client.get_classes(
|
||||||
|
dictionary_uri=dictionary_uri,
|
||||||
|
class_type="GroupOfProperties",
|
||||||
|
use_nested_classes=False,
|
||||||
|
related_ifc_entity=related_ifc_entity,
|
||||||
|
)
|
||||||
|
for bsdd_class in bsdd_classes["classes"]:
|
||||||
|
classes.add((bsdd_class["name"], bsdd_class["uri"]))
|
||||||
|
|
||||||
|
for bsdd_class in classes:
|
||||||
|
new = props.classes.add()
|
||||||
|
new.name = bsdd_class[0]
|
||||||
|
new.uri = bsdd_class[1]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def import_class_properties(cls) -> None:
|
||||||
|
props = cls.get_bsdd_props()
|
||||||
|
props.properties.clear()
|
||||||
|
if not (active_class := props.active_class):
|
||||||
|
return
|
||||||
|
if not (bsdd_class := cls.get_bsdd_class(active_class.uri)):
|
||||||
|
return
|
||||||
|
for bsdd_prop in bsdd_class.get("classProperties", []):
|
||||||
|
if not bsdd_prop.get("propertySet", None):
|
||||||
|
continue
|
||||||
|
cls.bsdd_properties[bsdd_prop["uri"]] = bsdd_prop
|
||||||
|
new = props.properties.add()
|
||||||
|
new.name = bsdd_prop["name"]
|
||||||
|
new.pset = bsdd_prop["propertySet"]
|
||||||
|
new.uri = bsdd_prop["uri"]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def import_properties(cls, obj, obj_type, keyword) -> None:
|
||||||
|
props = cls.get_bsdd_props()
|
||||||
|
props.properties.clear()
|
||||||
|
pprops = tool.Pset.get_pset_props(obj, obj_type)
|
||||||
|
dictionary_uris = (
|
||||||
|
[d.uri for d in props.dictionaries if d.is_active]
|
||||||
|
if pprops.pset_name == "BBIM_BSDD"
|
||||||
|
else [pprops.pset_name]
|
||||||
|
)
|
||||||
|
for dictionary_uri in dictionary_uris:
|
||||||
|
for bsdd_prop in cls.client.get_properties(dictionary_uri, keyword)["properties"]:
|
||||||
|
new = props.properties.add()
|
||||||
|
new.name = bsdd_prop["name"]
|
||||||
|
new.uri = bsdd_prop["uri"]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def import_selected_properties(cls) -> None:
|
||||||
|
props = cls.get_bsdd_props()
|
||||||
|
data_type_map = {
|
||||||
|
"String": "string",
|
||||||
|
"Real": "float",
|
||||||
|
"Boolean": "boolean",
|
||||||
|
}
|
||||||
|
imported_props = set()
|
||||||
|
for bsdd_prop in props.properties:
|
||||||
|
if not bsdd_prop.is_selected:
|
||||||
|
continue
|
||||||
|
if not (pset_name := bsdd_prop.pset):
|
||||||
|
prop_data = cls.get_bsdd_property(bsdd_prop.uri)
|
||||||
|
pset_name = prop_data.get("propertyClasses", [{}])[0].get("propertySet", "")
|
||||||
|
|
||||||
|
imported_props.add((pset_name, bsdd_prop.name))
|
||||||
|
if (
|
||||||
|
selected_property := props.selected_properties.get(bsdd_prop.name)
|
||||||
|
) and selected_property.metadata == pset_name:
|
||||||
|
continue
|
||||||
|
|
||||||
|
data = cls.bsdd_properties[bsdd_prop.uri]
|
||||||
|
|
||||||
|
predefined_value = data.get("predefinedValue")
|
||||||
|
if predefined_value:
|
||||||
|
possible_values = [predefined_value]
|
||||||
|
else:
|
||||||
|
possible_values = data.get("allowedValues", []) or []
|
||||||
|
possible_values = [v["value"] for v in possible_values]
|
||||||
|
|
||||||
|
new = props.selected_properties.add()
|
||||||
|
new.name = bsdd_prop.name
|
||||||
|
if possible_values:
|
||||||
|
new.enum_items = json.dumps(possible_values)
|
||||||
|
new.data_type = "enum"
|
||||||
|
else:
|
||||||
|
new.data_type = data_type_map.get(data["dataType"], "string")
|
||||||
|
new.description = data.get("description", "")
|
||||||
|
new.metadata = pset_name
|
||||||
|
|
||||||
|
to_remove = []
|
||||||
|
for i, selected_property in enumerate(props.selected_properties):
|
||||||
|
if (selected_property.metadata, selected_property.name) not in imported_props:
|
||||||
|
to_remove.append(i)
|
||||||
|
|
||||||
|
for i in to_remove[::-1]:
|
||||||
|
props.selected_properties.remove(i)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_applicable_psets(cls, element: ifcopenshell.entity_instance):
|
||||||
|
uris = set()
|
||||||
|
for reference in ifcopenshell.util.classification.get_references(element):
|
||||||
|
if (uri := reference.Location) and uri.startswith(cls.identifier_url):
|
||||||
|
uris.add(uri)
|
||||||
|
psets = set()
|
||||||
|
for uri in uris:
|
||||||
|
if not (bsdd_class := cls.bsdd_classes.get(uri, None)):
|
||||||
|
continue
|
||||||
|
for class_pset in bsdd_class.get("classProperties", []):
|
||||||
|
if not (pset_name := class_pset.get("propertySet", None)):
|
||||||
|
continue
|
||||||
|
psets.add((uri, bsdd_class["name"], pset_name))
|
||||||
|
return psets
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_applicable(cls, pset_uri: str, element: ifcopenshell.entity_instance) -> bool:
|
||||||
|
uris = set()
|
||||||
|
for reference in ifcopenshell.util.classification.get_references(element):
|
||||||
|
if (uri := reference.Location) and uri.startswith(cls.identifier_url):
|
||||||
|
uris.add(uri)
|
||||||
|
class_uri, pset_name = pset_uri.rsplit("#", 1)
|
||||||
|
return class_uri in uris
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class Pset(bonsai.core.tool.Pset):
|
|||||||
def get_pset_name(cls, obj: str, obj_type: tool.Ifc.OBJECT_TYPE, pset_type: PSET_TYPE = "PSET") -> str:
|
def get_pset_name(cls, obj: str, obj_type: tool.Ifc.OBJECT_TYPE, pset_type: PSET_TYPE = "PSET") -> str:
|
||||||
props = cls.get_pset_props(obj, obj_type)
|
props = cls.get_pset_props(obj, obj_type)
|
||||||
name = props.pset_name if pset_type == "PSET" else props.qto_name
|
name = props.pset_name if pset_type == "PSET" else props.qto_name
|
||||||
if name == "BBIM_CUSTOM":
|
if name in ("BBIM_CUSTOM", "BBIM_BSDD"):
|
||||||
return ""
|
return ""
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|||||||
+14
-2
@@ -658,13 +658,25 @@ class Client:
|
|||||||
return self.get(endpoint, params)
|
return self.get(endpoint, params)
|
||||||
|
|
||||||
def get_properties(
|
def get_properties(
|
||||||
self, dictionary_uri: str, offset: int = 0, limit: int = 100, language_code: str = "", version: int = 1
|
self,
|
||||||
|
dictionary_uri: str,
|
||||||
|
search_text: str = "",
|
||||||
|
offset: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
language_code: str = "",
|
||||||
|
version: int = 1,
|
||||||
) -> DictionaryPropertiesResponseContractV1:
|
) -> DictionaryPropertiesResponseContractV1:
|
||||||
"""
|
"""
|
||||||
Get Dictionary with its properties
|
Get Dictionary with its properties
|
||||||
"""
|
"""
|
||||||
endpoint = f"Dictionary/v{version}/Properties"
|
endpoint = f"Dictionary/v{version}/Properties"
|
||||||
params = {"Uri": dictionary_uri, "languageCode": language_code, "offset": offset, "limit": limit}
|
params = {
|
||||||
|
"Uri": dictionary_uri,
|
||||||
|
"SearchText": search_text,
|
||||||
|
"languageCode": language_code,
|
||||||
|
"offset": offset,
|
||||||
|
"limit": limit,
|
||||||
|
}
|
||||||
return self.get(endpoint, params)
|
return self.get(endpoint, params)
|
||||||
|
|
||||||
def get_class(
|
def get_class(
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ from typing import Optional
|
|||||||
|
|
||||||
|
|
||||||
def get_references(element: ifcopenshell.entity_instance, should_inherit=True) -> set[ifcopenshell.entity_instance]:
|
def get_references(element: ifcopenshell.entity_instance, should_inherit=True) -> set[ifcopenshell.entity_instance]:
|
||||||
|
"""Gets classification references associated with the element
|
||||||
|
|
||||||
|
:param should_inherit: If true, classification references are inherited
|
||||||
|
from the type. Classifications can be overriden per system.
|
||||||
|
:return: A set of IfcClassificationReference
|
||||||
|
"""
|
||||||
results = set()
|
results = set()
|
||||||
if not element.is_a("IfcRoot"):
|
if not element.is_a("IfcRoot"):
|
||||||
if (references := getattr(element, "HasExternalReferences", None)) is not None or (
|
if (references := getattr(element, "HasExternalReferences", None)) is not None or (
|
||||||
@@ -52,6 +58,11 @@ def get_references(element: ifcopenshell.entity_instance, should_inherit=True) -
|
|||||||
|
|
||||||
|
|
||||||
def get_classification(reference: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
def get_classification(reference: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||||
|
"""Get the IfcClassification that a classification reference belongs to
|
||||||
|
|
||||||
|
:param reference: An IfcClassificationReference
|
||||||
|
:return: IfcClassification
|
||||||
|
"""
|
||||||
if reference.is_a("IfcClassification"):
|
if reference.is_a("IfcClassification"):
|
||||||
return reference
|
return reference
|
||||||
return get_classification(reference.ReferencedSource) if reference.ReferencedSource is not None else None
|
return get_classification(reference.ReferencedSource) if reference.ReferencedSource is not None else None
|
||||||
|
|||||||
Reference in New Issue
Block a user