mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 05:52:33 +00:00
Rework python pset module (#1221)
New features ============ * Handle all syntax for ApplicableEntity as defined in IFC documentation. (drawback it increase request time by ~2/3) * Allow to get applicable psets directly from template definition without caching. This allow more general purpose usages. (drawback it increase request time by ~2.4) To notice / discuss =================== * `ifcwrap/CmakeLists` was installing only `.py` and `.bnf` files from `ifcopenshell-python`. Why ? It now copy all files. Is it an issue ? * property template file is now stored in ifcopenshell python module to allow usage from every softwares. It was before only available for blenderbim addon. * psets and qtos are now optionnally cached at object instead of module level. This allow to work with multiple schema in the same python interpreter. (eg. might help conversion between schemas) * in blenderbim addon psetqto are now stored in `schema.psetqto`.
This commit is contained in:
@@ -8,7 +8,6 @@ import os
|
||||
import zipfile
|
||||
import tempfile
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.pset
|
||||
import ifcopenshell.util.schema
|
||||
from pathlib import Path
|
||||
from mathutils import Vector, Matrix
|
||||
@@ -477,10 +476,10 @@ class IfcParser:
|
||||
return
|
||||
qto_names = self.get_applicable_qtos(ifc_class)
|
||||
for name in qto_names:
|
||||
if name not in ifcopenshell.util.pset.qtos:
|
||||
if name not in schema.ifc.psetqto.qtos:
|
||||
continue
|
||||
has_automatic_value = False
|
||||
props = ifcopenshell.util.pset.qtos[name]["HasPropertyTemplates"].keys()
|
||||
props = schema.ifc.psetqto.qtos[name]["HasPropertyTemplates"].keys()
|
||||
guessed_values = {}
|
||||
for prop_name in props:
|
||||
value = self.qto_calculator.guess_quantity(prop_name, props, obj)
|
||||
@@ -1699,12 +1698,12 @@ class IfcExporter:
|
||||
pset["ifc"] = self.file.create_entity("IfcMaterialProperties", **pset["attributes"])
|
||||
|
||||
def create_qto_properties(self, qto):
|
||||
if qto["attributes"]["Name"] in ifcopenshell.util.pset.qtos:
|
||||
if qto["attributes"]["Name"] in schema.ifc.psetqto.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 ifcopenshell.util.pset.psets:
|
||||
if pset["attributes"]["Name"] in schema.ifc.psetqto.psets:
|
||||
return self.create_templated_pset_properties(pset)
|
||||
return self.create_custom_pset_properties(pset)
|
||||
|
||||
@@ -1737,7 +1736,7 @@ class IfcExporter:
|
||||
|
||||
def create_templated_pset_properties(self, pset):
|
||||
properties = []
|
||||
templates = ifcopenshell.util.pset.psets[pset["attributes"]["Name"]]["HasPropertyTemplates"]
|
||||
templates = schema.ifc.psetqto.psets[pset["attributes"]["Name"]]["HasPropertyTemplates"]
|
||||
for name, data in templates.items():
|
||||
if name not in pset["raw"]:
|
||||
continue
|
||||
@@ -1764,7 +1763,7 @@ class IfcExporter:
|
||||
|
||||
def create_templated_qto_properties(self, qto):
|
||||
properties = []
|
||||
templates = ifcopenshell.util.pset.qtos[qto["attributes"]["Name"]]["HasPropertyTemplates"]
|
||||
templates = schema.ifc.psetqto.qtos[qto["attributes"]["Name"]]["HasPropertyTemplates"]
|
||||
for name, data in templates.items():
|
||||
if name not in qto["raw"]:
|
||||
continue
|
||||
|
||||
@@ -3,7 +3,6 @@ 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
|
||||
@@ -22,6 +21,7 @@ from itertools import cycle
|
||||
from datetime import datetime
|
||||
from . import helper
|
||||
from . import ifc
|
||||
from . import schema
|
||||
|
||||
|
||||
class FileCopy(threading.Thread):
|
||||
@@ -1394,8 +1394,8 @@ class IfcImporter:
|
||||
def add_pset(self, pset, props):
|
||||
new_pset = props.psets.add()
|
||||
new_pset.name = pset.Name
|
||||
if new_pset.name in ifcopenshell.util.pset.psets:
|
||||
for prop_name in ifcopenshell.util.pset.psets[new_pset.name]["HasPropertyTemplates"].keys():
|
||||
if new_pset.name in schema.ifc.psetqto.psets:
|
||||
for prop_name in schema.ifc.psetqto.psets[new_pset.name]["HasPropertyTemplates"].keys():
|
||||
prop = new_pset.properties.add()
|
||||
prop.name = prop_name
|
||||
try:
|
||||
@@ -1421,8 +1421,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 ifcopenshell.util.pset.qtos:
|
||||
for prop_name in ifcopenshell.util.pset.qtos[new_qto.name]["HasPropertyTemplates"].keys():
|
||||
if new_qto.name in schema.ifc.psetqto.qtos:
|
||||
for prop_name in schema.ifc.psetqto.qtos[new_qto.name]["HasPropertyTemplates"].keys():
|
||||
prop = new_qto.properties.add()
|
||||
prop.name = prop_name
|
||||
for prop in qto.Quantities:
|
||||
|
||||
@@ -10,7 +10,6 @@ import subprocess
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.selector
|
||||
import ifcopenshell.util.geolocation
|
||||
import ifcopenshell.util.pset
|
||||
import ifcopenshell.util.schema
|
||||
import tempfile
|
||||
from . import export_ifc
|
||||
@@ -588,7 +587,7 @@ class AddQto(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
self.applicable_qtos_cache = {}
|
||||
name = bpy.context.active_object.BIMObjectProperties.qto_name
|
||||
if name not in ifcopenshell.util.pset.qtos:
|
||||
if name not in schema.ifc.psetqto.qtos:
|
||||
return {"FINISHED"}
|
||||
for obj in bpy.context.selected_objects:
|
||||
if "/" not in obj.name or obj.BIMObjectProperties.qtos.find(name) != -1:
|
||||
@@ -598,16 +597,14 @@ class AddQto(bpy.types.Operator):
|
||||
continue
|
||||
qto = obj.BIMObjectProperties.qtos.add()
|
||||
qto.name = name
|
||||
for prop_name in ifcopenshell.util.pset.qtos[name]["HasPropertyTemplates"].keys():
|
||||
for prop_name in schema.ifc.psetqto.qtos[name]["HasPropertyTemplates"].keys():
|
||||
prop = qto.properties.add()
|
||||
prop.name = prop_name
|
||||
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
|
||||
)
|
||||
self.applicable_qtos_cache[ifc_class] = schema.ifc.psetqto.get_applicable_names(ifc_class, qto_only=True)
|
||||
return self.applicable_qtos_cache[ifc_class]
|
||||
|
||||
|
||||
@@ -618,7 +615,7 @@ class AddPset(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
self.applicable_psets_cache = {}
|
||||
name = bpy.context.active_object.BIMObjectProperties.pset_name
|
||||
if name not in ifcopenshell.util.pset.psets:
|
||||
if name not in schema.ifc.psetqto.psets:
|
||||
return {"FINISHED"}
|
||||
for obj in bpy.context.selected_objects:
|
||||
if "/" not in obj.name or obj.BIMObjectProperties.psets.find(name) != -1:
|
||||
@@ -628,16 +625,14 @@ class AddPset(bpy.types.Operator):
|
||||
continue
|
||||
pset = obj.BIMObjectProperties.psets.add()
|
||||
pset.name = name
|
||||
for prop_name in ifcopenshell.util.pset.psets[name]["HasPropertyTemplates"].keys():
|
||||
for prop_name in schema.ifc.psetqto.psets[name]["HasPropertyTemplates"].keys():
|
||||
prop = pset.properties.add()
|
||||
prop.name = prop_name
|
||||
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
|
||||
)
|
||||
self.applicable_psets_cache[ifc_class] = schema.ifc.psetqto.get_applicable_names(ifc_class, pset_only=True)
|
||||
return self.applicable_psets_cache[ifc_class]
|
||||
|
||||
|
||||
@@ -680,13 +675,13 @@ class AddMaterialPset(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
material = bpy.context.active_object.active_material
|
||||
name = material.BIMMaterialProperties.pset_name
|
||||
if name not in ifcopenshell.util.pset.psets:
|
||||
if name not in schema.ifc.psetqto.psets:
|
||||
return {"FINISHED"}
|
||||
if material.BIMMaterialProperties.psets.find(name) != -1:
|
||||
return {"FINISHED"}
|
||||
pset = material.BIMMaterialProperties.psets.add()
|
||||
pset.name = name
|
||||
for prop_name in ifcopenshell.util.pset.psets[name]["HasPropertyTemplates"].keys():
|
||||
for prop_name in schema.ifc.psetqto.psets[name]["HasPropertyTemplates"].keys():
|
||||
prop = pset.properties.add()
|
||||
prop.name = prop_name
|
||||
return {"FINISHED"}
|
||||
@@ -2649,7 +2644,7 @@ class CopyPropertyToSelection(bpy.types.Operator):
|
||||
continue
|
||||
pset = obj.BIMObjectProperties.psets.add()
|
||||
pset.name = self.pset_name
|
||||
for template_prop_name in ifcopenshell.util.pset.psets[self.pset_name]["HasPropertyTemplates"].keys():
|
||||
for template_prop_name in schema.ifc.psetqto.psets[self.pset_name]["HasPropertyTemplates"].keys():
|
||||
prop = pset.properties.add()
|
||||
prop.name = template_prop_name
|
||||
prop = pset.properties.get(self.prop_name)
|
||||
@@ -2659,9 +2654,7 @@ class CopyPropertyToSelection(bpy.types.Operator):
|
||||
|
||||
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
|
||||
)
|
||||
self.applicable_psets_cache[ifc_class] = schema.ifc.psetqto.get_applicable_names(ifc_class, pset_only=True)
|
||||
return self.applicable_psets_cache[ifc_class]
|
||||
|
||||
|
||||
@@ -3573,11 +3566,11 @@ class GuessQuantity(bpy.types.Operator):
|
||||
prop.string_value = str(round(quantity, 3))
|
||||
|
||||
def add_qto(self, obj, name):
|
||||
if name not in ifcopenshell.util.pset.qtos:
|
||||
if name not in schema.ifc.psetqto.qtos:
|
||||
return
|
||||
qto = obj.BIMObjectProperties.qtos.add()
|
||||
qto.name = name
|
||||
for prop_name in ifcopenshell.util.pset.qtos[name]["HasPropertyTemplates"].keys():
|
||||
for prop_name in schema.ifc.psetqto.qtos[name]["HasPropertyTemplates"].keys():
|
||||
prop = qto.properties.add()
|
||||
prop.name = prop_name
|
||||
return qto
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import json
|
||||
import os
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.pset
|
||||
from pathlib import Path
|
||||
from . import export_ifc
|
||||
from . import schema
|
||||
@@ -433,9 +432,7 @@ 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:
|
||||
pset_names = ifcopenshell.util.pset.get_applicable_psetqtos(
|
||||
bpy.context.scene.BIMProperties.export_schema, context.active_object.name.split("/")[0], is_pset=True
|
||||
)
|
||||
pset_names = schema.ifc.psetqto.get_applicable_names(context.active_object.name.split("/")[0], pset_only=True)
|
||||
psetnames_enum.extend([(p, p, "") for p in pset_names])
|
||||
return psetnames_enum
|
||||
|
||||
@@ -443,9 +440,7 @@ def getPsetNames(self, context):
|
||||
def getMaterialPsetNames(self, context):
|
||||
global materialpsetnames_enum
|
||||
materialpsetnames_enum.clear()
|
||||
pset_names = ifcopenshell.util.pset.get_applicable_psetqtos(
|
||||
bpy.context.scene.BIMProperties.export_schema, "IfcMaterial", is_pset=True
|
||||
)
|
||||
pset_names = schema.ifc.psetqto.get_applicable_names("IfcMaterial", pset_only=True)
|
||||
materialpsetnames_enum.extend([(p, p, "") for p in pset_names])
|
||||
return materialpsetnames_enum
|
||||
|
||||
@@ -454,9 +449,7 @@ 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:
|
||||
qto_names = ifcopenshell.util.pset.get_applicable_psetqtos(
|
||||
bpy.context.scene.BIMProperties.export_schema, context.active_object.name.split("/")[0], is_qto=True
|
||||
)
|
||||
qto_names = schema.ifc.psetqto.get_applicable_names(context.active_object.name.split("/")[0], qto_only=True)
|
||||
qtonames_enum.extend([(q, q, "") for q in qto_names])
|
||||
return qtonames_enum
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
class IfcSchema:
|
||||
def __init__(self):
|
||||
self.schema_dir = os.path.join(cwd, "schema") # TODO: make configurable
|
||||
self.data_dir = os.path.join(cwd, "data") # TODO: make configurable
|
||||
self.schema_dir = Path(cwd).joinpath("schema") # TODO: make configurable
|
||||
self.data_dir = Path(cwd).joinpath("data") # TODO: make configurable
|
||||
# TODO: Make it less troublesome
|
||||
self.products = [
|
||||
"IfcContext",
|
||||
@@ -29,10 +29,10 @@ class IfcSchema:
|
||||
self.elements = {}
|
||||
|
||||
self.property_files = []
|
||||
property_paths = Path(os.path.join(self.data_dir, "pset")).glob("*.ifc")
|
||||
property_paths = self.data_dir.joinpath("pset").glob("*.ifc")
|
||||
self.psetqto = ifcopenshell.util.pset.PsetQto("IFC4", use_cache=True)
|
||||
for path in property_paths:
|
||||
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.psetqto.templates.append(ifcopenshell.open(path))
|
||||
|
||||
self.classification_files = {}
|
||||
self.classifications = {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user