mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Feature faster unit method ---> Main (#5257)
* feature_faster_unit_method > main: added constants * feature_faster_unit_method > main: extended `file` class to dynamically save unit information * feature_faster_unit_method > main: refactored `get_property_unit` method 1. split out case that returns the wrong type (dictionary of units) into its own method 2. cleaned up (but preserved) logic 3. refactored common part of all cases (the method which prioritises unit then value-entity then measure_class) --------- Co-authored-by: raj-open <raj-open@users.noreply.github.com> Co-authored-by: Dion Moult <dion@thinkmoult.com>
This commit is contained in:
@@ -24,10 +24,18 @@ import zipfile
|
||||
import functools
|
||||
import ifcopenshell
|
||||
from pathlib import Path
|
||||
from typing import Optional, Any, Union, Callable, Generator, Literal, TYPE_CHECKING
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Generator
|
||||
from typing import Optional
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
|
||||
from . import ifcopenshell_wrapper
|
||||
from .entity_instance import entity_instance
|
||||
# from .util.constants import IFC_TYPES
|
||||
from .util.constants import IFC_UNIT_ASSIGNMENT
|
||||
from .util.unit import get_measure_unit_type
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import ifcopenshell.util.schema
|
||||
@@ -217,6 +225,7 @@ class file:
|
||||
"""
|
||||
|
||||
wrapped_data: ifcopenshell_wrapper.file
|
||||
_units: file_units | None = None
|
||||
history_size: int = 64
|
||||
|
||||
def __init__(
|
||||
@@ -456,6 +465,28 @@ class file:
|
||||
version.append(int(number.group(1)) if number else 0)
|
||||
return tuple(version)
|
||||
|
||||
@property
|
||||
def units(self) -> file_units:
|
||||
"""
|
||||
A class which dynamically stores unit information
|
||||
and provides methods to compute unit-entities associated to types.
|
||||
"""
|
||||
if self._units is None:
|
||||
self._units = file_units(self)
|
||||
return self._units
|
||||
|
||||
def unit_by_measure_class(
|
||||
self,
|
||||
measure_class: str | None = None,
|
||||
/,
|
||||
) -> ifcopenshell.entity_instance | None:
|
||||
"""
|
||||
Helper method to obtain unit-entity either directly
|
||||
or indirectly via measure class.
|
||||
"""
|
||||
if measure_class is not None:
|
||||
return self.units.by_measure_type(measure_class)
|
||||
|
||||
def __getattr__(self, attr) -> Union[Any, Callable[..., ifcopenshell.entity_instance]]:
|
||||
if attr[0:6] == "create":
|
||||
return functools.partial(self.create_entity, attr[6:])
|
||||
@@ -695,3 +726,43 @@ class file:
|
||||
|
||||
def to_string(self) -> str:
|
||||
return self.wrapped_data.to_string()
|
||||
|
||||
|
||||
class file_units:
|
||||
"""
|
||||
A class which provides methods to compute unit-entities associated to types.
|
||||
"""
|
||||
|
||||
_unit_assignment: dict[str, entity_instance] = {}
|
||||
|
||||
def __init__(self, ifc_file: file):
|
||||
self._load_unit_assignment(ifc_file)
|
||||
|
||||
def _load_unit_assignment(self, ifc_file: file, /):
|
||||
"""
|
||||
A mapping as dictionary which associates
|
||||
to basic UnitTypes a unit-entity in the IFC file.
|
||||
"""
|
||||
entities = self.by_type(IFC_UNIT_ASSIGNMENT)
|
||||
base = next(iter(entities), None)
|
||||
units = getattr(base, "Units", None) or ()
|
||||
units_and_types = [
|
||||
(u, getattr(u, "UnitType", None))
|
||||
for u in units
|
||||
if isinstance(u, entity_instance)
|
||||
]
|
||||
self._unit_assignment = {t: u for u, t in units_and_types if isinstance(t, str)}
|
||||
return
|
||||
|
||||
def by_type(self, t: str, /) -> entity_instance | None:
|
||||
"""
|
||||
Returns the unit entity associated to a basic type
|
||||
"""
|
||||
return self._unit_assignment.get(t, None)
|
||||
|
||||
def by_measure_type(self, t: str, /) -> entity_instance | None:
|
||||
"""
|
||||
Returns the unit entity associated to a measure type
|
||||
"""
|
||||
t = get_measure_unit_type(t)
|
||||
return self.by_type(t)
|
||||
Reference in New Issue
Block a user