Files
IfcOpenShell/src/ifcopenshell-python/ifcopenshell/util/representation.py
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

120 lines
4.8 KiB
Python
Raw Normal View History

# IfcOpenShell - IFC toolkit and geometry engine
2023-01-08 13:32:13 +05:00
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of IfcOpenShell.
#
# IfcOpenShell is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcOpenShell is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import numpy as np
import ifcopenshell
2024-03-21 14:17:02 +05:00
import ifcopenshell.util.placement
from typing import Optional, Union, TypedDict
2024-03-21 14:17:02 +05:00
def get_context(
ifc_file: ifcopenshell.file,
context: str,
subcontext: Optional[str] = None,
target_view: Optional[str] = None,
) -> Union[ifcopenshell.entity_instance, None]:
if subcontext or target_view:
elements = ifc_file.by_type("IfcGeometricRepresentationSubContext")
else:
elements = ifc_file.by_type("IfcGeometricRepresentationContext", include_subtypes=False)
for element in elements:
if context and element.ContextType != context:
continue
if subcontext and getattr(element, "ContextIdentifier") != subcontext:
continue
if target_view and getattr(element, "TargetView") != target_view:
continue
return element
2024-03-21 14:17:02 +05:00
def is_representation_of_context(
representation: ifcopenshell.entity_instance,
context: Union[ifcopenshell.entity_instance, str],
subcontext: Optional[str] = None,
target_view: Optional[str] = None,
) -> bool:
if isinstance(context, ifcopenshell.entity_instance):
return representation.ContextOfItems == context
if target_view is not None:
return (
representation.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
and representation.ContextOfItems.TargetView == target_view
and representation.ContextOfItems.ContextIdentifier == subcontext
and representation.ContextOfItems.ContextType == context
)
elif subcontext is not None:
return (
representation.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
and representation.ContextOfItems.ContextIdentifier == subcontext
and representation.ContextOfItems.ContextType == context
)
2024-03-21 14:17:02 +05:00
return representation.ContextOfItems.ContextType == context
2024-03-21 14:17:02 +05:00
def get_representation(
element: ifcopenshell.entity_instance,
context: Union[ifcopenshell.entity_instance, str],
subcontext: Optional[str] = None,
target_view: Optional[str] = None,
) -> Union[ifcopenshell.entity_instance, None]:
if element.is_a("IfcProduct") and element.Representation:
for r in element.Representation.Representations:
if is_representation_of_context(r, context, subcontext, target_view):
return r
elif element.is_a("IfcTypeProduct") and element.RepresentationMaps:
for r in element.RepresentationMaps:
if is_representation_of_context(r.MappedRepresentation, context, subcontext, target_view):
return r.MappedRepresentation
2024-03-21 14:17:02 +05:00
def resolve_representation(representation: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
"""Resolve possibly mapped representation.
:param representation: IfcRepresentation
:type representation: ifcopenshell.entity_instance
2024-03-21 14:17:02 +05:00
:return: Representation resolved from mappings
:rtype: ifcopenshell.entity_instance
2024-03-21 14:17:02 +05:00
"""
if len(representation.Items) == 1 and representation.Items[0].is_a("IfcMappedItem"):
return resolve_representation(representation.Items[0].MappingSource.MappedRepresentation)
return representation
2024-03-21 14:17:02 +05:00
class ResolvedItemDict(TypedDict):
matrix: np.array
item: ifcopenshell.entity_instance
def resolve_items(
representation: ifcopenshell.entity_instance, matrix: Optional[np.array] = None
) -> list[ResolvedItemDict]:
if matrix is None:
matrix = np.eye(4)
2024-03-21 14:17:02 +05:00
results: list[ResolvedItemDict] = []
for item in representation.Items or []: # Be forgiving of invalid IFCs because Revit :(
if item.is_a("IfcMappedItem"):
rep_matrix = ifcopenshell.util.placement.get_mappeditem_transformation(item)
if not np.allclose(rep_matrix, np.eye(4)):
rep_matrix = rep_matrix @ matrix.copy()
results.extend(resolve_items(item.MappingSource.MappedRepresentation, rep_matrix))
else:
2024-03-21 14:17:02 +05:00
results.append(ResolvedItemDict(matrix=matrix.copy(), item=item))
return results