# IfcOpenShell - IFC toolkit and geometry engine # Copyright (C) 2021 Dion Moult # # 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 . import json import os from typing import Union import ifcopenshell import ifcopenshell.util.classification import ifcopenshell.util.element import ifcopenshell.util.system cwd = os.path.dirname(os.path.realpath(__file__)) ifc4_to_brick_map = {} with open(os.path.join(cwd, "ifc4_to_brick.json")) as f: ifc4_to_brick_map = json.load(f) def get_brick_type(element: ifcopenshell.entity_instance) -> Union[str, None]: references = ifcopenshell.util.classification.get_references(element) for reference in references: system = ifcopenshell.util.classification.get_classification(reference) if system.Name == "Brick": return reference.Location result = None predefined_type = ifcopenshell.util.element.get_predefined_type(element) if predefined_type: result = ifc4_to_brick_map.get(f"{element.is_a()}.{predefined_type}", None) if not result: result = ifc4_to_brick_map.get(element.is_a(), None) if not result: element_type = ifcopenshell.util.element.get_type(element) if element_type: ifc_type_class = element_type.is_a().replace("Type", "") result = ifc4_to_brick_map.get(f"{ifc_type_class}.{predefined_type}", None) if not result: result = ifc4_to_brick_map.get(ifc_type_class, None) if result: if result.startswith("http"): return result return f"https://brickschema.org/schema/Brick#{result}" # Generic fallback if element.is_a("IfcDistributionElement"): return f"https://brickschema.org/schema/Brick#Equipment" elif element.is_a("IfcSpatialElement") or element.is_a("IfcSpatialStructureElement"): return f"https://brickschema.org/schema/Brick#Location" elif element.is_a("IfcSystem"): return f"https://brickschema.org/schema/Brick#System" def get_element_feeds(element: ifcopenshell.entity_instance) -> set[ifcopenshell.entity_instance]: current_element = element processed_elements = set() downstream_equipment: set[ifcopenshell.entity_instance] = set() # A queue is a list of branches. A branch is a list of elements in # sequence, each one connecting to another element. An element in a # branch may have a child queue. The queue and child queues are # acyclic. def extend_branch(element, branch, predecessor=None): processed_elements.add(element) branch_element = {"element": element, "children": [], "predecessor": predecessor} branch.append(branch_element) connected = { e for e in ifcopenshell.util.system.get_connected_to(element, flow_direction="SOURCE") if e not in processed_elements } connected.update( [ e for e in ifcopenshell.util.system.get_connected_from(element, flow_direction="SOURCE") if e not in processed_elements ] ) for connected_element in connected: if connected_element.is_a("IfcFlowFitting") or connected_element.is_a("IfcFlowSegment"): branch_element["children"].append(extend_branch(connected_element, [], element)) else: downstream_equipment.add(connected_element) return branch extended_branch = extend_branch(current_element, []) return downstream_equipment