This commit is contained in:
Andrej730
2024-12-27 13:39:55 +05:00
parent c770776228
commit 19c1394d94
5 changed files with 20 additions and 20 deletions
@@ -38,8 +38,9 @@ class AttributesData:
def attributes(cls): def attributes(cls):
results = [] results = []
element = tool.Ifc.get_entity(bpy.context.active_object) element = tool.Ifc.get_entity(bpy.context.active_object)
assert element
data = element.get_info() data = element.get_info()
if hasattr(element, "GlobalId"): if "GlobalId" in data:
excluded_keys = ["id", "type"] excluded_keys = ["id", "type"]
else: else:
excluded_keys = ["type"] excluded_keys = ["type"]
@@ -41,6 +41,7 @@ class EnableEditingAttributes(bpy.types.Operator):
props.attributes.clear() props.attributes.clear()
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
assert element
has_inherited_predefined_type = False has_inherited_predefined_type = False
if not element.is_a("IfcTypeObject") and (element_type := ifcopenshell.util.element.get_type(element)): if not element.is_a("IfcTypeObject") and (element_type := ifcopenshell.util.element.get_type(element)):
# Allow for None due to https://github.com/buildingSMART/IFC4.3.x-development/issues/818 # Allow for None due to https://github.com/buildingSMART/IFC4.3.x-development/issues/818
+12 -16
View File
@@ -17,10 +17,12 @@
# along with Ifc5D. If not, see <http://www.gnu.org/licenses/>. # along with Ifc5D. If not, see <http://www.gnu.org/licenses/>.
import os import os
import types
import json import json
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.api.pset import ifcopenshell.api.pset
import ifcopenshell.geom
import ifcopenshell.util.unit import ifcopenshell.util.unit
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.selector import ifcopenshell.util.selector
@@ -35,6 +37,7 @@ Function = namedtuple("Function", ["measure", "name", "description"])
RULE_SET = Literal["IFC4QtoBaseQuantities", "IFC4QtoBaseQuantitiesBlender"] RULE_SET = Literal["IFC4QtoBaseQuantities", "IFC4QtoBaseQuantitiesBlender"]
rules: dict[RULE_SET, dict[str, Any]] = {} rules: dict[RULE_SET, dict[str, Any]] = {}
ResultsDict = dict[ifcopenshell.entity_instance, dict[str, dict[str, float]]] ResultsDict = dict[ifcopenshell.entity_instance, dict[str, dict[str, float]]]
QtosFormulas = dict[str, dict[str, str]]
cwd = os.path.dirname(os.path.realpath(__file__)) cwd = os.path.dirname(os.path.realpath(__file__))
for name in get_args(RULE_SET): for name in get_args(RULE_SET):
@@ -91,7 +94,7 @@ class SI2ProjectUnitConverter:
"IfcVolumeMeasure": "CUBIC_METRE", "IfcVolumeMeasure": "CUBIC_METRE",
} }
def convert(self, value, measure): def convert(self, value: float, measure: str) -> float:
if measure_unit := self.project_units.get(measure, None): if measure_unit := self.project_units.get(measure, None):
return ifcopenshell.util.unit.convert(value, None, self.si_names[measure], *measure_unit) return ifcopenshell.util.unit.convert(value, None, self.si_names[measure], *measure_unit)
return value return value
@@ -101,6 +104,7 @@ class IfcOpenShell:
"""Calculates Model body context geometry using the default IfcOpenShell """Calculates Model body context geometry using the default IfcOpenShell
iterator on triangulation elements.""" iterator on triangulation elements."""
# Implementations are located in ifcopenshell.util.shape.
raw_functions = { raw_functions = {
# IfcLengthMeasure # IfcLengthMeasure
"get_x": Function("IfcLengthMeasure", "X", "Calculates the length along the local X axis"), "get_x": Function("IfcLengthMeasure", "X", "Calculates the length along the local X axis"),
@@ -158,19 +162,15 @@ class IfcOpenShell:
qtos: dict[str, dict[str, Union[str, None]]], qtos: dict[str, dict[str, Union[str, None]]],
results: ResultsDict, results: ResultsDict,
) -> None: ) -> None:
import ifcopenshell formula_functions: dict[str, types.FunctionType] = {}
import ifcopenshell.geom
import ifcopenshell.util.shape
formula_functions = {}
cls.gross_settings = ifcopenshell.geom.settings() cls.gross_settings = ifcopenshell.geom.settings()
cls.gross_settings.set("disable-opening-subtractions", True) cls.gross_settings.set("disable-opening-subtractions", True)
cls.net_settings = ifcopenshell.geom.settings() cls.net_settings = ifcopenshell.geom.settings()
cls.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) cls.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
gross_qtos = {} gross_qtos: QtosFormulas = {}
net_qtos = {} net_qtos: QtosFormulas = {}
for name, quantities in qtos.items(): for name, quantities in qtos.items():
for quantity, formula in quantities.items(): for quantity, formula in quantities.items():
@@ -179,16 +179,12 @@ class IfcOpenShell:
gross_or_net_qtos = gross_qtos if formula.startswith("gross_") else net_qtos gross_or_net_qtos = gross_qtos if formula.startswith("gross_") else net_qtos
if formula.endswith("get_segment_length"): if formula.endswith("get_segment_length"):
gross_or_net_qtos.setdefault(name, {})[quantity] = formula.partition("_")[2] gross_or_net_qtos.setdefault(name, {})[quantity] = formula.partition("_")[2]
elif formula.startswith("gross_"): elif formula.startswith(("gross_", "net_")):
formula = formula.partition("_")[2]
gross_or_net_qtos.setdefault(name, {})[quantity] = formula
formula_functions[formula] = getattr(ifcopenshell.util.shape, formula)
elif formula.startswith("net_"):
formula = formula.partition("_")[2] formula = formula.partition("_")[2]
gross_or_net_qtos.setdefault(name, {})[quantity] = formula gross_or_net_qtos.setdefault(name, {})[quantity] = formula
formula_functions[formula] = getattr(ifcopenshell.util.shape, formula) formula_functions[formula] = getattr(ifcopenshell.util.shape, formula)
tasks = [] tasks: list[tuple[ifcopenshell.geom.iterator, QtosFormulas]] = []
if gross_qtos: if gross_qtos:
tasks.append((IfcOpenShell.create_iterator(ifc_file, cls.gross_settings, list(elements)), gross_qtos)) tasks.append((IfcOpenShell.create_iterator(ifc_file, cls.gross_settings, list(elements)), gross_qtos))
@@ -198,13 +194,13 @@ class IfcOpenShell:
cls.unit_converter = SI2ProjectUnitConverter(ifc_file) cls.unit_converter = SI2ProjectUnitConverter(ifc_file)
for iterator, qtos in tasks: for iterator, qtos_ in tasks:
if iterator.initialize(): if iterator.initialize():
while True: while True:
shape = iterator.get() shape = iterator.get()
element = ifc_file.by_id(shape.id) element = ifc_file.by_id(shape.id)
results.setdefault(element, {}) results.setdefault(element, {})
for name, quantities in qtos.items(): for name, quantities in qtos_.items():
results[element].setdefault(name, {}) results[element].setdefault(name, {})
for quantity, formula in quantities.items(): for quantity, formula in quantities.items():
if formula == "get_segment_length": if formula == "get_segment_length":
@@ -25,7 +25,7 @@ import operator
import subprocess import subprocess
import sys import sys
import time import time
from typing import Union, Any, Callable, TypeVar, overload, Iterable from typing import Union, Any, Callable, TypeVar, overload, Iterable, Sequence
from . import ifcopenshell_wrapper from . import ifcopenshell_wrapper
from . import settings from . import settings
@@ -551,7 +551,7 @@ class entity_instance:
include_identifier: bool = True, include_identifier: bool = True,
recursive: bool = False, recursive: bool = False,
return_type: Union[type[dict], type] = dict, return_type: Union[type[dict], type] = dict,
ignore: Iterable[str] = (), ignore: Sequence[str] = (),
scalar_only: bool = False, scalar_only: bool = False,
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Return a dictionary of the entity_instance's properties (Python and IFC) and their values. """Return a dictionary of the entity_instance's properties (Python and IFC) and their values.
@@ -28,7 +28,7 @@ from ..entity_instance import entity_instance
from . import has_occ from . import has_occ
from typing import TypeVar, Union, Optional, Generator, Any, Literal, overload, TYPE_CHECKING, Iterable from typing import TypeVar, Union, Optional, Generator, Any, Literal, overload, TYPE_CHECKING, Iterable, cast
if TYPE_CHECKING: if TYPE_CHECKING:
from OCC.Core import TopoDS from OCC.Core import TopoDS
@@ -262,6 +262,8 @@ class iterator(ifcopenshell_wrapper.Iterator):
include_or_exclude_type = set(x.__class__.__name__ for x in include_or_exclude) include_or_exclude_type = set(x.__class__.__name__ for x in include_or_exclude)
if include_or_exclude_type == {"entity_instance"}: if include_or_exclude_type == {"entity_instance"}:
include_or_exclude = cast(set[entity_instance], include_or_exclude)
if not all(inst.is_a("IfcProduct") for inst in include_or_exclude): if not all(inst.is_a("IfcProduct") for inst in include_or_exclude):
raise ValueError("include and exclude need to be an aggregate of IfcProduct") raise ValueError("include and exclude need to be an aggregate of IfcProduct")