mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-05 23:41:44 +00:00
Fix #971. New utility function to query which psets/qtos apply to a class.
This commit is contained in:
@@ -6,12 +6,13 @@ import datetime
|
||||
import os
|
||||
import zipfile
|
||||
import tempfile
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.pset
|
||||
from pathlib import Path
|
||||
from mathutils import Vector, Matrix
|
||||
from .helper import SIUnitHelper, get_representation_elements
|
||||
from . import schema
|
||||
from . import ifc
|
||||
import ifcopenshell
|
||||
import addon_utils
|
||||
|
||||
|
||||
@@ -466,10 +467,10 @@ class IfcParser:
|
||||
return
|
||||
qto_names = self.get_applicable_qtos(ifc_class)
|
||||
for name in qto_names:
|
||||
if name not in schema.ifc.qtos:
|
||||
if name not in ifcopenshell.util.pset.qtos:
|
||||
continue
|
||||
has_automatic_value = False
|
||||
props = schema.ifc.qtos[name]["HasPropertyTemplates"].keys()
|
||||
props = ifcopenshell.util.pset.qtos[name]["HasPropertyTemplates"].keys()
|
||||
guessed_values = {}
|
||||
for prop_name in props:
|
||||
value = self.qto_calculator.guess_quantity(prop_name, props, obj)
|
||||
@@ -1666,12 +1667,12 @@ class IfcExporter:
|
||||
)
|
||||
|
||||
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_custom_qto_properties(qto)
|
||||
|
||||
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_custom_pset_properties(pset)
|
||||
|
||||
@@ -1704,7 +1705,7 @@ class IfcExporter:
|
||||
|
||||
def create_templated_pset_properties(self, pset):
|
||||
properties = []
|
||||
templates = schema.ifc.psets[pset["attributes"]["Name"]]["HasPropertyTemplates"]
|
||||
templates = ifcopenshell.util.pset.psets[pset["attributes"]["Name"]]["HasPropertyTemplates"]
|
||||
for name, data in templates.items():
|
||||
if name not in pset["raw"]:
|
||||
continue
|
||||
@@ -1731,7 +1732,7 @@ class IfcExporter:
|
||||
|
||||
def create_templated_qto_properties(self, qto):
|
||||
properties = []
|
||||
templates = schema.ifc.qtos[qto["attributes"]["Name"]]["HasPropertyTemplates"]
|
||||
templates = ifcopenshell.util.pset.qtos[qto["attributes"]["Name"]]["HasPropertyTemplates"]
|
||||
for name, data in templates.items():
|
||||
if name not in qto["raw"]:
|
||||
continue
|
||||
@@ -3157,10 +3158,7 @@ class IfcExporter:
|
||||
)
|
||||
|
||||
def relate_spaces_to_boundary_elements(self):
|
||||
for (
|
||||
relating_space_index,
|
||||
relationships,
|
||||
) in self.ifc_parser.rel_space_boundaries.items():
|
||||
for (relating_space_index, relationships,) in self.ifc_parser.rel_space_boundaries.items():
|
||||
for relationship in relationships:
|
||||
relationship["attributes"]["GlobalId"] = ifcopenshell.guid.new()
|
||||
relationship["attributes"]["RelatedBuildingElement"] = self.ifc_parser.products[
|
||||
|
||||
@@ -3,6 +3,7 @@ import ifcopenshell.geom
|
||||
import ifcopenshell.util.geolocation
|
||||
import ifcopenshell.util.selector
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.pset
|
||||
import bpy
|
||||
import bmesh
|
||||
import os
|
||||
@@ -206,8 +207,8 @@ class MaterialCreator:
|
||||
def add_pset(self, pset, obj):
|
||||
new_pset = obj.BIMMaterialProperties.psets.add()
|
||||
new_pset.name = pset.Name
|
||||
if new_pset.name in schema.ifc.psets:
|
||||
for prop_name in schema.ifc.psets[new_pset.name]["HasPropertyTemplates"].keys():
|
||||
if new_pset.name in ifcopenshell.util.pset.psets:
|
||||
for prop_name in ifcopenshell.util.pset.psets[new_pset.name]["HasPropertyTemplates"].keys():
|
||||
prop = new_pset.properties.add()
|
||||
prop.name = prop_name
|
||||
for prop in pset.Properties:
|
||||
@@ -1338,8 +1339,8 @@ class IfcImporter:
|
||||
def add_pset(self, pset, obj):
|
||||
new_pset = obj.BIMObjectProperties.psets.add()
|
||||
new_pset.name = pset.Name
|
||||
if new_pset.name in schema.ifc.psets:
|
||||
for prop_name in schema.ifc.psets[new_pset.name]["HasPropertyTemplates"].keys():
|
||||
if new_pset.name in ifcopenshell.util.pset.psets:
|
||||
for prop_name in ifcopenshell.util.pset.psets[new_pset.name]["HasPropertyTemplates"].keys():
|
||||
prop = new_pset.properties.add()
|
||||
prop.name = prop_name
|
||||
# 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):
|
||||
new_qto = obj.BIMObjectProperties.qtos.add()
|
||||
new_qto.name = str(qto.Name)
|
||||
if new_qto.name in schema.ifc.qtos:
|
||||
for prop_name in schema.ifc.qtos[new_qto.name]["HasPropertyTemplates"].keys():
|
||||
if new_qto.name in ifcopenshell.util.pset.qtos:
|
||||
for prop_name in ifcopenshell.util.pset.qtos[new_qto.name]["HasPropertyTemplates"].keys():
|
||||
prop = new_qto.properties.add()
|
||||
prop.name = prop_name
|
||||
for prop in qto.Quantities:
|
||||
|
||||
@@ -9,6 +9,7 @@ import subprocess
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.selector
|
||||
import ifcopenshell.util.geolocation
|
||||
import ifcopenshell.util.pset
|
||||
import tempfile
|
||||
from . import export_ifc
|
||||
from . import import_ifc
|
||||
@@ -836,11 +837,11 @@ class AddQto(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
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"}
|
||||
qto = bpy.context.active_object.BIMObjectProperties.qtos.add()
|
||||
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.name = prop_name
|
||||
return {"FINISHED"}
|
||||
@@ -852,11 +853,11 @@ class AddPset(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
pset_name = bpy.context.active_object.BIMObjectProperties.pset_name
|
||||
if pset_name not in schema.ifc.psets:
|
||||
if pset_name not in ifcopenshell.util.pset.psets:
|
||||
return {"FINISHED"}
|
||||
pset = bpy.context.active_object.BIMObjectProperties.psets.add()
|
||||
pset.name = pset_name
|
||||
for prop_name in schema.ifc.psets[pset_name]["HasPropertyTemplates"].keys():
|
||||
for prop_name in ifcopenshell.util.pset.psets[pset_name]["HasPropertyTemplates"].keys():
|
||||
prop = pset.properties.add()
|
||||
prop.name = prop_name
|
||||
return {"FINISHED"}
|
||||
@@ -2729,7 +2730,6 @@ class CopyPropertyToSelection(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
self.applicable_psets_cache = {}
|
||||
self.empty = ifcopenshell.file()
|
||||
for obj in bpy.context.selected_objects:
|
||||
if "/" not in obj.name:
|
||||
continue
|
||||
@@ -2740,7 +2740,7 @@ class CopyPropertyToSelection(bpy.types.Operator):
|
||||
continue
|
||||
pset = obj.BIMObjectProperties.psets.add()
|
||||
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.name = template_prop_name
|
||||
prop = pset.properties.get(self.prop_name)
|
||||
@@ -2748,15 +2748,11 @@ class CopyPropertyToSelection(bpy.types.Operator):
|
||||
prop.string_value = self.prop_value
|
||||
return {"FINISHED"}
|
||||
|
||||
# TODO: move into util module. See bug #971
|
||||
def get_applicable_psets(self, element_class):
|
||||
if element_class not in self.applicable_psets_cache:
|
||||
element = self.empty.create_entity(element_class)
|
||||
applicable_psets = []
|
||||
for ifc_class, pset_names in schema.ifc.applicable_psets.items():
|
||||
if element.is_a(ifc_class):
|
||||
applicable_psets.extend(pset_names)
|
||||
self.applicable_psets_cache[element_class] = applicable_psets
|
||||
self.applicable_psets_cache[element_class] = ifcopenshell.util.pset.get_applicable_psetqtos(
|
||||
bpy.context.scene.BIMProperties.export_schema, element_class, is_pset=True
|
||||
)
|
||||
return self.applicable_psets_cache[element_class]
|
||||
|
||||
|
||||
@@ -3604,11 +3600,11 @@ class GuessQuantity(bpy.types.Operator):
|
||||
prop.string_value = str(round(quantity, 3))
|
||||
|
||||
def add_qto(self, obj, name):
|
||||
if name not in schema.ifc.qtos:
|
||||
if name not in ifcopenshell.util.pset.qtos:
|
||||
return
|
||||
qto = obj.BIMObjectProperties.qtos.add()
|
||||
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.name = prop_name
|
||||
return qto
|
||||
|
||||
@@ -2,6 +2,7 @@ import json
|
||||
import os
|
||||
import csv
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.pset
|
||||
from pathlib import Path
|
||||
from . import export_ifc
|
||||
from . import schema
|
||||
@@ -429,29 +430,25 @@ def refreshReferences(self, context):
|
||||
context.scene.BIMProperties.classification_references.root = ""
|
||||
|
||||
|
||||
# TODO: move into util module. See bug #971
|
||||
def getPsetNames(self, context):
|
||||
global psetnames_enum
|
||||
psetnames_enum.clear()
|
||||
if "/" in context.active_object.name and context.active_object.name.split("/")[0] in schema.ifc.elements:
|
||||
empty = ifcopenshell.file()
|
||||
element = empty.create_entity(context.active_object.name.split("/")[0])
|
||||
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])
|
||||
pset_names = ifcopenshell.util.pset.get_applicable_psetqtos(
|
||||
bpy.context.scene.BIMProperties.export_schema, context.active_object.name.split("/")[0], is_pset=True
|
||||
)
|
||||
psetnames_enum.extend([(p, p, "") for p in pset_names])
|
||||
return psetnames_enum
|
||||
|
||||
|
||||
# TODO: move into util module. See bug #971
|
||||
def getQtoNames(self, context):
|
||||
global qtonames_enum
|
||||
qtonames_enum.clear()
|
||||
if "/" in context.active_object.name and context.active_object.name.split("/")[0] in schema.ifc.elements:
|
||||
empty = ifcopenshell.file()
|
||||
element = empty.create_entity(context.active_object.name.split("/")[0])
|
||||
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])
|
||||
qto_names = ifcopenshell.util.pset.get_applicable_psetqtos(
|
||||
bpy.context.scene.BIMProperties.export_schema, context.active_object.name.split("/")[0], is_qto=True
|
||||
)
|
||||
qtonames_enum.extend([(q, q, "") for q in qto_names])
|
||||
return qtonames_enum
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import json
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.pset
|
||||
import bpy
|
||||
from pathlib import Path
|
||||
|
||||
@@ -30,14 +31,10 @@ class IfcSchema:
|
||||
self.property_files = []
|
||||
property_paths = Path(os.path.join(self.data_dir, "pset")).glob("*.ifc")
|
||||
for path in property_paths:
|
||||
self.property_files.append(ifcopenshell.open(path))
|
||||
self.property_files.append(ifcopenshell.open(os.path.join(self.schema_dir, "Pset_IFC4_ADD2.ifc")))
|
||||
ifcopenshell.util.pset.load_property_set_template(path)
|
||||
ifcopenshell.util.pset.load_property_set_template(os.path.join(self.schema_dir, "Pset_IFC4_ADD2.ifc"))
|
||||
|
||||
self.classification_files = {}
|
||||
self.psets = {}
|
||||
self.qtos = {}
|
||||
self.applicable_psets = {}
|
||||
self.applicable_qtos = {}
|
||||
self.classifications = {}
|
||||
self.load()
|
||||
|
||||
@@ -50,17 +47,6 @@ class IfcSchema:
|
||||
with open(os.path.join(self.schema_dir, "ifc_types_IFC4.json")) as 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):
|
||||
if name not in self.classifications:
|
||||
if classification_index is not None:
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user