mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 18:57:17 +00:00
New hierarchical classification navigator, reading class data from IFCs. Thanks to Lucyon Oak (Teck-Freak)
This commit is contained in:
@@ -72,9 +72,12 @@ if bpy is not None:
|
|||||||
operator.EditAggregate,
|
operator.EditAggregate,
|
||||||
operator.SaveAggregate,
|
operator.SaveAggregate,
|
||||||
operator.ExplodeAggregate,
|
operator.ExplodeAggregate,
|
||||||
|
operator.LoadClassification,
|
||||||
|
operator.AddClassification,
|
||||||
|
operator.RemoveClassification,
|
||||||
operator.AssignClassification,
|
operator.AssignClassification,
|
||||||
operator.UnassignClassification,
|
operator.UnassignClassification,
|
||||||
operator.RemoveClassification,
|
operator.RemoveClassificationReference,
|
||||||
operator.FetchLibraryInformation,
|
operator.FetchLibraryInformation,
|
||||||
operator.FetchExternalMaterial,
|
operator.FetchExternalMaterial,
|
||||||
operator.FetchObjectPassport,
|
operator.FetchObjectPassport,
|
||||||
@@ -95,6 +98,11 @@ if bpy is not None:
|
|||||||
operator.SetViewPreset1,
|
operator.SetViewPreset1,
|
||||||
operator.OpenUpstream,
|
operator.OpenUpstream,
|
||||||
operator.BIM_OT_CopyAttributesToSelection,
|
operator.BIM_OT_CopyAttributesToSelection,
|
||||||
|
operator.BIM_OT_ChangeClassificationLevel,
|
||||||
|
prop.StrProperty,
|
||||||
|
prop.Classification,
|
||||||
|
prop.ClassificationReference,
|
||||||
|
prop.ClassificationView,
|
||||||
prop.BcfTopic,
|
prop.BcfTopic,
|
||||||
prop.BcfTopicLabel,
|
prop.BcfTopicLabel,
|
||||||
prop.BcfTopicFile,
|
prop.BcfTopicFile,
|
||||||
@@ -112,7 +120,6 @@ if bpy is not None:
|
|||||||
prop.BoundaryCondition,
|
prop.BoundaryCondition,
|
||||||
prop.PsetQto,
|
prop.PsetQto,
|
||||||
prop.Document,
|
prop.Document,
|
||||||
prop.Classification,
|
|
||||||
prop.GlobalId,
|
prop.GlobalId,
|
||||||
prop.BIMObjectProperties,
|
prop.BIMObjectProperties,
|
||||||
prop.BIMMaterialProperties,
|
prop.BIMMaterialProperties,
|
||||||
@@ -121,6 +128,7 @@ if bpy is not None:
|
|||||||
prop.BIMCameraProperties,
|
prop.BIMCameraProperties,
|
||||||
ui.BIM_PT_documentation,
|
ui.BIM_PT_documentation,
|
||||||
ui.BIM_PT_bim,
|
ui.BIM_PT_bim,
|
||||||
|
ui.BIM_PT_classifications,
|
||||||
ui.BIM_PT_search,
|
ui.BIM_PT_search,
|
||||||
ui.BIM_PT_bcf,
|
ui.BIM_PT_bcf,
|
||||||
ui.BIM_PT_owner,
|
ui.BIM_PT_owner,
|
||||||
@@ -133,8 +141,10 @@ if bpy is not None:
|
|||||||
ui.BIM_PT_material,
|
ui.BIM_PT_material,
|
||||||
ui.BIM_PT_mesh,
|
ui.BIM_PT_mesh,
|
||||||
ui.BIM_PT_object,
|
ui.BIM_PT_object,
|
||||||
|
ui.BIM_PT_classification_references,
|
||||||
ui.BIM_PT_camera,
|
ui.BIM_PT_camera,
|
||||||
ui.BIM_UL_topics,
|
ui.BIM_UL_topics,
|
||||||
|
ui.BIM_UL_classifications,
|
||||||
ui.BIM_ADDON_preferences,
|
ui.BIM_ADDON_preferences,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
Source,Edition,EditionDate,Name,Description,Location,ReferenceTokens
|
|
||||||
RIBA Enterprises Ltd,2015,Aug-19,Uniclass 2015,Uniclass2015 is a unified classification for the UK industry covering all construction sectors.,https://www.thenbs.com/our-tools/uniclass-2015,"[""_""]"
|
|
||||||
OmniClass,2.1,May-12,OmniClass,The OmniClass Construction Classification System is a classification system for the construction industry.,https://www.csiresources.org/standards/omniclass,"[""-"","" ""]"
|
|
||||||
|
@@ -1,2 +0,0 @@
|
|||||||
Identification,Name,ReferencedSource
|
|
||||||
Pr_20_85_14_16,Concrete solid slabs,0
|
|
||||||
|
@@ -463,7 +463,7 @@ class IfcParser():
|
|||||||
|
|
||||||
for classification in obj.BIMObjectProperties.classifications:
|
for classification in obj.BIMObjectProperties.classifications:
|
||||||
self.rel_associates_classification_object.setdefault(
|
self.rel_associates_classification_object.setdefault(
|
||||||
classification.identification, []).append(product)
|
classification.name, []).append(product)
|
||||||
|
|
||||||
for key in obj.keys():
|
for key in obj.keys():
|
||||||
if key[0:9] == 'Objective':
|
if key[0:9] == 'Objective':
|
||||||
@@ -634,32 +634,39 @@ class IfcParser():
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
def get_classifications(self):
|
def get_classifications(self):
|
||||||
results = []
|
classifications = bpy.context.scene.BIMProperties.classifications
|
||||||
class_path = self.data_dir + 'class/'
|
results = {}
|
||||||
with open(class_path + 'classifications.csv', 'r') as f:
|
for classification in classifications:
|
||||||
data = list(csv.reader(f))
|
results[classification.name] = {
|
||||||
keys = data.pop(0)
|
'ifc': None,
|
||||||
for row in data:
|
'raw': classification,
|
||||||
row[-1] = json.loads(row[-1])
|
'attributes': {
|
||||||
results.append({
|
'Name': classification.name,
|
||||||
'ifc': None,
|
'Source': classification.source,
|
||||||
'raw': row,
|
'Edition': classification.edition,
|
||||||
'attributes': dict(zip(keys, row))
|
'EditionDate': classification.edition_date,
|
||||||
})
|
'Description': classification.description,
|
||||||
|
'Location': classification.location,
|
||||||
|
'ReferenceTokens': json.loads(
|
||||||
|
'[{}]'.format(classification.reference_tokens[1:-1].replace('\'', '"').strip(',')))
|
||||||
|
}
|
||||||
|
}
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def get_classification_references(self):
|
def get_classification_references(self):
|
||||||
results = {}
|
results = {}
|
||||||
class_path = self.data_dir + 'class/'
|
for product in self.selected_products:
|
||||||
with open(class_path + 'references.csv', 'r') as f:
|
for reference in product['raw'].BIMObjectProperties.classifications:
|
||||||
data = list(csv.reader(f))
|
results[reference.name] = {
|
||||||
keys = data.pop(0)
|
|
||||||
for row in data:
|
|
||||||
results[row[0]] = {
|
|
||||||
'ifc': None,
|
'ifc': None,
|
||||||
'raw': row,
|
'raw': reference,
|
||||||
'referenced_source': int(row.pop()),
|
'referenced_source': reference.referenced_source,
|
||||||
'attributes': dict(zip(keys, row))
|
'attributes': {
|
||||||
|
'Location': reference.location,
|
||||||
|
'Identification': reference.name,
|
||||||
|
'Name': reference.human_name,
|
||||||
|
'Description': reference.description
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -1323,7 +1330,7 @@ class IfcExporter():
|
|||||||
[self.ifc_parser.project['ifc']], document['ifc'])
|
[self.ifc_parser.project['ifc']], document['ifc'])
|
||||||
|
|
||||||
def create_classifications(self):
|
def create_classifications(self):
|
||||||
for classification in self.ifc_parser.classifications:
|
for classification in self.ifc_parser.classifications.values():
|
||||||
classification['ifc'] = self.file.create_entity(
|
classification['ifc'] = self.file.create_entity(
|
||||||
'IfcClassification',
|
'IfcClassification',
|
||||||
**classification['attributes']
|
**classification['attributes']
|
||||||
|
|||||||
@@ -1198,14 +1198,64 @@ class ExplodeAggregate(bpy.types.Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class LoadClassification(bpy.types.Operator):
|
||||||
|
bl_idname = 'bim.load_classification'
|
||||||
|
bl_label = 'Load Classification'
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
from . import prop
|
||||||
|
prop.ClassificationView.raw_data = schema.ifc.load_classification(
|
||||||
|
context.scene.BIMProperties.classification)
|
||||||
|
context.scene.BIMProperties.classification_references.root = ''
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class AddClassification(bpy.types.Operator):
|
||||||
|
bl_idname = 'bim.add_classification'
|
||||||
|
bl_label = 'Add Classification'
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
if context.scene.BIMProperties.classification in schema.ifc.classifications:
|
||||||
|
data = schema.ifc.classifications[context.scene.BIMProperties.classification]
|
||||||
|
classification = context.scene.BIMProperties.classifications.add()
|
||||||
|
classification.source = data.Source
|
||||||
|
classification.edition = data.Edition
|
||||||
|
classification.edition_date = data.EditionDate
|
||||||
|
classification.name = data.Name
|
||||||
|
classification.description = data.Description
|
||||||
|
classification.location = data.Location
|
||||||
|
classification.reference_tokens = str(data.ReferenceTokens)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveClassification(bpy.types.Operator):
|
||||||
|
bl_idname = 'bim.remove_classification'
|
||||||
|
bl_label = 'Remove Classification'
|
||||||
|
classification_index: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
bpy.context.scene.BIMProperties.classifications.remove(self.classification_index)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class AssignClassification(bpy.types.Operator):
|
class AssignClassification(bpy.types.Operator):
|
||||||
bl_idname = 'bim.assign_classification'
|
bl_idname = 'bim.assign_classification'
|
||||||
bl_label = 'Assign Classification'
|
bl_label = 'Assign Classification'
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
referenced_source = schema.ifc.classifications[bpy.context.scene.BIMProperties.classification].Name
|
||||||
for obj in bpy.context.selected_objects:
|
for obj in bpy.context.selected_objects:
|
||||||
classification = obj.BIMObjectProperties.classifications.add()
|
classification = obj.BIMObjectProperties.classifications.add()
|
||||||
classification.identification = bpy.context.scene.BIMProperties.reference
|
refs = bpy.context.scene.BIMProperties.classification_references
|
||||||
|
data = refs.root['children'][refs.children[refs.active_index].name]
|
||||||
|
if data['identification']:
|
||||||
|
classification.name = data['identification']
|
||||||
|
if data['name']:
|
||||||
|
classification.human_name = data['name']
|
||||||
|
for key in ['location', 'description']:
|
||||||
|
if data[key]:
|
||||||
|
setattr(classification, key, data[key])
|
||||||
|
classification.referenced_source = referenced_source
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
@@ -1214,18 +1264,20 @@ class UnassignClassification(bpy.types.Operator):
|
|||||||
bl_label = 'Unassign Classification'
|
bl_label = 'Unassign Classification'
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
refs = bpy.context.scene.BIMProperties.classification_references
|
||||||
|
key = refs.children[refs.active_index].name
|
||||||
for obj in bpy.context.selected_objects:
|
for obj in bpy.context.selected_objects:
|
||||||
index = object.BIMObjectProperties.classifications.find(bpy.context.scene.BIMProperties.classification)
|
index = obj.BIMObjectProperties.classifications.find(key)
|
||||||
if index != -1:
|
if index != -1:
|
||||||
object.BIMObjectProperties.classifications.remove(index)
|
obj.BIMObjectProperties.classifications.remove(index)
|
||||||
|
|
||||||
obj.BIMObjectProperties.classification = ''
|
obj.BIMObjectProperties.classification = ''
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class RemoveClassification(bpy.types.Operator):
|
class RemoveClassificationReference(bpy.types.Operator):
|
||||||
bl_idname = 'bim.remove_classification'
|
bl_idname = 'bim.remove_classification_reference'
|
||||||
bl_label = 'Remove Classification'
|
bl_label = 'Remove Classification Reference'
|
||||||
classification_index: bpy.props.IntProperty()
|
classification_index: bpy.props.IntProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@@ -1662,3 +1714,24 @@ class BIM_OT_CopyAttributesToSelection(bpy.types.Operator):
|
|||||||
try:
|
try:
|
||||||
setattr(new_prop_base, p, getattr(prop, p))
|
setattr(new_prop_base, p, getattr(prop, p))
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_OT_ChangeClassificationLevel(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.change_classification_level"
|
||||||
|
bl_label = "Change Classification Level"
|
||||||
|
|
||||||
|
# string representing the id-data (e.g. the scene).
|
||||||
|
path_sid: bpy.props.StringProperty()
|
||||||
|
# path from the id-data to the classification view object
|
||||||
|
path_lst: bpy.props.StringProperty()
|
||||||
|
# name of child entity to enter (empty = go up one level)
|
||||||
|
path_itm: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
id_data = eval(self.path_sid)
|
||||||
|
lst = id_data.path_resolve(self.path_lst)
|
||||||
|
if self.path_itm:
|
||||||
|
lst.root = self.path_itm
|
||||||
|
else:
|
||||||
|
lst.root = ''
|
||||||
|
return {'FINISHED'}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ scenarios_enum = []
|
|||||||
psetnames_enum = []
|
psetnames_enum = []
|
||||||
psetfiles_enum = []
|
psetfiles_enum = []
|
||||||
classification_enum = []
|
classification_enum = []
|
||||||
reference_enum = []
|
|
||||||
attributes_enum = []
|
attributes_enum = []
|
||||||
overridepsetnames_enum = []
|
overridepsetnames_enum = []
|
||||||
qtonames_enum = []
|
qtonames_enum = []
|
||||||
@@ -236,31 +235,15 @@ def getClassifications(self, context):
|
|||||||
global classification_enum
|
global classification_enum
|
||||||
if len(classification_enum) < 1:
|
if len(classification_enum) < 1:
|
||||||
classification_enum.clear()
|
classification_enum.clear()
|
||||||
with open(os.path.join(self.data_dir, 'class', 'classifications.csv'), 'r') as f:
|
files = os.listdir(os.path.join(self.schema_dir, 'classifications'))
|
||||||
data = list(csv.reader(f))
|
classification_enum.extend([(f.replace('.ifc', ''), f.replace('.ifc', ''), '') for f in files])
|
||||||
keys = data.pop(0)
|
|
||||||
index = keys.index('Name')
|
|
||||||
classification_enum.extend([(str(i), d[index], '') for i, d in enumerate(data)])
|
|
||||||
return classification_enum
|
return classification_enum
|
||||||
|
|
||||||
|
|
||||||
def refreshReferences(self, context):
|
def refreshReferences(self, context):
|
||||||
global reference_enum
|
context.scene.BIMProperties.classification_references.root = None
|
||||||
reference_enum.clear()
|
ClassificationView.raw_data = schema.ifc.load_classification(context.scene.BIMProperties.classification)
|
||||||
getReferences(self, context)
|
context.scene.BIMProperties.classification_references.root = ''
|
||||||
|
|
||||||
|
|
||||||
def getReferences(self, context):
|
|
||||||
global reference_enum
|
|
||||||
if len(reference_enum) < 1:
|
|
||||||
if not self.classification.strip():
|
|
||||||
return reference_enum
|
|
||||||
with open(os.path.join(self.data_dir, 'class', 'references.csv'), 'r') as f:
|
|
||||||
data = list(csv.reader(f))
|
|
||||||
keys = data.pop(0)
|
|
||||||
reference_enum.extend([(d[0], '{} - {}'.format(d[0], d[1]), '') for d in data if
|
|
||||||
d[2] == self.classification.strip()])
|
|
||||||
return reference_enum
|
|
||||||
|
|
||||||
|
|
||||||
def getOverridePsetNames(self, context):
|
def getOverridePsetNames(self, context):
|
||||||
@@ -390,6 +373,10 @@ def getSheets(self, context):
|
|||||||
return sheets_enum
|
return sheets_enum
|
||||||
|
|
||||||
|
|
||||||
|
class StrProperty(PropertyGroup):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Subcontext(PropertyGroup):
|
class Subcontext(PropertyGroup):
|
||||||
name: StringProperty(name='Name')
|
name: StringProperty(name='Name')
|
||||||
target_view: StringProperty(name='Target View')
|
target_view: StringProperty(name='Target View')
|
||||||
@@ -587,6 +574,78 @@ def getBcfViewpoints(self, context):
|
|||||||
return bcfviewpoints_enum
|
return bcfviewpoints_enum
|
||||||
|
|
||||||
|
|
||||||
|
class Classification(PropertyGroup):
|
||||||
|
name: StringProperty(name="Name")
|
||||||
|
source: StringProperty(name="Source")
|
||||||
|
edition: StringProperty(name="Edition")
|
||||||
|
edition_date: StringProperty(name="Edition Date")
|
||||||
|
description: StringProperty(name="Description")
|
||||||
|
location: StringProperty(name="Location")
|
||||||
|
reference_tokens: StringProperty(name="Reference Tokens")
|
||||||
|
|
||||||
|
|
||||||
|
class ClassificationReference(PropertyGroup):
|
||||||
|
name: StringProperty(name="Identification")
|
||||||
|
location: StringProperty(name="Location")
|
||||||
|
human_name: StringProperty(name="Name")
|
||||||
|
referenced_source: StringProperty(name="Source")
|
||||||
|
description: StringProperty(name="Description")
|
||||||
|
sort: StringProperty(name="Sort")
|
||||||
|
|
||||||
|
|
||||||
|
class ClassificationView(PropertyGroup):
|
||||||
|
crumbs: None
|
||||||
|
children: None
|
||||||
|
active_index: bpy.props.IntProperty()
|
||||||
|
raw_data = {}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def root(self):
|
||||||
|
data = self.raw_data
|
||||||
|
for crumb in self.crumbs:
|
||||||
|
data = data['children'].get(crumb.name)
|
||||||
|
if not data:
|
||||||
|
raise TypeError('Cannot resolve crumb path')
|
||||||
|
return data
|
||||||
|
|
||||||
|
@root.setter
|
||||||
|
def root(self, rt):
|
||||||
|
if rt == None:
|
||||||
|
self.crumbs.clear()
|
||||||
|
self.children.clear()
|
||||||
|
elif rt == '':
|
||||||
|
if self.crumbs:
|
||||||
|
self.crumbs.remove(len(self.crumbs)-1)
|
||||||
|
self.children.clear()
|
||||||
|
for child in self.root['children'].keys():
|
||||||
|
self.children.add().name = child
|
||||||
|
else:
|
||||||
|
data = self.root
|
||||||
|
if rt in data['children'].keys():
|
||||||
|
self.crumbs.add().name = rt
|
||||||
|
self.children.clear()
|
||||||
|
for child in data['children'][rt]['children'].keys():
|
||||||
|
self.children.add().name = child
|
||||||
|
|
||||||
|
def draw_stub(self, context, layout):
|
||||||
|
if not self.children:
|
||||||
|
op = layout.operator('bim.change_classification_level', text="@Toplevel")
|
||||||
|
else:
|
||||||
|
op = layout.operator('bim.change_classification_level', text=self.root['name'])
|
||||||
|
op.path_sid = "%r"%self.id_data
|
||||||
|
op.path_lst = self.path_from_id()
|
||||||
|
op.path_itm = ''
|
||||||
|
layout.template_list('BIM_UL_classifications',
|
||||||
|
self.path_from_id(), self, 'children', self, 'active_index')
|
||||||
|
|
||||||
|
|
||||||
|
# Monkey-patched, just to keep registration in one block
|
||||||
|
ClassificationView.__annotations__['crumbs'] = \
|
||||||
|
bpy.props.CollectionProperty(type=StrProperty)
|
||||||
|
ClassificationView.__annotations__['children'] = \
|
||||||
|
bpy.props.CollectionProperty(type=StrProperty)
|
||||||
|
|
||||||
|
|
||||||
class BIMProperties(PropertyGroup):
|
class BIMProperties(PropertyGroup):
|
||||||
schema_dir: StringProperty(default=os.path.join(cwd ,'schema') + os.path.sep, name="Schema Directory")
|
schema_dir: StringProperty(default=os.path.join(cwd ,'schema') + os.path.sep, name="Schema Directory")
|
||||||
data_dir: StringProperty(default=os.path.join(cwd, 'data') + os.path.sep, name="Data Directory")
|
data_dir: StringProperty(default=os.path.join(cwd, 'data') + os.path.sep, name="Data Directory")
|
||||||
@@ -639,7 +698,7 @@ class BIMProperties(PropertyGroup):
|
|||||||
aggregate_class: EnumProperty(items=getIfcClasses, name="Aggregate Class")
|
aggregate_class: EnumProperty(items=getIfcClasses, name="Aggregate Class")
|
||||||
aggregate_name: StringProperty(name="Aggregate Name")
|
aggregate_name: StringProperty(name="Aggregate Name")
|
||||||
classification: EnumProperty(items=getClassifications, name="Classification", update=refreshReferences)
|
classification: EnumProperty(items=getClassifications, name="Classification", update=refreshReferences)
|
||||||
reference: EnumProperty(items=getReferences, name="Reference")
|
classifications: CollectionProperty(name="Classifications", type=Classification)
|
||||||
has_model_context: BoolProperty(name="Has Model Context", default=True)
|
has_model_context: BoolProperty(name="Has Model Context", default=True)
|
||||||
has_plan_context: BoolProperty(name="Has Plan Context", default=False)
|
has_plan_context: BoolProperty(name="Has Plan Context", default=False)
|
||||||
model_subcontexts: CollectionProperty(name='Model Subcontexts', type=Subcontext)
|
model_subcontexts: CollectionProperty(name='Model Subcontexts', type=Subcontext)
|
||||||
@@ -647,6 +706,7 @@ class BIMProperties(PropertyGroup):
|
|||||||
available_contexts: EnumProperty(items=[('Model', 'Model', ''), ('Plan', 'Plan', '')], name="Available Contexts")
|
available_contexts: EnumProperty(items=[('Model', 'Model', ''), ('Plan', 'Plan', '')], name="Available Contexts")
|
||||||
available_subcontexts: EnumProperty(items=getSubcontexts, name="Available Subcontexts")
|
available_subcontexts: EnumProperty(items=getSubcontexts, name="Available Subcontexts")
|
||||||
available_target_views: EnumProperty(items=getTargetViews, name="Available Target Views")
|
available_target_views: EnumProperty(items=getTargetViews, name="Available Target Views")
|
||||||
|
classification_references: PointerProperty(type=ClassificationView)
|
||||||
|
|
||||||
|
|
||||||
class BCFProperties(PropertyGroup):
|
class BCFProperties(PropertyGroup):
|
||||||
@@ -720,10 +780,6 @@ class PsetQto(PropertyGroup):
|
|||||||
class Document(PropertyGroup):
|
class Document(PropertyGroup):
|
||||||
file: StringProperty(name="File")
|
file: StringProperty(name="File")
|
||||||
|
|
||||||
class Classification(PropertyGroup):
|
|
||||||
name: StringProperty(name="Name")
|
|
||||||
identification: StringProperty(name="Identification")
|
|
||||||
|
|
||||||
|
|
||||||
class GlobalId(PropertyGroup):
|
class GlobalId(PropertyGroup):
|
||||||
name: StringProperty(name="Name")
|
name: StringProperty(name="Name")
|
||||||
@@ -744,7 +800,7 @@ class BIMObjectProperties(PropertyGroup):
|
|||||||
applicable_attributes: EnumProperty(items=getApplicableAttributes, name="Attribute Names")
|
applicable_attributes: EnumProperty(items=getApplicableAttributes, name="Attribute Names")
|
||||||
documents: CollectionProperty(name="Documents", type=Document)
|
documents: CollectionProperty(name="Documents", type=Document)
|
||||||
applicable_documents: EnumProperty(items=getApplicableDocuments, name="Available Documents")
|
applicable_documents: EnumProperty(items=getApplicableDocuments, name="Available Documents")
|
||||||
classifications: CollectionProperty(name="Classifications", type=Classification)
|
classifications: CollectionProperty(name="Classifications", type=ClassificationReference)
|
||||||
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
|
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
|
||||||
override_psets: CollectionProperty(name="Override Psets", type=PsetQto)
|
override_psets: CollectionProperty(name="Override Psets", type=PsetQto)
|
||||||
override_pset_name: EnumProperty(items=getOverridePsetNames, name='Override Pset Name')
|
override_pset_name: EnumProperty(items=getOverridePsetNames, name='Override Pset Name')
|
||||||
|
|||||||
@@ -21,14 +21,22 @@ class IfcSchema():
|
|||||||
'IfcElementType'
|
'IfcElementType'
|
||||||
]
|
]
|
||||||
self.elements = {}
|
self.elements = {}
|
||||||
|
|
||||||
self.property_files = []
|
self.property_files = []
|
||||||
property_paths = Path(self.schema_dir).glob('Pset_*.ifc')
|
property_paths = Path(self.schema_dir).glob('Pset_*.ifc')
|
||||||
for path in property_paths:
|
for path in property_paths:
|
||||||
self.property_files.append(ifcopenshell.open(path))
|
self.property_files.append(ifcopenshell.open(path))
|
||||||
|
|
||||||
|
self.classification_files = {}
|
||||||
|
classification_paths = Path(self.schema_dir).glob('classifications/*.ifc')
|
||||||
|
for path in classification_paths:
|
||||||
|
self.classification_files[os.path.basename(path).split('.')[0]] = ifcopenshell.open(path)
|
||||||
|
|
||||||
self.psets = {}
|
self.psets = {}
|
||||||
self.qtos = {}
|
self.qtos = {}
|
||||||
self.applicable_psets = {}
|
self.applicable_psets = {}
|
||||||
self.applicable_qtos = {}
|
self.applicable_qtos = {}
|
||||||
|
self.classifications = {}
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
@@ -53,4 +61,31 @@ class IfcSchema():
|
|||||||
entity = prop.ApplicableEntity if prop.ApplicableEntity else 'IfcRoot'
|
entity = prop.ApplicableEntity if prop.ApplicableEntity else 'IfcRoot'
|
||||||
self.applicable_psets.setdefault(entity, []).append(prop.Name)
|
self.applicable_psets.setdefault(entity, []).append(prop.Name)
|
||||||
|
|
||||||
|
for filename, classification_file in self.classification_files.items():
|
||||||
|
classification = classification_file.by_type('IfcClassification')[0]
|
||||||
|
self.classifications[filename] = classification
|
||||||
|
|
||||||
|
def load_classification(self, filename):
|
||||||
|
classification = self.classifications[filename]
|
||||||
|
return {
|
||||||
|
'name': '',
|
||||||
|
'description': '',
|
||||||
|
'children': self.get_classification_references(classification)
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_classification_references(self, classification):
|
||||||
|
references = {}
|
||||||
|
if not classification.HasReferences:
|
||||||
|
return references
|
||||||
|
for reference in classification.HasReferences:
|
||||||
|
references[reference.Identification] = {
|
||||||
|
'location': reference.Location,
|
||||||
|
'identification': reference.Identification,
|
||||||
|
'name': reference.Name,
|
||||||
|
'description': reference.Description,
|
||||||
|
'children': self.get_classification_references(reference)
|
||||||
|
}
|
||||||
|
return references
|
||||||
|
|
||||||
|
|
||||||
ifc = IfcSchema()
|
ifc = IfcSchema()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+12474
File diff suppressed because it is too large
Load Diff
@@ -111,17 +111,6 @@ class BIM_PT_object(Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(props, 'documents')
|
row.prop(props, 'documents')
|
||||||
|
|
||||||
layout.label(text="Classification:")
|
|
||||||
|
|
||||||
for index, classification in enumerate(props.classifications):
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.prop(classification, 'identification', text='')
|
|
||||||
row.prop(classification, 'name', text='')
|
|
||||||
row.operator('bim.remove_classification', icon='X', text='').classification_index = index
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(props, 'classifications')
|
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(props, 'material_type')
|
row.prop(props, 'material_type')
|
||||||
|
|
||||||
@@ -142,6 +131,87 @@ class BIM_PT_object(Panel):
|
|||||||
row.prop(props, 'structural_member_connection')
|
row.prop(props, 'structural_member_connection')
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_PT_classification_references(Panel):
|
||||||
|
bl_label = 'Classification References'
|
||||||
|
bl_idname = 'BIM_PT_classification_references'
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
bl_context = 'object'
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
props = context.active_object.BIMObjectProperties
|
||||||
|
|
||||||
|
layout.label(text="Classification:")
|
||||||
|
|
||||||
|
for index, classification in enumerate(props.classifications):
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'name')
|
||||||
|
row.operator('bim.remove_classification_reference', icon='X', text='').classification_index = index
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'human_name')
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'location')
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'description')
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'referenced_source')
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(props, 'classifications')
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_PT_classifications(Panel):
|
||||||
|
bl_label = 'Classifications'
|
||||||
|
bl_idname = 'BIM_PT_classifications'
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
bl_context = 'scene'
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
props = context.scene.BIMProperties
|
||||||
|
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(props, "classification", text='')
|
||||||
|
row.operator("bim.add_classification", text='', icon='ADD')
|
||||||
|
|
||||||
|
if context.scene.BIMProperties.classification_references.raw_data:
|
||||||
|
context.scene.BIMProperties.classification_references.draw_stub(context, layout)
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.operator("bim.assign_classification")
|
||||||
|
row.operator("bim.unassign_classification")
|
||||||
|
else:
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.operator('bim.load_classification')
|
||||||
|
|
||||||
|
if not props.classifications:
|
||||||
|
return
|
||||||
|
|
||||||
|
layout.label(text="Classifications:")
|
||||||
|
|
||||||
|
for index, classification in enumerate(props.classifications):
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'name')
|
||||||
|
row.operator('bim.remove_classification', icon='X', text='').classification_index = index
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'source')
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'edition')
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'edition_date')
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'description')
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'location')
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(classification, 'reference_tokens')
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(props, 'classifications')
|
||||||
|
|
||||||
class BIM_PT_mesh(Panel):
|
class BIM_PT_mesh(Panel):
|
||||||
bl_label = 'IFC Representations'
|
bl_label = 'IFC Representations'
|
||||||
bl_idname = 'BIM_PT_mesh'
|
bl_idname = 'BIM_PT_mesh'
|
||||||
@@ -499,16 +569,6 @@ class BIM_PT_bim(Panel):
|
|||||||
row.operator("bim.edit_aggregate")
|
row.operator("bim.edit_aggregate")
|
||||||
row.operator("bim.save_aggregate")
|
row.operator("bim.save_aggregate")
|
||||||
|
|
||||||
layout.label(text="Classifications:")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "classification")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "reference")
|
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.operator("bim.assign_classification")
|
|
||||||
row.operator("bim.unassign_classification")
|
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_search(Panel):
|
class BIM_PT_search(Panel):
|
||||||
bl_label = "BIM Search"
|
bl_label = "BIM Search"
|
||||||
@@ -852,6 +912,24 @@ class BIM_UL_topics(bpy.types.UIList):
|
|||||||
layout.label(text="", translate=False)
|
layout.label(text="", translate=False)
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_UL_classifications(bpy.types.UIList):
|
||||||
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
|
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||||
|
rt = data.root
|
||||||
|
ch = rt['children']
|
||||||
|
itemdata = ch[item.name]
|
||||||
|
if itemdata.get('children', {}):
|
||||||
|
op = layout.operator("bim.change_classification_level", text="",
|
||||||
|
emboss=False, icon="DISCLOSURE_TRI_RIGHT")
|
||||||
|
op.path_sid = "%r"%active_data.id_data # get id-data
|
||||||
|
op.path_lst = active_data.path_from_id() # path to view
|
||||||
|
op.path_itm = item.name # name of child. empty = go up
|
||||||
|
else:
|
||||||
|
layout.label(text='', icon='BLANK1')
|
||||||
|
layout.prop(item, "name", text="", emboss=False)
|
||||||
|
layout.label(text=itemdata['name'])
|
||||||
|
|
||||||
|
|
||||||
class BIM_ADDON_preferences(bpy.types.AddonPreferences):
|
class BIM_ADDON_preferences(bpy.types.AddonPreferences):
|
||||||
bl_idname = 'blenderbim'
|
bl_idname = 'blenderbim'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user