mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
typing
This commit is contained in:
@@ -171,7 +171,7 @@ class BIM_OT_multiple_file_selector(bpy.types.Operator):
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
def poll(cls, context):
|
||||
return getattr(context, "file_props", None) is not None
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
@@ -434,6 +434,7 @@ class BIM_PT_tabs(Panel):
|
||||
"QUALITY",
|
||||
"SWITCH",
|
||||
]:
|
||||
# Draw a little underscore below the active tab icon.
|
||||
if aprops.tab == tab:
|
||||
row.prop(aprops, "active_tab", text="", icon="BLANK1")
|
||||
else:
|
||||
|
||||
+38
-18
@@ -20,6 +20,9 @@ import os
|
||||
import re
|
||||
import csv
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
from collections import defaultdict
|
||||
from typing import Literal, Union, Any, Callable
|
||||
|
||||
try:
|
||||
from openpyxl import Workbook
|
||||
@@ -44,12 +47,21 @@ except:
|
||||
__version__ = version = "0.0.0"
|
||||
|
||||
|
||||
ParserPreset = Literal["basic", "cobie24", "cobie24legacy"]
|
||||
|
||||
|
||||
class Parser:
|
||||
def __init__(self, preset="basic"):
|
||||
config: dict[str, Any]
|
||||
categories: defaultdict[str, dict[str, Any]]
|
||||
get_custom_element_data: dict[
|
||||
str, Union[Callable[[ifcopenshell.file, ifcopenshell.entity_instance], dict[str, Any]], dict[str, Any]]
|
||||
]
|
||||
duplicate_keys: list[tuple[dict[str, Any], dict[str, Any]]]
|
||||
|
||||
def __init__(self, preset: Union[ParserPreset, dict[str, Any]] = "basic"):
|
||||
self.file = None
|
||||
self.preset = preset
|
||||
self.categories = {}
|
||||
self.config = None
|
||||
self.categories = defaultdict(dict)
|
||||
self.get_custom_element_data = {}
|
||||
self.duplicate_keys = []
|
||||
|
||||
@@ -59,9 +71,9 @@ class Parser:
|
||||
else:
|
||||
self.config = preset
|
||||
|
||||
def parse(self, ifc_file, name=None):
|
||||
# TODO: name is unused?
|
||||
def parse(self, ifc_file: ifcopenshell.file, name=None):
|
||||
for category_name, category_config in self.config["categories"].items():
|
||||
self.categories.setdefault(category_name, {})
|
||||
for element in category_config["get_category_elements"](ifc_file):
|
||||
get_element_data = category_config["get_element_data"]
|
||||
|
||||
@@ -69,7 +81,7 @@ class Parser:
|
||||
data = {}
|
||||
for key, query in get_element_data.items():
|
||||
data[key] = ifcopenshell.util.selector.get_element_value(element, query)
|
||||
else:
|
||||
elif isinstance(get_element_data, Callable):
|
||||
data = get_element_data(ifc_file, element) or {}
|
||||
|
||||
get_custom_element_data = self.get_custom_element_data.get(category_name, lambda x, y: None)
|
||||
@@ -77,28 +89,26 @@ class Parser:
|
||||
custom_data = {}
|
||||
for key, query in get_custom_element_data.items():
|
||||
custom_data[key] = ifcopenshell.util.selector.get_element_value(element, query)
|
||||
else:
|
||||
elif isinstance(get_custom_element_data, Callable):
|
||||
custom_data = get_custom_element_data(ifc_file, element) or {}
|
||||
|
||||
data.update(custom_data)
|
||||
|
||||
if data:
|
||||
key = "-".join([str(data[k]) for k in category_config["keys"]])
|
||||
# TODO: duplicate_keys are never used?
|
||||
if key in self.categories[category_name]:
|
||||
self.duplicate_keys.append((self.categories[category_name][key], data))
|
||||
self.categories[category_name][key] = data
|
||||
|
||||
def federate(self, paths):
|
||||
def federate(self, paths: list[str]) -> None:
|
||||
for path in paths:
|
||||
spreadsheet = pd.ExcelFile(path)
|
||||
sheet_names = spreadsheet.sheet_names
|
||||
|
||||
for category_name, category_config in self.config["categories"].items():
|
||||
self.categories.setdefault(category_name, {})
|
||||
if category_name not in sheet_names:
|
||||
continue
|
||||
|
||||
self.categories.setdefault(category_name, {})
|
||||
df = pd.read_excel(spreadsheet, sheet_name=category_name, keep_default_na=False)
|
||||
for _, row in df.iterrows():
|
||||
key = "-".join([str(row[k]) for k in category_config["keys"]])
|
||||
@@ -106,18 +116,21 @@ class Parser:
|
||||
continue
|
||||
self.categories[category_name][key] = row.to_dict()
|
||||
|
||||
def exclude_categories(self, names):
|
||||
def exclude_categories(self, names: list[str]) -> None:
|
||||
for name in names:
|
||||
if name in self.config["categories"]:
|
||||
del self.config["categories"][name]
|
||||
|
||||
def exclude_element_data(self, category, names):
|
||||
def exclude_element_data(self, category: str, names: list[str]) -> None:
|
||||
headers = self.config["categories"][category]["headers"]
|
||||
self.config["categories"][category]["headers"] = [h for h in headers if h not in names]
|
||||
|
||||
|
||||
class Writer:
|
||||
def __init__(self, parser):
|
||||
config: dict[str, Any]
|
||||
categories: dict[str, dict[str, Any]]
|
||||
|
||||
def __init__(self, parser: Parser):
|
||||
self.parser = parser
|
||||
if isinstance(self.parser.preset, str):
|
||||
module = importlib.import_module(f"ifcfm.{self.parser.preset}")
|
||||
@@ -127,7 +140,14 @@ class Writer:
|
||||
else:
|
||||
self.config = getattr(self.parser.preset, "config")
|
||||
|
||||
def write(self, null="N/A", empty="-", bool_true="YES", bool_false="NO", list_separator=", "):
|
||||
def write(
|
||||
self,
|
||||
null: str = "N/A",
|
||||
empty: str = "-",
|
||||
bool_true: str = "YES",
|
||||
bool_false: str = "NO",
|
||||
list_separator: str = ", ",
|
||||
) -> None:
|
||||
self.categories = {}
|
||||
null = self.config.get("null", null)
|
||||
empty = self.config.get("empty", empty)
|
||||
@@ -191,7 +211,7 @@ class Writer:
|
||||
for row in data["rows"]:
|
||||
writer.writerow(row)
|
||||
|
||||
def write_ods(self, output):
|
||||
def write_ods(self, output: str) -> None:
|
||||
doc = OpenDocumentSpreadsheet()
|
||||
|
||||
for key, value in self.config.get("colours", {}).items():
|
||||
@@ -229,7 +249,7 @@ class Writer:
|
||||
|
||||
doc.save(output, True)
|
||||
|
||||
def write_xlsx(self, output):
|
||||
def write_xlsx(self, output: str) -> None:
|
||||
workbook = Workbook()
|
||||
|
||||
cell_formats = {}
|
||||
@@ -270,7 +290,7 @@ class Writer:
|
||||
|
||||
workbook.save(output)
|
||||
|
||||
def write_pd(self):
|
||||
def write_pd(self) -> dict[str, pd.DataFrame]:
|
||||
results = {}
|
||||
for category, data in self.categories.items():
|
||||
results[category] = pd.DataFrame(data["rows"], columns=data["headers"])
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
# IfcFM - IFC for facility management
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcFM.
|
||||
#
|
||||
# IfcFM 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.
|
||||
#
|
||||
# IfcFM 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 IfcFM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcfm
|
||||
import argparse
|
||||
import ifcopenshell
|
||||
|
||||
+31
-25
@@ -17,26 +17,28 @@
|
||||
# along with IfcFM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.fm
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.system
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.classification
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.fm
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.system
|
||||
from typing import Any, Union, Optional
|
||||
|
||||
|
||||
def get_facilities(ifc_file):
|
||||
def get_facilities(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcBuilding")
|
||||
|
||||
|
||||
def get_storeys(ifc_file):
|
||||
def get_storeys(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcBuildingStorey")
|
||||
|
||||
|
||||
def get_spaces(ifc_file):
|
||||
def get_spaces(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcSpace")
|
||||
|
||||
|
||||
def get_zones(ifc_file):
|
||||
def get_zones(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
zones = []
|
||||
for zone in ifc_file.by_type("IfcZone"):
|
||||
for rel in zone.IsGroupedBy:
|
||||
@@ -44,22 +46,22 @@ def get_zones(ifc_file):
|
||||
return zones
|
||||
|
||||
|
||||
def get_element_types(ifc_file):
|
||||
def get_element_types(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifcopenshell.util.fm.get_fmhem_types(ifc_file)
|
||||
|
||||
|
||||
def get_elements(ifc_file):
|
||||
def get_elements(ifc_file: ifcopenshell.file) -> set[ifcopenshell.entity_instance]:
|
||||
elements = set()
|
||||
for element_type in get_element_types(ifc_file):
|
||||
elements.update(ifcopenshell.util.element.get_types(element_type))
|
||||
return elements
|
||||
|
||||
|
||||
def get_systems(ifc_file):
|
||||
def get_systems(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcSystem")
|
||||
|
||||
|
||||
def get_facility_data(ifc_file, element):
|
||||
def get_facility_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
return {
|
||||
"Name": element.Name,
|
||||
"ProjectName": ifc_file.by_type("IfcProject")[0].Name,
|
||||
@@ -78,7 +80,7 @@ def get_facility_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_storey_data(ifc_file, element):
|
||||
def get_storey_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
return {
|
||||
"Name": element.Name,
|
||||
"ClassificationIdentification": "Level",
|
||||
@@ -92,7 +94,7 @@ def get_storey_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_space_data(ifc_file, element):
|
||||
def get_space_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
psets = ifcopenshell.util.element.get_psets(element)
|
||||
return {
|
||||
"Name": element.Name,
|
||||
@@ -110,7 +112,7 @@ def get_space_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_zone_data(ifc_file, element):
|
||||
def get_zone_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
zone, space = element
|
||||
return {
|
||||
"Name": zone.Name,
|
||||
@@ -122,7 +124,7 @@ def get_zone_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_element_type_data(ifc_file, element):
|
||||
def get_element_type_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
psets = ifcopenshell.util.element.get_psets(element)
|
||||
return {
|
||||
"Name": element.Name,
|
||||
@@ -143,7 +145,7 @@ def get_element_type_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_element_data(ifc_file, element):
|
||||
def get_element_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
space = ifcopenshell.util.element.get_container(element)
|
||||
space_name = space.Name if space.is_a("IfcSpace") else None
|
||||
systems = ifcopenshell.util.system.get_element_systems(element)
|
||||
@@ -170,7 +172,7 @@ def get_element_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_system_data(ifc_file, element):
|
||||
def get_system_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
return {
|
||||
"Name": element.Name,
|
||||
"Description": element.Description,
|
||||
@@ -183,25 +185,27 @@ def get_system_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_owner_name(element):
|
||||
def get_owner_name(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if not getattr(element, "OwnerHistory", None):
|
||||
return
|
||||
return element.OwnerHistory.OwningUser.TheOrganization.Name
|
||||
|
||||
|
||||
def get_owner_creation_date(element):
|
||||
def get_owner_creation_date(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if not getattr(element, "OwnerHistory", None):
|
||||
return
|
||||
return ifcopenshell.util.date.ifc2datetime(element.OwnerHistory.CreationDate).isoformat()
|
||||
|
||||
|
||||
def get_owner_application(element):
|
||||
def get_owner_application(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if not getattr(element, "OwnerHistory", None):
|
||||
return
|
||||
return element.OwnerHistory.OwningApplication.ApplicationFullName
|
||||
|
||||
|
||||
def get_facility_parent(element, ifc_class):
|
||||
def get_facility_parent(
|
||||
element: ifcopenshell.entity_instance, ifc_class: str
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
parent = ifcopenshell.util.element.get_aggregate(element)
|
||||
while parent:
|
||||
if parent.is_a(ifc_class):
|
||||
@@ -211,7 +215,7 @@ def get_facility_parent(element, ifc_class):
|
||||
parent = ifcopenshell.util.element.get_aggregate(parent)
|
||||
|
||||
|
||||
def get_classification_identification(element):
|
||||
def get_classification_identification(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
references = list(ifcopenshell.util.classification.get_references(element))
|
||||
if references:
|
||||
if hasattr(references[0], "Identification"):
|
||||
@@ -219,13 +223,15 @@ def get_classification_identification(element):
|
||||
return references[0].ItemReference
|
||||
|
||||
|
||||
def get_classification_name(element):
|
||||
def get_classification_name(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
references = list(ifcopenshell.util.classification.get_references(element))
|
||||
if references:
|
||||
return references[0].Name
|
||||
|
||||
|
||||
def get_property(psets, pset_name, prop_name, decimals=None):
|
||||
def get_property(
|
||||
psets: dict[str, Any], pset_name: str, prop_name: str, decimals: Optional[int] = None
|
||||
) -> Union[Any, None, float]:
|
||||
if pset_name in psets:
|
||||
result = psets[pset_name].get(prop_name, None)
|
||||
if decimals is None or result is None:
|
||||
|
||||
+67
-52
@@ -17,11 +17,13 @@
|
||||
# along with IfcFM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.fm
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.system
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.classification
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.fm
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.system
|
||||
from typing import Any, Union, Optional
|
||||
|
||||
|
||||
# The original BIMServer plugin has a function called ifcToCOBie:
|
||||
@@ -34,15 +36,15 @@ import ifcopenshell.util.classification
|
||||
# Impact, Coordinate, Issue, Picklist
|
||||
|
||||
|
||||
def get_contacts(ifc_file):
|
||||
def get_contacts(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcActor")
|
||||
|
||||
|
||||
def get_facilities(ifc_file):
|
||||
def get_facilities(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcBuilding")
|
||||
|
||||
|
||||
def get_floors(ifc_file):
|
||||
def get_floors(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return [
|
||||
e
|
||||
for e in ifc_file.by_type("IfcBuildingStorey")
|
||||
@@ -50,11 +52,11 @@ def get_floors(ifc_file):
|
||||
]
|
||||
|
||||
|
||||
def get_spaces(ifc_file):
|
||||
def get_spaces(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcSpace")
|
||||
|
||||
|
||||
def get_zones(ifc_file):
|
||||
def get_zones(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
results = []
|
||||
zones = ifc_file.by_type("IfcZone")
|
||||
for zone in zones or []:
|
||||
@@ -69,18 +71,18 @@ def get_zones(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_types(ifc_file):
|
||||
def get_types(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifcopenshell.util.fm.get_cobie_types(ifc_file)
|
||||
|
||||
|
||||
def get_components(ifc_file):
|
||||
def get_components(ifc_file: ifcopenshell.file) -> set[ifcopenshell.entity_instance]:
|
||||
elements = set()
|
||||
for element_type in get_types(ifc_file):
|
||||
elements.update(ifcopenshell.util.element.get_types(element_type))
|
||||
return elements
|
||||
|
||||
|
||||
def get_systems(ifc_file):
|
||||
def get_systems(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
results = []
|
||||
components = get_components(ifc_file)
|
||||
if ifc_file.schema == "IFC2X3":
|
||||
@@ -94,7 +96,7 @@ def get_systems(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_assemblies(ifc_file):
|
||||
def get_assemblies(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
results = []
|
||||
layer_sets = ifc_file.by_type("IfcMaterialLayerSet")
|
||||
layer_sets = [] # This is temporarily overridden because it is unclear exactly how this is stored in Type.
|
||||
@@ -128,23 +130,25 @@ def get_assemblies(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_connections(ifc_file):
|
||||
def get_connections(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcRelConnectsPorts")
|
||||
|
||||
|
||||
def get_spares(ifc_file):
|
||||
def get_spares(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcConstructionProductResource")
|
||||
|
||||
|
||||
def get_resources(ifc_file):
|
||||
def get_resources(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcConstructionEquipmentResource")
|
||||
|
||||
|
||||
def get_jobs(ifc_file):
|
||||
def get_jobs(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcTask")
|
||||
|
||||
|
||||
def get_documents(ifc_file):
|
||||
def get_documents(
|
||||
ifc_file: ifcopenshell.file,
|
||||
) -> list[tuple[ifcopenshell.entity_instance, ifcopenshell.entity_instance, ifcopenshell.entity_instance]]:
|
||||
# The original COBie-Plugins assumes a single related object per rel. I think this was wrong.
|
||||
results = []
|
||||
for rel in ifc_file.by_type("IfcRelAssociatesDocument"):
|
||||
@@ -158,7 +162,7 @@ def get_documents(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_attributes(ifc_file):
|
||||
def get_attributes(ifc_file: ifcopenshell.file) -> list[dict[str, Any]]:
|
||||
results = []
|
||||
history = get_history(ifc_file)
|
||||
created_by = get_email_from_history(history) if history else None
|
||||
@@ -247,7 +251,7 @@ def get_attributes(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_contact_data(ifc_file, element):
|
||||
def get_contact_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
the_actor = element.TheActor
|
||||
|
||||
if the_actor.is_a("IfcPerson"):
|
||||
@@ -299,7 +303,7 @@ def get_contact_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_facility_data(ifc_file, element):
|
||||
def get_facility_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
site = get_facility_parent(element, "IfcSite")
|
||||
site_name = None
|
||||
site_description = None
|
||||
@@ -343,7 +347,7 @@ def get_facility_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_floor_data(ifc_file, element):
|
||||
def get_floor_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
height_names = {
|
||||
"Height",
|
||||
"NetHeight",
|
||||
@@ -382,7 +386,7 @@ def get_floor_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_space_data(ifc_file, element):
|
||||
def get_space_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
floor_name = None
|
||||
floor = ifcopenshell.util.element.get_aggregate(element)
|
||||
if floor and floor.is_a("IfcBuildingStorey"):
|
||||
@@ -425,7 +429,7 @@ def get_space_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_zone_data(ifc_file, element):
|
||||
def get_zone_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
zone, space = element
|
||||
|
||||
name = zone.Name
|
||||
@@ -449,7 +453,7 @@ def get_zone_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_type_data(ifc_file, element):
|
||||
def get_type_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
asset_type = None
|
||||
manufacturer = None
|
||||
model_number = None
|
||||
@@ -555,7 +559,7 @@ def get_type_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_component_data(ifc_file, element):
|
||||
def get_component_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
space = ifcopenshell.util.element.get_container(element)
|
||||
space_name = space.Name if space.is_a("IfcSpace") else None
|
||||
systems = ifcopenshell.util.system.get_element_systems(element)
|
||||
@@ -610,7 +614,7 @@ def get_component_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_system_data(ifc_file, element):
|
||||
def get_system_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
system, component = element
|
||||
category = get_category(system)
|
||||
component_name = val(component.Name)
|
||||
@@ -627,7 +631,7 @@ def get_system_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_assembly_data(ifc_file, element):
|
||||
def get_assembly_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
rel, relating_object, related_object = element
|
||||
|
||||
if relating_object.is_a("IfcMaterialLayerSet"):
|
||||
@@ -663,7 +667,7 @@ def get_assembly_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_connection_data(ifc_file, element):
|
||||
def get_connection_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
connection_type = (
|
||||
val(element.RelatingPort.ObjectType)
|
||||
or val(element.RelatedPort.ObjectType)
|
||||
@@ -691,7 +695,7 @@ def get_connection_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_spare_data(ifc_file, element):
|
||||
def get_spare_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
type_name = None
|
||||
for rel in element.ResourceOf or []:
|
||||
for related_object in rel.RelatedObjects or []:
|
||||
@@ -726,7 +730,7 @@ def get_spare_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_resource_data(ifc_file, element):
|
||||
def get_resource_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
return {
|
||||
"Name": val(element.Name),
|
||||
"CreatedBy": get_created_by(element),
|
||||
@@ -739,7 +743,7 @@ def get_resource_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_job_data(ifc_file, element):
|
||||
def get_job_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
type_names = []
|
||||
resource_names = []
|
||||
for rel in element.OperatesOn or []:
|
||||
@@ -810,7 +814,7 @@ def get_job_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_document_data(ifc_file, element):
|
||||
def get_document_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
rel, doc, related_object = element
|
||||
directory = getattr(doc, "Location", None)
|
||||
file = None
|
||||
@@ -847,11 +851,13 @@ def get_document_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_attribute_data(ifc_file, element):
|
||||
def get_attribute_data(
|
||||
ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance
|
||||
) -> ifcopenshell.entity_instance:
|
||||
return element
|
||||
|
||||
|
||||
def get_unit_type_name(ifc_file, unit_type):
|
||||
def get_unit_type_name(ifc_file: ifcopenshell.file, unit_type: str) -> Union[str, None]:
|
||||
for unit in ifc_file.by_type("IfcUnitAssignment")[0].Units:
|
||||
if unit.is_a("IfcNamedUnit") and unit.UnitType == unit_type:
|
||||
if unit.is_a("IfcSIUnit"):
|
||||
@@ -868,17 +874,17 @@ def get_unit_type_name(ifc_file, unit_type):
|
||||
return val(unit.Currency)
|
||||
|
||||
|
||||
def get_unit_name(ifc_file, unit):
|
||||
def get_unit_name(ifc_file: ifcopenshell.entity_instance, unit: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if unit.is_a("IfcNamedUnit"):
|
||||
return val(unit.Name)
|
||||
|
||||
|
||||
def get_created_by(element):
|
||||
def get_created_by(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if getattr(element, "OwnerHistory", None):
|
||||
return get_email_from_history(element.OwnerHistory)
|
||||
|
||||
|
||||
def get_email_from_history(element):
|
||||
def get_email_from_history(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
pao = element.OwningUser
|
||||
if pao.is_a("IfcPersonAndOrganization"):
|
||||
return get_email_from_pao(pao.ThePerson, pao.TheOrganization)
|
||||
@@ -888,7 +894,9 @@ def get_email_from_history(element):
|
||||
return get_email_from_pao(None, pao)
|
||||
|
||||
|
||||
def get_email_from_pao(person, organization):
|
||||
def get_email_from_pao(
|
||||
person: ifcopenshell.entity_instance, organization: ifcopenshell.entity_instance
|
||||
) -> Union[str, None]:
|
||||
if organization:
|
||||
for address in organization.Addresses or []:
|
||||
if address.is_a("IfcTelecomAddress") and address.ElectronicMailAddresses:
|
||||
@@ -900,23 +908,25 @@ def get_email_from_pao(person, organization):
|
||||
return address.ElectronicMailAddresses[0]
|
||||
|
||||
|
||||
def get_owner_name(element):
|
||||
def get_owner_name(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if getattr(element, "OwnerHistory", None):
|
||||
return element.OwnerHistory.OwningUser.TheOrganization.Name
|
||||
|
||||
|
||||
def get_created_on(element):
|
||||
def get_created_on(element: ifcopenshell.entity_instance) -> str:
|
||||
if getattr(element, "OwnerHistory", None):
|
||||
return ifcopenshell.util.date.ifc2datetime(element.OwnerHistory.CreationDate).isoformat()
|
||||
return "1900-12-31T23:59:59" # Yes, really
|
||||
|
||||
|
||||
def get_external_system(element):
|
||||
def get_external_system(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if getattr(element, "OwnerHistory", None):
|
||||
return val(element.OwnerHistory.OwningApplication.ApplicationFullName)
|
||||
|
||||
|
||||
def get_facility_parent(element, ifc_class):
|
||||
def get_facility_parent(
|
||||
element: ifcopenshell.entity_instance, ifc_class: str
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
parent = ifcopenshell.util.element.get_aggregate(element)
|
||||
while parent:
|
||||
if parent.is_a(ifc_class):
|
||||
@@ -926,11 +936,11 @@ def get_facility_parent(element, ifc_class):
|
||||
parent = ifcopenshell.util.element.get_aggregate(parent)
|
||||
|
||||
|
||||
def val(x):
|
||||
def val(x: Any) -> Any:
|
||||
return x if x not in ("", "n/a") else None
|
||||
|
||||
|
||||
def get_area_measurement(element):
|
||||
def get_area_measurement(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
for relationship in getattr(element, "IsDefinedBy", []) or []:
|
||||
if relationship.is_a("IfcRelDefinesByProperties"):
|
||||
definition = relationship.RelatingPropertyDefinition
|
||||
@@ -950,7 +960,7 @@ def get_area_measurement(element):
|
||||
return value
|
||||
|
||||
|
||||
def get_category(element):
|
||||
def get_category(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
references = list(ifcopenshell.util.classification.get_references(element))
|
||||
results = []
|
||||
for reference in references:
|
||||
@@ -968,7 +978,9 @@ def get_category(element):
|
||||
return ",".join(results)
|
||||
|
||||
|
||||
def get_pao_address(person, organization, name):
|
||||
def get_pao_address(
|
||||
person: ifcopenshell.entity_instance, organization: ifcopenshell.entity_instance, name: str
|
||||
) -> Union[str, None]:
|
||||
for actor in [organization, person]:
|
||||
if not actor:
|
||||
continue
|
||||
@@ -982,7 +994,9 @@ def get_pao_address(person, organization, name):
|
||||
return result
|
||||
|
||||
|
||||
def get_property(psets, pset_name, prop_name, decimals=None):
|
||||
def get_property(
|
||||
psets: dict[str, dict[str, Any]], pset_name: str, prop_name: str, decimals: Optional[int] = None
|
||||
) -> Union[Any, None, float]:
|
||||
if pset_name in psets:
|
||||
result = psets[pset_name].get(prop_name, None)
|
||||
if decimals is None or result is None:
|
||||
@@ -990,13 +1004,13 @@ def get_property(psets, pset_name, prop_name, decimals=None):
|
||||
return round(result, decimals)
|
||||
|
||||
|
||||
def get_history(ifc_file):
|
||||
def get_history(ifc_file: ifcopenshell.file) -> Union[ifcopenshell.entity_instance, None]:
|
||||
histories = ifc_file.by_type("IfcOwnerHistory")
|
||||
if histories:
|
||||
return sorted(histories, key=lambda x: x.id())[-1]
|
||||
|
||||
|
||||
def get_property_unit(pset, prop_name):
|
||||
def get_property_unit(pset: ifcopenshell.entity_instance, prop_name: str) -> Union[str, None]:
|
||||
for prop in getattr(pset, "HasProperties", []) or []:
|
||||
if prop.Name == prop_name:
|
||||
unit = getattr(prop, "Unit", None)
|
||||
@@ -1004,7 +1018,8 @@ def get_property_unit(pset, prop_name):
|
||||
return get_unit_name(unit)
|
||||
|
||||
|
||||
def get_allowed_values(pset_id, prop_name):
|
||||
# TODO: never used?
|
||||
def get_allowed_values(ifc_file: ifcopenshell.file, pset_id: int, prop_name: str) -> Union[str, None]:
|
||||
pset = ifc_file.by_id(pset_id)
|
||||
for prop in getattr(pset, "HasProperties", []) or []:
|
||||
if prop.Name == prop_name:
|
||||
@@ -1012,7 +1027,7 @@ def get_allowed_values(pset_id, prop_name):
|
||||
return ",".join([v.wrappedValue for v in prop.EnumerationValues])
|
||||
|
||||
|
||||
def get_sheet_name(element):
|
||||
def get_sheet_name(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if element.is_a("IfcBuilding"):
|
||||
return "Facility"
|
||||
elif element.is_a("IfcBuildingStorey"):
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.guid
|
||||
import ifcopenshell.util.fm
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.system
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.classification
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.fm
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.system
|
||||
from typing import Any, Union, Optional
|
||||
|
||||
|
||||
# The original BIMServer plugin has a function called ifcToCOBie:
|
||||
@@ -35,15 +37,15 @@ import ifcopenshell.util.classification
|
||||
# Impact, Coordinate, Issue, Picklist
|
||||
|
||||
|
||||
def get_contacts(ifc_file):
|
||||
def get_contacts(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcPersonAndOrganization")
|
||||
|
||||
|
||||
def get_facilities(ifc_file):
|
||||
def get_facilities(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcBuilding")
|
||||
|
||||
|
||||
def get_floors(ifc_file):
|
||||
def get_floors(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return [
|
||||
e
|
||||
for e in ifc_file.by_type("IfcBuildingStorey")
|
||||
@@ -51,11 +53,11 @@ def get_floors(ifc_file):
|
||||
]
|
||||
|
||||
|
||||
def get_spaces(ifc_file):
|
||||
def get_spaces(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcSpace")
|
||||
|
||||
|
||||
def get_zones(ifc_file):
|
||||
def get_zones(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
results = []
|
||||
zones = ifc_file.by_type("IfcZone")
|
||||
for zone in zones or []:
|
||||
@@ -86,18 +88,18 @@ def get_zones(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_types(ifc_file):
|
||||
def get_types(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifcopenshell.util.fm.get_cobie_types(ifc_file)
|
||||
|
||||
|
||||
def get_components(ifc_file):
|
||||
def get_components(ifc_file: ifcopenshell.file) -> set[ifcopenshell.entity_instance]:
|
||||
elements = set()
|
||||
for element_type in get_types(ifc_file):
|
||||
elements.update(ifcopenshell.util.element.get_types(element_type))
|
||||
return elements
|
||||
|
||||
|
||||
def get_systems(ifc_file):
|
||||
def get_systems(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
results = []
|
||||
components = get_components(ifc_file)
|
||||
if ifc_file.schema == "IFC2X3":
|
||||
@@ -111,7 +113,7 @@ def get_systems(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_assemblies(ifc_file):
|
||||
def get_assemblies(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
results = []
|
||||
layer_sets = ifc_file.by_type("IfcMaterialLayerSet")
|
||||
layer_sets = [] # This is temporarily overridden because it is unclear exactly how this is stored in Type.
|
||||
@@ -145,23 +147,25 @@ def get_assemblies(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_connections(ifc_file):
|
||||
def get_connections(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcRelConnectsPorts")
|
||||
|
||||
|
||||
def get_spares(ifc_file):
|
||||
def get_spares(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcConstructionProductResource")
|
||||
|
||||
|
||||
def get_resources(ifc_file):
|
||||
def get_resources(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcConstructionEquipmentResource")
|
||||
|
||||
|
||||
def get_jobs(ifc_file):
|
||||
def get_jobs(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
return ifc_file.by_type("IfcTask")
|
||||
|
||||
|
||||
def get_documents(ifc_file):
|
||||
def get_documents(
|
||||
ifc_file: ifcopenshell.file,
|
||||
) -> list[tuple[ifcopenshell.entity_instance, ifcopenshell.entity_instance, ifcopenshell.entity_instance]]:
|
||||
# The original COBie-Plugins assumes a single related object per rel. I think this was wrong.
|
||||
results = []
|
||||
for rel in ifc_file.by_type("IfcRelAssociatesDocument"):
|
||||
@@ -175,7 +179,7 @@ def get_documents(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_attributes(ifc_file):
|
||||
def get_attributes(ifc_file: ifcopenshell.file) -> list[dict[str, Any]]:
|
||||
results = []
|
||||
history = get_history(ifc_file)
|
||||
created_by = get_email_from_history(history) if history else None
|
||||
@@ -265,7 +269,7 @@ def get_attributes(ifc_file):
|
||||
return results
|
||||
|
||||
|
||||
def get_contact_data(ifc_file, element):
|
||||
def get_contact_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
email = get_email_from_pao(element)
|
||||
|
||||
history = get_history(ifc_file)
|
||||
@@ -314,7 +318,7 @@ def get_contact_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_facility_data(ifc_file, element):
|
||||
def get_facility_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
site = get_facility_parent(element, "IfcSite")
|
||||
site_name = None
|
||||
site_description = None
|
||||
@@ -365,7 +369,7 @@ def get_facility_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_floor_data(ifc_file, element):
|
||||
def get_floor_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
external_object = element.is_a()
|
||||
if element.ObjectType and element.ObjectType.lower() in ("site", "ifcsite"):
|
||||
external_object = "IfcSite"
|
||||
@@ -409,7 +413,7 @@ def get_floor_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_space_data(ifc_file, element):
|
||||
def get_space_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
floor_name = None
|
||||
floor = ifcopenshell.util.element.get_aggregate(element)
|
||||
if floor and floor.is_a("IfcBuildingStorey"):
|
||||
@@ -452,7 +456,7 @@ def get_space_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_zone_data(ifc_file, element):
|
||||
def get_zone_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
zone, space = element
|
||||
|
||||
if isinstance(zone, tuple):
|
||||
@@ -493,7 +497,7 @@ def get_zone_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_type_data(ifc_file, element):
|
||||
def get_type_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
pset_metadata = {}
|
||||
pset_mapping = {
|
||||
"manufacturer": {"Manufacturer"},
|
||||
@@ -628,7 +632,7 @@ def get_type_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_component_data(ifc_file, element):
|
||||
def get_component_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
space = ifcopenshell.util.element.get_container(element)
|
||||
space_name = space.Name if space.is_a("IfcSpace") else None
|
||||
systems = ifcopenshell.util.system.get_element_systems(element)
|
||||
@@ -684,7 +688,7 @@ def get_component_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_system_data(ifc_file, element):
|
||||
def get_system_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
system, component = element
|
||||
category = get_category(system)
|
||||
component_name = val(component.Name)
|
||||
@@ -702,7 +706,7 @@ def get_system_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_assembly_data(ifc_file, element):
|
||||
def get_assembly_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
rel, relating_object, related_object = element
|
||||
|
||||
if relating_object.is_a("IfcMaterialLayerSet"):
|
||||
@@ -739,7 +743,7 @@ def get_assembly_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_connection_data(ifc_file, element):
|
||||
def get_connection_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
connection_type = (
|
||||
val(element.RelatingPort.ObjectType)
|
||||
or val(element.RelatedPort.ObjectType)
|
||||
@@ -768,7 +772,7 @@ def get_connection_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_spare_data(ifc_file, element):
|
||||
def get_spare_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
type_name = None
|
||||
for rel in element.ResourceOf or []:
|
||||
for related_object in rel.RelatedObjects or []:
|
||||
@@ -804,7 +808,7 @@ def get_spare_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_resource_data(ifc_file, element):
|
||||
def get_resource_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
return {
|
||||
"key": val(element.Name),
|
||||
"Name": val(element.Name),
|
||||
@@ -818,7 +822,7 @@ def get_resource_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_job_data(ifc_file, element):
|
||||
def get_job_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
type_names = []
|
||||
resource_names = []
|
||||
for rel in element.OperatesOn or []:
|
||||
@@ -890,7 +894,7 @@ def get_job_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_document_data(ifc_file, element):
|
||||
def get_document_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||
rel, doc, related_object = element
|
||||
directory = getattr(doc, "Location", None)
|
||||
file = None
|
||||
@@ -928,11 +932,13 @@ def get_document_data(ifc_file, element):
|
||||
}
|
||||
|
||||
|
||||
def get_attribute_data(ifc_file, element):
|
||||
def get_attribute_data(
|
||||
ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance
|
||||
) -> ifcopenshell.entity_instance:
|
||||
return element
|
||||
|
||||
|
||||
def get_unit_type_name(ifc_file, unit_type):
|
||||
def get_unit_type_name(ifc_file: ifcopenshell.file, unit_type: str) -> Union[str, None]:
|
||||
for unit in ifc_file.by_type("IfcUnitAssignment")[0].Units:
|
||||
if unit.is_a("IfcNamedUnit") and unit.UnitType == unit_type:
|
||||
if unit.is_a("IfcSIUnit"):
|
||||
@@ -949,23 +955,23 @@ def get_unit_type_name(ifc_file, unit_type):
|
||||
return val(unit.Currency)
|
||||
|
||||
|
||||
def get_unit_name(ifc_file, unit):
|
||||
def get_unit_name(ifc_file: ifcopenshell.entity_instance, unit: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if unit.is_a("IfcNamedUnit"):
|
||||
return val(unit.Name)
|
||||
|
||||
|
||||
def get_created_by(element):
|
||||
def get_created_by(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if getattr(element, "OwnerHistory", None):
|
||||
return get_email_from_history(element.OwnerHistory)
|
||||
|
||||
|
||||
def get_email_from_history(element):
|
||||
def get_email_from_history(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
pao = element.OwningUser
|
||||
if pao.is_a("IfcPersonAndOrganization"):
|
||||
return get_email_from_pao(pao)
|
||||
|
||||
|
||||
def get_email_from_pao(pao):
|
||||
def get_email_from_pao(pao: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
for address in pao.ThePerson.Addresses or []:
|
||||
if address.is_a("IfcTelecomAddress") and address.ElectronicMailAddresses:
|
||||
return address.ElectronicMailAddresses[0]
|
||||
@@ -986,23 +992,25 @@ def get_email_from_pao(pao):
|
||||
return pao.ThePerson.GivenName + pao.ThePerson.FamilyName + "@" + pao.TheOrganization.Name + ".com"
|
||||
|
||||
|
||||
def get_owner_name(element):
|
||||
def get_owner_name(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if getattr(element, "OwnerHistory", None):
|
||||
return element.OwnerHistory.OwningUser.TheOrganization.Name
|
||||
|
||||
|
||||
def get_created_on(element):
|
||||
def get_created_on(element: ifcopenshell.entity_instance) -> str:
|
||||
if getattr(element, "OwnerHistory", None):
|
||||
return ifcopenshell.util.date.ifc2datetime(element.OwnerHistory.CreationDate).isoformat()
|
||||
return "1900-12-31T23:59:59" # Yes, really
|
||||
|
||||
|
||||
def get_external_system(element):
|
||||
def get_external_system(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if getattr(element, "OwnerHistory", None):
|
||||
return val(element.OwnerHistory.OwningApplication.ApplicationFullName)
|
||||
|
||||
|
||||
def get_facility_parent(element, ifc_class):
|
||||
def get_facility_parent(
|
||||
element: ifcopenshell.entity_instance, ifc_class: str
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
parent = ifcopenshell.util.element.get_aggregate(element)
|
||||
while parent:
|
||||
if parent.is_a(ifc_class):
|
||||
@@ -1012,11 +1020,11 @@ def get_facility_parent(element, ifc_class):
|
||||
parent = ifcopenshell.util.element.get_aggregate(parent)
|
||||
|
||||
|
||||
def val(x):
|
||||
def val(x: Any) -> Any:
|
||||
return x if x not in ("", "n/a") else None
|
||||
|
||||
|
||||
def get_area_measurement(element):
|
||||
def get_area_measurement(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
for relationship in getattr(element, "IsDefinedBy", []) or []:
|
||||
if relationship.is_a("IfcRelDefinesByProperties"):
|
||||
definition = relationship.RelatingPropertyDefinition
|
||||
@@ -1029,7 +1037,7 @@ def get_area_measurement(element):
|
||||
return result
|
||||
|
||||
|
||||
def get_category(element):
|
||||
def get_category(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
references = list(ifcopenshell.util.classification.get_references(element))
|
||||
results = []
|
||||
for reference in references:
|
||||
@@ -1078,7 +1086,7 @@ def get_category(element):
|
||||
return val(getattr(element, "ObjectType", None))
|
||||
|
||||
|
||||
def get_pao_address(element, name):
|
||||
def get_pao_address(element: ifcopenshell.entity_instance, name: str) -> Union[str, None]:
|
||||
for actor in [element.ThePerson, element.TheOrganization]:
|
||||
for address in actor.Addresses or []:
|
||||
if hasattr(address, name) and getattr(address, name, None):
|
||||
@@ -1090,7 +1098,9 @@ def get_pao_address(element, name):
|
||||
return result
|
||||
|
||||
|
||||
def get_property(psets, pset_name, prop_name, decimals=None):
|
||||
def get_property(
|
||||
psets: dict[str, dict[str, Any]], pset_name: str, prop_name: str, decimals: Optional[int] = None
|
||||
) -> Union[Any, None, float]:
|
||||
if pset_name in psets:
|
||||
result = psets[pset_name].get(prop_name, None)
|
||||
if decimals is None or result is None:
|
||||
@@ -1098,13 +1108,13 @@ def get_property(psets, pset_name, prop_name, decimals=None):
|
||||
return round(result, decimals)
|
||||
|
||||
|
||||
def get_history(ifc_file):
|
||||
def get_history(ifc_file: ifcopenshell.file) -> Union[ifcopenshell.entity_instance, None]:
|
||||
histories = ifc_file.by_type("IfcOwnerHistory")
|
||||
if histories:
|
||||
return sorted(histories, key=lambda x: x.id())[-1]
|
||||
|
||||
|
||||
def get_property_unit(pset, prop_name):
|
||||
def get_property_unit(pset: ifcopenshell.entity_instance, prop_name: str) -> Union[str, None]:
|
||||
for prop in getattr(pset, "HasProperties", []) or []:
|
||||
if prop.Name == prop_name:
|
||||
unit = getattr(prop, "Unit", None)
|
||||
@@ -1112,7 +1122,8 @@ def get_property_unit(pset, prop_name):
|
||||
return get_unit_name(unit)
|
||||
|
||||
|
||||
def get_allowed_values(pset_id, prop_name):
|
||||
# TODO: never used?
|
||||
def get_allowed_values(ifc_file: ifcopenshell.file, pset_id: int, prop_name: str) -> Union[str, None]:
|
||||
pset = ifc_file.by_id(pset_id)
|
||||
for prop in getattr(pset, "HasProperties", []) or []:
|
||||
if prop.Name == prop_name:
|
||||
@@ -1120,7 +1131,7 @@ def get_allowed_values(pset_id, prop_name):
|
||||
return ",".join([v.wrappedValue for v in prop.EnumerationValues])
|
||||
|
||||
|
||||
def get_sheet_name(element):
|
||||
def get_sheet_name(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
if element.is_a("IfcBuilding"):
|
||||
return "Facility"
|
||||
elif element.is_a("IfcBuildingStorey"):
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import ifcopenshell
|
||||
import ifcopenshell.guid
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.representation
|
||||
from typing import Any, Callable, Optional, Union, Literal, overload
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.ifcopenshell_wrapper as W
|
||||
import ifcopenshell.util.attribute
|
||||
from typing import Literal
|
||||
from typing_extensions import assert_never
|
||||
|
||||
# COBie actually uses an exclusion list, but this inclusion list is equivalent.
|
||||
cobie_type_classes = [
|
||||
@@ -114,7 +117,7 @@ fmhem_excluded_classes = [
|
||||
]
|
||||
|
||||
|
||||
def get_cobie_types(ifc_file):
|
||||
def get_cobie_types(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
elements = []
|
||||
for ifc_class in cobie_type_classes:
|
||||
try:
|
||||
@@ -124,7 +127,7 @@ def get_cobie_types(ifc_file):
|
||||
return elements
|
||||
|
||||
|
||||
def get_cobie_components(ifc_file):
|
||||
def get_cobie_components(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
elements = []
|
||||
for ifc_class in cobie_component_classes:
|
||||
try:
|
||||
@@ -134,7 +137,7 @@ def get_cobie_components(ifc_file):
|
||||
return elements
|
||||
|
||||
|
||||
def get_fmhem_types(ifc_file):
|
||||
def get_fmhem_types(ifc_file: ifcopenshell.file) -> list[ifcopenshell.entity_instance]:
|
||||
elements = []
|
||||
if ifc_file.schema == "IFC2X3":
|
||||
fmhem_classes = fmhem_classes_ifc2x3
|
||||
@@ -148,10 +151,10 @@ def get_fmhem_types(ifc_file):
|
||||
return elements
|
||||
|
||||
|
||||
def get_fmhem_classes(schema="IFC4"):
|
||||
def get_fmhem_classes(schema: Literal["IFC4", "IFC2X3"] = "IFC4") -> dict[str, list[str]]:
|
||||
results = {}
|
||||
|
||||
def get_fmhem_class(declaration):
|
||||
def get_fmhem_class(declaration: W.entity) -> None:
|
||||
if declaration.name() in fmhem_excluded_classes:
|
||||
pass
|
||||
elif declaration.is_abstract():
|
||||
@@ -172,8 +175,10 @@ def get_fmhem_classes(schema="IFC4"):
|
||||
classes = fmhem_classes_ifc4
|
||||
elif schema == "IFC2X3":
|
||||
classes = fmhem_classes_ifc2x3
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema)
|
||||
else:
|
||||
assert_never(schema)
|
||||
schema_ = ifcopenshell.schema_by_name(schema)
|
||||
for ifc_class in classes:
|
||||
declaration = schema.declaration_by_name(ifc_class)
|
||||
declaration = schema_.declaration_by_name(ifc_class)
|
||||
get_fmhem_class(declaration)
|
||||
return results
|
||||
|
||||
Reference in New Issue
Block a user