Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into presentationlayer

This commit is contained in:
ofskrand
2020-11-04 07:57:40 +01:00
11 changed files with 262 additions and 98 deletions
+8
View File
@@ -0,0 +1,8 @@
c14f5eeca042232025797990396232e4feab53e7
d6881e833da0b6278313870d37d42ca6ece8686a
892be5444c5bd01a601c99243ac8d3e7b2f0e779
d169a964dd7e9ab5c98b35a82bcbc76dc6229a7a
4a6ec11f6f84a3d1fed2ee9b2f85d783ac3daa9d
2c9d6a47f4d24a923069775206bf734feeb14830
8f1743ed64a2a52c201a1ef5e312b4d3a7a922cf
ad7f030344c405e10cfa7d5cf06d82c121eeb825
+2
View File
@@ -38,10 +38,12 @@ endif
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && rm -f geolocation.py cd dist/blenderbim/libs/site/packages/ifcopenshell/util && rm -f geolocation.py
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && rm -f selector.py cd dist/blenderbim/libs/site/packages/ifcopenshell/util && rm -f selector.py
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && rm -f unit.py cd dist/blenderbim/libs/site/packages/ifcopenshell/util && rm -f unit.py
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && rm -f pset.py
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/element.py cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/element.py
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/geolocation.py cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/geolocation.py
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/selector.py cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/selector.py
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/unit.py cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/unit.py
cd dist/blenderbim/libs/site/packages/ifcopenshell/util && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcopenshell-python/ifcopenshell/util/pset.py
# Provides Python OCC functionality for cutting IFC geometry for construction documentation # Provides Python OCC functionality for cutting IFC geometry for construction documentation
mkdir dist/working mkdir dist/working
@@ -21,6 +21,7 @@ if bpy is not None:
from .module.model import opening as model_opening from .module.model import opening as model_opening
classes = ( classes = (
operator.ReassignClass,
operator.AssignClass, operator.AssignClass,
operator.UnassignClass, operator.UnassignClass,
operator.SelectClass, operator.SelectClass,
@@ -6,12 +6,13 @@ import datetime
import os import os
import zipfile import zipfile
import tempfile import tempfile
import ifcopenshell
import ifcopenshell.util.pset
from pathlib import Path from pathlib import Path
from mathutils import Vector, Matrix from mathutils import Vector, Matrix
from .helper import SIUnitHelper, get_representation_elements from .helper import SIUnitHelper, get_representation_elements
from . import schema from . import schema
from . import ifc from . import ifc
import ifcopenshell
import addon_utils import addon_utils
@@ -466,10 +467,10 @@ class IfcParser:
return return
qto_names = self.get_applicable_qtos(ifc_class) qto_names = self.get_applicable_qtos(ifc_class)
for name in qto_names: for name in qto_names:
if name not in schema.ifc.qtos: if name not in ifcopenshell.util.pset.qtos:
continue continue
has_automatic_value = False has_automatic_value = False
props = schema.ifc.qtos[name]["HasPropertyTemplates"].keys() props = ifcopenshell.util.pset.qtos[name]["HasPropertyTemplates"].keys()
guessed_values = {} guessed_values = {}
for prop_name in props: for prop_name in props:
value = self.qto_calculator.guess_quantity(prop_name, props, obj) value = self.qto_calculator.guess_quantity(prop_name, props, obj)
@@ -1666,12 +1667,12 @@ class IfcExporter:
) )
def create_qto_properties(self, qto): def create_qto_properties(self, qto):
if qto["attributes"]["Name"] in schema.ifc.qtos: if qto["attributes"]["Name"] in ifcopenshell.util.pset.qtos:
return self.create_templated_qto_properties(qto) return self.create_templated_qto_properties(qto)
return self.create_custom_qto_properties(qto) return self.create_custom_qto_properties(qto)
def create_pset_properties(self, pset): def create_pset_properties(self, pset):
if pset["attributes"]["Name"] in schema.ifc.psets: if pset["attributes"]["Name"] in ifcopenshell.util.pset.psets:
return self.create_templated_pset_properties(pset) return self.create_templated_pset_properties(pset)
return self.create_custom_pset_properties(pset) return self.create_custom_pset_properties(pset)
@@ -1704,7 +1705,7 @@ class IfcExporter:
def create_templated_pset_properties(self, pset): def create_templated_pset_properties(self, pset):
properties = [] properties = []
templates = schema.ifc.psets[pset["attributes"]["Name"]]["HasPropertyTemplates"] templates = ifcopenshell.util.pset.psets[pset["attributes"]["Name"]]["HasPropertyTemplates"]
for name, data in templates.items(): for name, data in templates.items():
if name not in pset["raw"]: if name not in pset["raw"]:
continue continue
@@ -1731,7 +1732,7 @@ class IfcExporter:
def create_templated_qto_properties(self, qto): def create_templated_qto_properties(self, qto):
properties = [] properties = []
templates = schema.ifc.qtos[qto["attributes"]["Name"]]["HasPropertyTemplates"] templates = ifcopenshell.util.pset.qtos[qto["attributes"]["Name"]]["HasPropertyTemplates"]
for name, data in templates.items(): for name, data in templates.items():
if name not in qto["raw"]: if name not in qto["raw"]:
continue continue
@@ -3157,10 +3158,7 @@ class IfcExporter:
) )
def relate_spaces_to_boundary_elements(self): def relate_spaces_to_boundary_elements(self):
for ( for (relating_space_index, relationships,) in self.ifc_parser.rel_space_boundaries.items():
relating_space_index,
relationships,
) in self.ifc_parser.rel_space_boundaries.items():
for relationship in relationships: for relationship in relationships:
relationship["attributes"]["GlobalId"] = ifcopenshell.guid.new() relationship["attributes"]["GlobalId"] = ifcopenshell.guid.new()
relationship["attributes"]["RelatedBuildingElement"] = self.ifc_parser.products[ relationship["attributes"]["RelatedBuildingElement"] = self.ifc_parser.products[
@@ -3,6 +3,7 @@ import ifcopenshell.geom
import ifcopenshell.util.geolocation import ifcopenshell.util.geolocation
import ifcopenshell.util.selector import ifcopenshell.util.selector
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.pset
import bpy import bpy
import bmesh import bmesh
import os import os
@@ -206,8 +207,8 @@ class MaterialCreator:
def add_pset(self, pset, obj): def add_pset(self, pset, obj):
new_pset = obj.BIMMaterialProperties.psets.add() new_pset = obj.BIMMaterialProperties.psets.add()
new_pset.name = pset.Name new_pset.name = pset.Name
if new_pset.name in schema.ifc.psets: if new_pset.name in ifcopenshell.util.pset.psets:
for prop_name in schema.ifc.psets[new_pset.name]["HasPropertyTemplates"].keys(): for prop_name in ifcopenshell.util.pset.psets[new_pset.name]["HasPropertyTemplates"].keys():
prop = new_pset.properties.add() prop = new_pset.properties.add()
prop.name = prop_name prop.name = prop_name
for prop in pset.Properties: for prop in pset.Properties:
@@ -1338,8 +1339,8 @@ class IfcImporter:
def add_pset(self, pset, obj): def add_pset(self, pset, obj):
new_pset = obj.BIMObjectProperties.psets.add() new_pset = obj.BIMObjectProperties.psets.add()
new_pset.name = pset.Name new_pset.name = pset.Name
if new_pset.name in schema.ifc.psets: if new_pset.name in ifcopenshell.util.pset.psets:
for prop_name in schema.ifc.psets[new_pset.name]["HasPropertyTemplates"].keys(): for prop_name in ifcopenshell.util.pset.psets[new_pset.name]["HasPropertyTemplates"].keys():
prop = new_pset.properties.add() prop = new_pset.properties.add()
prop.name = prop_name prop.name = prop_name
# Invalid IFC, but some vendors like Solidworks do this so we accomodate it # Invalid IFC, but some vendors like Solidworks do this so we accomodate it
@@ -1358,8 +1359,8 @@ class IfcImporter:
def add_qto(self, qto, obj): def add_qto(self, qto, obj):
new_qto = obj.BIMObjectProperties.qtos.add() new_qto = obj.BIMObjectProperties.qtos.add()
new_qto.name = str(qto.Name) new_qto.name = str(qto.Name)
if new_qto.name in schema.ifc.qtos: if new_qto.name in ifcopenshell.util.pset.qtos:
for prop_name in schema.ifc.qtos[new_qto.name]["HasPropertyTemplates"].keys(): for prop_name in ifcopenshell.util.pset.qtos[new_qto.name]["HasPropertyTemplates"].keys():
prop = new_qto.properties.add() prop = new_qto.properties.add()
prop.name = prop_name prop.name = prop_name
for prop in qto.Quantities: for prop in qto.Quantities:
+99 -33
View File
@@ -9,6 +9,7 @@ import subprocess
import ifcopenshell import ifcopenshell
import ifcopenshell.util.selector import ifcopenshell.util.selector
import ifcopenshell.util.geolocation import ifcopenshell.util.geolocation
import ifcopenshell.util.pset
import tempfile import tempfile
from . import export_ifc from . import export_ifc
from . import import_ifc from . import import_ifc
@@ -213,6 +214,20 @@ class SelectPset(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class ReassignClass(bpy.types.Operator):
bl_idname = "bim.reassign_class"
bl_label = "Reassign IFC Class"
def execute(self, context):
obj = bpy.context.active_object
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = True
bpy.context.scene.BIMProperties.ifc_class = obj.name.split("/")[0]
predefined_type = obj.BIMObjectProperties.attributes.get("PredefinedType")
if predefined_type:
bpy.context.scene.BIMProperties.ifc_predefined_type = predefined_type.string_value
return {"FINISHED"}
class AssignClass(bpy.types.Operator): class AssignClass(bpy.types.Operator):
bl_idname = "bim.assign_class" bl_idname = "bim.assign_class"
bl_label = "Assign IFC Class" bl_label = "Assign IFC Class"
@@ -221,6 +236,7 @@ class AssignClass(bpy.types.Operator):
def execute(self, context): def execute(self, context):
if self.object_name: if self.object_name:
objects = [bpy.data.objects.get(self.object_name)] objects = [bpy.data.objects.get(self.object_name)]
objects[0].BIMObjectProperties.is_reassigning_class = False
else: else:
objects = bpy.context.selected_objects objects = bpy.context.selected_objects
for obj in objects: for obj in objects:
@@ -835,32 +851,60 @@ class AddQto(bpy.types.Operator):
bl_label = "Add Qto" bl_label = "Add Qto"
def execute(self, context): def execute(self, context):
self.applicable_qtos_cache = {}
name = bpy.context.active_object.BIMObjectProperties.qto_name name = bpy.context.active_object.BIMObjectProperties.qto_name
if name not in schema.ifc.qtos: if name not in ifcopenshell.util.pset.qtos:
return {"FINISHED"} return {"FINISHED"}
qto = bpy.context.active_object.BIMObjectProperties.qtos.add() for obj in bpy.context.selected_objects:
qto.name = name if "/" not in obj.name or obj.BIMObjectProperties.qtos.find(name) != -1:
for prop_name in schema.ifc.qtos[name]["HasPropertyTemplates"].keys(): continue
prop = qto.properties.add() applicable_qtos = self.get_applicable_qtos(obj.name.split("/")[0])
prop.name = prop_name if name not in applicable_qtos:
continue
qto = obj.BIMObjectProperties.qtos.add()
qto.name = name
for prop_name in ifcopenshell.util.pset.qtos[name]["HasPropertyTemplates"].keys():
prop = qto.properties.add()
prop.name = prop_name
return {"FINISHED"} return {"FINISHED"}
def get_applicable_qtos(self, ifc_class):
if ifc_class not in self.applicable_qtos_cache:
self.applicable_qtos_cache[ifc_class] = ifcopenshell.util.pset.get_applicable_psetqtos(
bpy.context.scene.BIMProperties.export_schema, ifc_class, is_qto=True
)
return self.applicable_qtos_cache[ifc_class]
class AddPset(bpy.types.Operator): class AddPset(bpy.types.Operator):
bl_idname = "bim.add_pset" bl_idname = "bim.add_pset"
bl_label = "Add Pset" bl_label = "Add Pset"
def execute(self, context): def execute(self, context):
pset_name = bpy.context.active_object.BIMObjectProperties.pset_name self.applicable_psets_cache = {}
if pset_name not in schema.ifc.psets: name = bpy.context.active_object.BIMObjectProperties.pset_name
if name not in ifcopenshell.util.pset.psets:
return {"FINISHED"} return {"FINISHED"}
pset = bpy.context.active_object.BIMObjectProperties.psets.add() for obj in bpy.context.selected_objects:
pset.name = pset_name if "/" not in obj.name or obj.BIMObjectProperties.psets.find(name) != -1:
for prop_name in schema.ifc.psets[pset_name]["HasPropertyTemplates"].keys(): continue
prop = pset.properties.add() applicable_psets = self.get_applicable_psets(obj.name.split("/")[0])
prop.name = prop_name if name not in applicable_psets:
continue
pset = obj.BIMObjectProperties.psets.add()
pset.name = name
for prop_name in ifcopenshell.util.pset.psets[name]["HasPropertyTemplates"].keys():
prop = pset.properties.add()
prop.name = prop_name
return {"FINISHED"} return {"FINISHED"}
def get_applicable_psets(self, ifc_class):
if ifc_class not in self.applicable_psets_cache:
self.applicable_psets_cache[ifc_class] = ifcopenshell.util.pset.get_applicable_psetqtos(
bpy.context.scene.BIMProperties.export_schema, ifc_class, is_pset=True
)
return self.applicable_psets_cache[ifc_class]
class RemovePset(bpy.types.Operator): class RemovePset(bpy.types.Operator):
bl_idname = "bim.remove_pset" bl_idname = "bim.remove_pset"
@@ -868,7 +912,13 @@ class RemovePset(bpy.types.Operator):
pset_index: bpy.props.IntProperty() pset_index: bpy.props.IntProperty()
def execute(self, context): def execute(self, context):
bpy.context.active_object.BIMObjectProperties.psets.remove(self.pset_index) name = bpy.context.active_object.BIMObjectProperties.psets[self.pset_index].name
for obj in bpy.context.selected_objects:
if "/" not in obj.name:
continue
index = obj.BIMObjectProperties.psets.find(name)
if index != -1:
obj.BIMObjectProperties.psets.remove(index)
return {"FINISHED"} return {"FINISHED"}
@@ -878,7 +928,13 @@ class RemoveQto(bpy.types.Operator):
index: bpy.props.IntProperty() index: bpy.props.IntProperty()
def execute(self, context): def execute(self, context):
bpy.context.active_object.BIMObjectProperties.qtos.remove(self.index) name = bpy.context.active_object.BIMObjectProperties.qtos[self.index].name
for obj in bpy.context.selected_objects:
if "/" not in obj.name:
continue
index = obj.BIMObjectProperties.qtos.find(name)
if index != -1:
obj.BIMObjectProperties.qtos.remove(index)
return {"FINISHED"} return {"FINISHED"}
@@ -1221,9 +1277,18 @@ class AddAttribute(bpy.types.Operator):
bl_label = "Add Attribute" bl_label = "Add Attribute"
def execute(self, context): def execute(self, context):
if bpy.context.active_object.BIMObjectProperties.applicable_attributes: if not bpy.context.active_object.BIMObjectProperties.applicable_attributes:
attribute = bpy.context.active_object.BIMObjectProperties.attributes.add() return {"FINISHED"}
attribute.name = bpy.context.active_object.BIMObjectProperties.applicable_attributes name = bpy.context.active_object.BIMObjectProperties.applicable_attributes
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
for obj in bpy.context.selected_objects:
if "/" not in obj.name or obj.BIMObjectProperties.attributes.find(name) != -1:
continue
entity = schema.declaration_by_name(obj.name.split("/")[0])
if name not in [a.name() for a in entity.all_attributes()]:
continue
attribute = obj.BIMObjectProperties.attributes.add()
attribute.name = name
if attribute.name == "GlobalId": if attribute.name == "GlobalId":
attribute.string_value = ifcopenshell.guid.new() attribute.string_value = ifcopenshell.guid.new()
return {"FINISHED"} return {"FINISHED"}
@@ -1246,7 +1311,13 @@ class RemoveAttribute(bpy.types.Operator):
attribute_index: bpy.props.IntProperty() attribute_index: bpy.props.IntProperty()
def execute(self, context): def execute(self, context):
bpy.context.active_object.BIMObjectProperties.attributes.remove(self.attribute_index) name = bpy.context.active_object.BIMObjectProperties.attributes[self.attribute_index].name
for obj in bpy.context.selected_objects:
if "/" not in obj.name:
continue
index = obj.BIMObjectProperties.attributes.find(name)
if index != -1:
obj.BIMObjectProperties.attributes.remove(index)
return {"FINISHED"} return {"FINISHED"}
@@ -2714,7 +2785,6 @@ class CopyPropertyToSelection(bpy.types.Operator):
def execute(self, context): def execute(self, context):
self.applicable_psets_cache = {} self.applicable_psets_cache = {}
self.empty = ifcopenshell.file()
for obj in bpy.context.selected_objects: for obj in bpy.context.selected_objects:
if "/" not in obj.name: if "/" not in obj.name:
continue continue
@@ -2725,7 +2795,7 @@ class CopyPropertyToSelection(bpy.types.Operator):
continue continue
pset = obj.BIMObjectProperties.psets.add() pset = obj.BIMObjectProperties.psets.add()
pset.name = self.pset_name pset.name = self.pset_name
for template_prop_name in schema.ifc.psets[self.pset_name]["HasPropertyTemplates"].keys(): for template_prop_name in ifcopenshell.util.pset.psets[self.pset_name]["HasPropertyTemplates"].keys():
prop = pset.properties.add() prop = pset.properties.add()
prop.name = template_prop_name prop.name = template_prop_name
prop = pset.properties.get(self.prop_name) prop = pset.properties.get(self.prop_name)
@@ -2733,16 +2803,12 @@ class CopyPropertyToSelection(bpy.types.Operator):
prop.string_value = self.prop_value prop.string_value = self.prop_value
return {"FINISHED"} return {"FINISHED"}
# TODO: move into util module. See bug #971 def get_applicable_psets(self, ifc_class):
def get_applicable_psets(self, element_class): if ifc_class not in self.applicable_psets_cache:
if element_class not in self.applicable_psets_cache: self.applicable_psets_cache[ifc_class] = ifcopenshell.util.pset.get_applicable_psetqtos(
element = self.empty.create_entity(element_class) bpy.context.scene.BIMProperties.export_schema, ifc_class, is_pset=True
applicable_psets = [] )
for ifc_class, pset_names in schema.ifc.applicable_psets.items(): return self.applicable_psets_cache[ifc_class]
if element.is_a(ifc_class):
applicable_psets.extend(pset_names)
self.applicable_psets_cache[element_class] = applicable_psets
return self.applicable_psets_cache[element_class]
class BIM_OT_ChangeClassificationLevel(bpy.types.Operator): class BIM_OT_ChangeClassificationLevel(bpy.types.Operator):
@@ -3589,11 +3655,11 @@ class GuessQuantity(bpy.types.Operator):
prop.string_value = str(round(quantity, 3)) prop.string_value = str(round(quantity, 3))
def add_qto(self, obj, name): def add_qto(self, obj, name):
if name not in schema.ifc.qtos: if name not in ifcopenshell.util.pset.qtos:
return return
qto = obj.BIMObjectProperties.qtos.add() qto = obj.BIMObjectProperties.qtos.add()
qto.name = name qto.name = name
for prop_name in schema.ifc.qtos[name]["HasPropertyTemplates"].keys(): for prop_name in ifcopenshell.util.pset.qtos[name]["HasPropertyTemplates"].keys():
prop = qto.properties.add() prop = qto.properties.add()
prop.name = prop_name prop.name = prop_name
return qto return qto
+10 -12
View File
@@ -2,6 +2,7 @@ import json
import os import os
import csv import csv
import ifcopenshell import ifcopenshell
import ifcopenshell.util.pset
from pathlib import Path from pathlib import Path
from . import export_ifc from . import export_ifc
from . import schema from . import schema
@@ -449,29 +450,25 @@ def refreshReferences(self, context):
context.scene.BIMProperties.classification_references.root = "" context.scene.BIMProperties.classification_references.root = ""
# TODO: move into util module. See bug #971
def getPsetNames(self, context): def getPsetNames(self, context):
global psetnames_enum global psetnames_enum
psetnames_enum.clear() psetnames_enum.clear()
if "/" in context.active_object.name and context.active_object.name.split("/")[0] in schema.ifc.elements: if "/" in context.active_object.name and context.active_object.name.split("/")[0] in schema.ifc.elements:
empty = ifcopenshell.file() pset_names = ifcopenshell.util.pset.get_applicable_psetqtos(
element = empty.create_entity(context.active_object.name.split("/")[0]) bpy.context.scene.BIMProperties.export_schema, context.active_object.name.split("/")[0], is_pset=True
for ifc_class, pset_names in schema.ifc.applicable_psets.items(): )
if element.is_a(ifc_class): psetnames_enum.extend([(p, p, "") for p in pset_names])
psetnames_enum.extend([(p, p, "") for p in pset_names])
return psetnames_enum return psetnames_enum
# TODO: move into util module. See bug #971
def getQtoNames(self, context): def getQtoNames(self, context):
global qtonames_enum global qtonames_enum
qtonames_enum.clear() qtonames_enum.clear()
if "/" in context.active_object.name and context.active_object.name.split("/")[0] in schema.ifc.elements: if "/" in context.active_object.name and context.active_object.name.split("/")[0] in schema.ifc.elements:
empty = ifcopenshell.file() qto_names = ifcopenshell.util.pset.get_applicable_psetqtos(
element = empty.create_entity(context.active_object.name.split("/")[0]) bpy.context.scene.BIMProperties.export_schema, context.active_object.name.split("/")[0], is_qto=True
for ifc_class, qto_names in schema.ifc.applicable_qtos.items(): )
if element.is_a(ifc_class): qtonames_enum.extend([(q, q, "") for q in qto_names])
qtonames_enum.extend([(q, q, "") for q in qto_names])
return qtonames_enum return qtonames_enum
@@ -1625,6 +1622,7 @@ class BoundaryCondition(PropertyGroup):
class BIMObjectProperties(PropertyGroup): class BIMObjectProperties(PropertyGroup):
is_reassigning_class: BoolProperty(name="Is Reassigning Class")
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId) global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
attributes: CollectionProperty(name="Attributes", type=Attribute) attributes: CollectionProperty(name="Attributes", type=Attribute)
relating_type: PointerProperty(name="Type Product", type=bpy.types.Object) relating_type: PointerProperty(name="Type Product", type=bpy.types.Object)
+3 -17
View File
@@ -1,6 +1,7 @@
import os import os
import json import json
import ifcopenshell import ifcopenshell
import ifcopenshell.util.pset
import bpy import bpy
from pathlib import Path from pathlib import Path
@@ -30,14 +31,10 @@ class IfcSchema:
self.property_files = [] self.property_files = []
property_paths = Path(os.path.join(self.data_dir, "pset")).glob("*.ifc") property_paths = Path(os.path.join(self.data_dir, "pset")).glob("*.ifc")
for path in property_paths: for path in property_paths:
self.property_files.append(ifcopenshell.open(path)) ifcopenshell.util.pset.load_property_set_template(path)
self.property_files.append(ifcopenshell.open(os.path.join(self.schema_dir, "Pset_IFC4_ADD2.ifc"))) ifcopenshell.util.pset.load_property_set_template(os.path.join(self.schema_dir, "Pset_IFC4_ADD2.ifc"))
self.classification_files = {} self.classification_files = {}
self.psets = {}
self.qtos = {}
self.applicable_psets = {}
self.applicable_qtos = {}
self.classifications = {} self.classifications = {}
self.load() self.load()
@@ -50,17 +47,6 @@ class IfcSchema:
with open(os.path.join(self.schema_dir, "ifc_types_IFC4.json")) as f: with open(os.path.join(self.schema_dir, "ifc_types_IFC4.json")) as f:
self.type_map = json.load(f) self.type_map = json.load(f)
for property_file in self.property_files:
for prop in property_file.by_type("IfcPropertySetTemplate"):
if prop.Name[0:4] == "Qto_":
self.qtos[prop.Name] = {"HasPropertyTemplates": {p.Name: p for p in prop.HasPropertyTemplates}}
entity = prop.ApplicableEntity if prop.ApplicableEntity else "IfcRoot"
self.applicable_qtos.setdefault(entity, []).append(prop.Name)
else:
self.psets[prop.Name] = {"HasPropertyTemplates": {p.Name: p for p in prop.HasPropertyTemplates}}
entity = prop.ApplicableEntity if prop.ApplicableEntity else "IfcRoot"
self.applicable_psets.setdefault(entity, []).append(prop.Name)
def load_classification(self, name, classification_index=None): def load_classification(self, name, classification_index=None):
if name not in self.classifications: if name not in self.classifications:
if classification_index is not None: if classification_index is not None:
+26 -19
View File
@@ -21,24 +21,28 @@ class BIM_PT_object(Panel):
props = context.active_object.BIMObjectProperties props = context.active_object.BIMObjectProperties
bim_properties = context.scene.BIMProperties bim_properties = context.scene.BIMProperties
row = layout.row() if props.is_reassigning_class or "/" not in context.active_object.name:
row.prop(bim_properties, "ifc_product")
row = layout.row()
row.prop(bim_properties, "ifc_class")
if bim_properties.ifc_predefined_type:
row = layout.row() row = layout.row()
row.prop(bim_properties, "ifc_predefined_type") row.prop(bim_properties, "ifc_product")
if bim_properties.ifc_predefined_type == "USERDEFINED":
row = layout.row() row = layout.row()
row.prop(bim_properties, "ifc_userdefined_type") row.prop(bim_properties, "ifc_class")
row = layout.row(align=True) if bim_properties.ifc_predefined_type:
if "Ifc" not in context.active_object.name: row = layout.row()
op = row.operator("bim.assign_class") row.prop(bim_properties, "ifc_predefined_type")
if bim_properties.ifc_predefined_type == "USERDEFINED":
row = layout.row()
row.prop(bim_properties, "ifc_userdefined_type")
row = layout.row(align=True)
if "Ifc" not in context.active_object.name:
op = row.operator("bim.assign_class")
else:
op = row.operator("bim.assign_class")
op.object_name = context.active_object.name
op = row.operator("bim.unassign_class", icon="X", text="")
op.object_name = context.active_object.name
else: else:
op = row.operator("bim.assign_class", text="Reassign IFC Class") row = layout.row()
op.object_name = context.active_object.name row.operator("bim.reassign_class", text="Reassign IFC Class")
op = row.operator("bim.unassign_class", icon="X", text="")
op.object_name = context.active_object.name
if "Ifc" not in context.active_object.name: if "Ifc" not in context.active_object.name:
return return
@@ -1894,10 +1898,13 @@ class BIM_UL_classifications(bpy.types.UIList):
class BIM_ADDON_preferences(bpy.types.AddonPreferences): class BIM_ADDON_preferences(bpy.types.AddonPreferences):
bl_idname = "blenderbim" bl_idname = "blenderbim"
svg2pdf_command: StringProperty(name="SVG to PDF Command") svg2pdf_command: StringProperty(name="SVG to PDF Command", description="E.g. [['inkscape', svg, '-o', pdf]]")
svg2dxf_command: StringProperty(name="SVG to DXF Command") svg2dxf_command: StringProperty(
svg_command: StringProperty(name="SVG Command") name="SVG to DXF Command",
pdf_command: StringProperty(name="PDF Command") description="E.g. [['inkscape', svg, '-o', eps], ['pstoedit', '-dt', '-f', 'dxf:-polyaslines -mm', eps, dxf, '-psarg', '-dNOSAFER']]",
)
svg_command: StringProperty(name="SVG Command", description="E.g. [['firefox-bin', path]]")
pdf_command: StringProperty(name="PDF Command", description="E.g. [['firefox-bin', path]]")
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@@ -0,0 +1,39 @@
import ifcopenshell
property_set_template_files = []
psets = {}
qtos = {}
applicable_psets = {}
applicable_qtos = {}
def load_property_set_template(path):
property_set_template_files.append(ifcopenshell.open(path))
for prop in property_set_template_files[-1].by_type("IfcPropertySetTemplate"):
if prop.Name[0:4] == "Qto_":
qtos[prop.Name] = {"HasPropertyTemplates": {p.Name: p for p in prop.HasPropertyTemplates}}
entity = prop.ApplicableEntity if prop.ApplicableEntity else "IfcRoot"
applicable_qtos.setdefault(entity, []).append(prop.Name)
else:
psets[prop.Name] = {"HasPropertyTemplates": {p.Name: p for p in prop.HasPropertyTemplates}}
entity = prop.ApplicableEntity if prop.ApplicableEntity else "IfcRoot"
applicable_psets.setdefault(entity, []).append(prop.Name)
def get_applicable_psetqtos(schema_version, ifc_class, is_pset=False, is_qto=False):
def is_a(entity, ifc_class):
if entity.name() == ifc_class:
return True
return is_a(entity.supertype(), ifc_class) if entity.supertype() else False
results = []
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_version)
entity = schema.declaration_by_name(ifc_class)
if is_pset:
search_items = applicable_psets.items()
elif is_qto:
search_items = applicable_qtos.items()
for ifc_class, pset_names in search_items:
if is_a(entity, ifc_class):
results.extend(pset_names)
return results
+58
View File
@@ -0,0 +1,58 @@
import ifcopenshell
import ifcopenshell.util.selector
class Patcher:
def __init__(self, src, file, logger, args=None):
self.src = src
self.file = file
self.logger = logger
self.args = args
def patch(self):
self.contained_ins = {}
self.aggregates = {}
self.new = ifcopenshell.file(schema=self.file.wrapped_data.schema)
self.owner_history = None
for owner_history in self.file.by_type("IfcOwnerHistory"):
self.owner_history = self.new.add(owner_history)
break
selector = ifcopenshell.util.selector.Selector()
for element in selector.parse(self.file, self.args[0]):
self.add_element(element)
self.create_spatial_tree()
self.file = self.new
def add_element(self, element):
new_element = self.new.add(element)
for rel in element.ContainedInStructure:
spatial_element = rel.RelatingStructure
new_spatial_element = self.new.add(spatial_element)
self.contained_ins.setdefault(spatial_element.GlobalId, set()).add(new_element)
self.add_spatial_tree(spatial_element, new_spatial_element)
def add_spatial_tree(self, spatial_element, new_spatial_element):
for rel in spatial_element.Decomposes:
new = self.new.add(rel.RelatingObject)
self.aggregates.setdefault(rel.RelatingObject.GlobalId, set()).add(new_spatial_element)
self.add_spatial_tree(rel.RelatingObject, new)
def create_spatial_tree(self):
for relating_structure, related_elements in self.contained_ins.items():
self.new.createIfcRelContainedInSpatialStructure(
ifcopenshell.guid.new(),
self.owner_history,
None,
None,
list(related_elements),
self.new.by_guid(relating_structure),
)
for relating_object, related_objects in self.aggregates.items():
self.new.createIfcRelAggregates(
ifcopenshell.guid.new(),
self.owner_history,
None,
None,
self.new.by_guid(relating_object),
list(related_objects),
)