mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-30 16:43:00 +00:00
typing
This commit is contained in:
@@ -199,7 +199,7 @@ class MaterialCreator:
|
|||||||
|
|
||||||
|
|
||||||
class IfcImporter:
|
class IfcImporter:
|
||||||
def __init__(self, ifc_import_settings):
|
def __init__(self, ifc_import_settings: IfcImportSettings):
|
||||||
self.ifc_import_settings = ifc_import_settings
|
self.ifc_import_settings = ifc_import_settings
|
||||||
self.diff = None
|
self.diff = None
|
||||||
self.file: ifcopenshell.file = None
|
self.file: ifcopenshell.file = None
|
||||||
@@ -722,7 +722,7 @@ class IfcImporter:
|
|||||||
if len(subelement.Coordinates) == 3 and self.is_point_far_away(subelement, is_meters=False):
|
if len(subelement.Coordinates) == 3 and self.is_point_far_away(subelement, is_meters=False):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def apply_blender_offset_to_matrix_world(self, obj, matrix):
|
def apply_blender_offset_to_matrix_world(self, obj: bpy.types.Object, matrix: np.ndarray) -> mathutils.Matrix:
|
||||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||||
if props.has_blender_offset:
|
if props.has_blender_offset:
|
||||||
if obj.data and obj.data.get("has_cartesian_point_offset", None):
|
if obj.data and obj.data.get("has_cartesian_point_offset", None):
|
||||||
@@ -950,7 +950,9 @@ class IfcImporter:
|
|||||||
self.create_product(element, mesh=mesh)
|
self.create_product(element, mesh=mesh)
|
||||||
|
|
||||||
def create_products(
|
def create_products(
|
||||||
self, products, settings: Optional[ifcopenshell.geom.main.settings] = None
|
self,
|
||||||
|
products: set[ifcopenshell.entity_instance],
|
||||||
|
settings: Optional[ifcopenshell.geom.main.settings] = None,
|
||||||
) -> set[ifcopenshell.entity_instance]:
|
) -> set[ifcopenshell.entity_instance]:
|
||||||
results = set()
|
results = set()
|
||||||
if not products:
|
if not products:
|
||||||
@@ -1804,7 +1806,7 @@ class IfcImporter:
|
|||||||
if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup.ObjectType == "DRAWING":
|
if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup.ObjectType == "DRAWING":
|
||||||
return rel.RelatingGroup
|
return rel.RelatingGroup
|
||||||
|
|
||||||
def get_element_matrix(self, element: ifcopenshell.entity_instance) -> np.array:
|
def get_element_matrix(self, element: ifcopenshell.entity_instance) -> np.ndarray:
|
||||||
if isinstance(element, ifcopenshell.sqlite_entity):
|
if isinstance(element, ifcopenshell.sqlite_entity):
|
||||||
result = self.geometry_cache["shapes"][element.id()]["matrix"]
|
result = self.geometry_cache["shapes"][element.id()]["matrix"]
|
||||||
else:
|
else:
|
||||||
@@ -1950,14 +1952,14 @@ class IfcImporter:
|
|||||||
|
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
||||||
def a2p(self, o, z, x):
|
def a2p(self, o: mathutils.Vector, z: mathutils.Vector, x: mathutils.Vector) -> mathutils.Matrix:
|
||||||
y = z.cross(x)
|
y = z.cross(x)
|
||||||
r = mathutils.Matrix((x, y, z, o))
|
r = mathutils.Matrix((x, y, z, o))
|
||||||
r.resize_4x4()
|
r.resize_4x4()
|
||||||
r.transpose()
|
r.transpose()
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def get_axis2placement(self, plc):
|
def get_axis2placement(self, plc: ifcopenshell.entity_instance) -> mathutils.Matrix:
|
||||||
if plc.is_a("IfcAxis2Placement3D"):
|
if plc.is_a("IfcAxis2Placement3D"):
|
||||||
z = mathutils.Vector(plc.Axis.DirectionRatios if plc.Axis else (0, 0, 1))
|
z = mathutils.Vector(plc.Axis.DirectionRatios if plc.Axis else (0, 0, 1))
|
||||||
x = mathutils.Vector(plc.RefDirection.DirectionRatios if plc.RefDirection else (1, 0, 0))
|
x = mathutils.Vector(plc.RefDirection.DirectionRatios if plc.RefDirection else (1, 0, 0))
|
||||||
@@ -1977,7 +1979,7 @@ class IfcImporter:
|
|||||||
o = plc.LocalOrigin.Coordinates
|
o = plc.LocalOrigin.Coordinates
|
||||||
return self.a2p(o, z, x)
|
return self.a2p(o, z, x)
|
||||||
|
|
||||||
def get_local_placement(self, plc):
|
def get_local_placement(self, plc: Optional[ifcopenshell.entity_instance] = None) -> mathutils.Matrix:
|
||||||
if plc is None:
|
if plc is None:
|
||||||
return mathutils.Matrix()
|
return mathutils.Matrix()
|
||||||
if plc.PlacementRelTo is None:
|
if plc.PlacementRelTo is None:
|
||||||
@@ -1992,11 +1994,11 @@ class IfcImporter:
|
|||||||
bpy.context.scene.BIMRootProperties.contexts = str(subcontext.id())
|
bpy.context.scene.BIMRootProperties.contexts = str(subcontext.id())
|
||||||
break
|
break
|
||||||
|
|
||||||
def link_element(self, element, obj):
|
def link_element(self, element: ifcopenshell.entity_instance, obj: IFC_CONNECTED_TYPE) -> None:
|
||||||
self.added_data[element.id()] = obj
|
self.added_data[element.id()] = obj
|
||||||
tool.Ifc.link(element, obj)
|
tool.Ifc.link(element, obj)
|
||||||
|
|
||||||
def set_matrix_world(self, obj, matrix_world):
|
def set_matrix_world(self, obj: bpy.types.Object, matrix_world: mathutils.Matrix) -> None:
|
||||||
obj.matrix_world = matrix_world
|
obj.matrix_world = matrix_world
|
||||||
tool.Geometry.record_object_position(obj)
|
tool.Geometry.record_object_position(obj)
|
||||||
|
|
||||||
|
|||||||
@@ -622,7 +622,7 @@ class Geometry(blenderbim.core.tool.Geometry):
|
|||||||
obj.data.BIMMeshProperties.material_checksum = str([s.id() for s in cls.get_styles(obj) if s])
|
obj.data.BIMMeshProperties.material_checksum = str([s.id() for s in cls.get_styles(obj) if s])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def record_object_position(cls, obj):
|
def record_object_position(cls, obj: bpy.types.Object) -> None:
|
||||||
# These are recorded separately because they have different numerical tolerances
|
# These are recorded separately because they have different numerical tolerances
|
||||||
obj.BIMObjectProperties.location_checksum = repr(np.array(obj.matrix_world.translation).tobytes())
|
obj.BIMObjectProperties.location_checksum = repr(np.array(obj.matrix_world.translation).tobytes())
|
||||||
obj.BIMObjectProperties.rotation_checksum = repr(np.array(obj.matrix_world.to_3x3()).tobytes())
|
obj.BIMObjectProperties.rotation_checksum = repr(np.array(obj.matrix_world.to_3x3()).tobytes())
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import zipfile
|
import zipfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import ifcopenshell.util.file
|
import ifcopenshell.util.file
|
||||||
|
|
||||||
@@ -197,12 +198,14 @@ def register_schema(schema):
|
|||||||
register_schema_attributes(schema.schema)
|
register_schema_attributes(schema.schema)
|
||||||
|
|
||||||
|
|
||||||
def schema_by_name(schema=None, schema_version=None):
|
def schema_by_name(
|
||||||
|
schema: Optional[str] = None, schema_version: Optional[tuple[int, ...]] = None
|
||||||
|
) -> ifcopenshell_wrapper.schema_definition:
|
||||||
"""Returns an object allowing you to query the IFC schema itself
|
"""Returns an object allowing you to query the IFC schema itself
|
||||||
|
|
||||||
:param schema: Which IFC schema to use, chosen from "IFC2X3", "IFC4",
|
:param schema: Which IFC schema to use, chosen from "IFC2X3", "IFC4",
|
||||||
or "IFC4X3". These refer to the ISO approved versions of IFC.
|
or "IFC4X3". These refer to the ISO approved versions of IFC.
|
||||||
:type schema: string
|
:type schema: string, optional
|
||||||
:param schema_version: If you want to specify an exact version of IFC
|
:param schema_version: If you want to specify an exact version of IFC
|
||||||
that may not be an ISO approved version, use this argument instead
|
that may not be an ISO approved version, use this argument instead
|
||||||
of ``schema``. IFC versions on technical.buildingsmart.org are
|
of ``schema``. IFC versions on technical.buildingsmart.org are
|
||||||
@@ -211,7 +214,9 @@ def schema_by_name(schema=None, schema_version=None):
|
|||||||
ADD2 TC1, which is the official version approved by ISO when people
|
ADD2 TC1, which is the official version approved by ISO when people
|
||||||
refer to "IFC4". Generally you should not use this argument unless
|
refer to "IFC4". Generally you should not use this argument unless
|
||||||
you are testing non-ISO IFC releases.
|
you are testing non-ISO IFC releases.
|
||||||
:type schema_version: tuple[int]
|
:type schema_version: tuple[int, ...], optional
|
||||||
|
:return: Schema definition object.
|
||||||
|
:rtype: ifocpenshell_wrapper.schema_definition
|
||||||
"""
|
"""
|
||||||
if schema_version:
|
if schema_version:
|
||||||
prefixes = ("IFC", "X", "_ADD", "_TC")
|
prefixes = ("IFC", "X", "_ADD", "_TC")
|
||||||
|
|||||||
@@ -17,12 +17,19 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import ifcopenshell.util.constraint
|
||||||
import ifcopenshell.util.date
|
import ifcopenshell.util.date
|
||||||
import ifcopenshell.util.sequence
|
import ifcopenshell.util.sequence
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
class Usecase:
|
||||||
def __init__(self, file, task_time=None, attributes=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
file: ifcopenshell.file,
|
||||||
|
task_time: ifcopenshell.entity_instance,
|
||||||
|
attributes: Optional[dict[str, Any]] = None,
|
||||||
|
):
|
||||||
"""Edits the attributes of an IfcTaskTime
|
"""Edits the attributes of an IfcTaskTime
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -55,7 +62,7 @@ class Usecase:
|
|||||||
self.file = file
|
self.file = file
|
||||||
self.settings = {"task_time": task_time, "attributes": attributes or {}}
|
self.settings = {"task_time": task_time, "attributes": attributes or {}}
|
||||||
|
|
||||||
def execute(self):
|
def execute(self) -> None:
|
||||||
self.task = self.get_task()
|
self.task = self.get_task()
|
||||||
self.calendar = ifcopenshell.util.sequence.derive_calendar(self.task)
|
self.calendar = ifcopenshell.util.sequence.derive_calendar(self.task)
|
||||||
|
|
||||||
@@ -169,12 +176,12 @@ class Usecase:
|
|||||||
duration, "IfcDuration"
|
duration, "IfcDuration"
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_task(self):
|
def get_task(self) -> ifcopenshell.entity_instance:
|
||||||
return [
|
return next(
|
||||||
e
|
e
|
||||||
for e in self.file.get_inverse(self.settings["task_time"])
|
for e in self.file.get_inverse(self.settings["task_time"])
|
||||||
if e.is_a("IfcTask")
|
if e.is_a("IfcTask")
|
||||||
][0]
|
)
|
||||||
|
|
||||||
def handle_resource_calculation(self):
|
def handle_resource_calculation(self):
|
||||||
resources = ifcopenshell.util.sequence.get_task_resources(self.task, is_deep=False)
|
resources = ifcopenshell.util.sequence.get_task_resources(self.task, is_deep=False)
|
||||||
|
|||||||
@@ -17,10 +17,16 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import ifcopenshell.util.date
|
import ifcopenshell.util.date
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
class Usecase:
|
||||||
def __init__(self, file, work_time=None, attributes=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
file: ifcopenshell.file,
|
||||||
|
work_time: ifcopenshell.entity_instance,
|
||||||
|
attributes: Optional[dict[str, Any]] = None,
|
||||||
|
):
|
||||||
"""Edits the attributes of an IfcWorkTime
|
"""Edits the attributes of an IfcWorkTime
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -53,13 +59,15 @@ class Usecase:
|
|||||||
self.file = file
|
self.file = file
|
||||||
self.settings = {"work_time": work_time, "attributes": attributes or {}}
|
self.settings = {"work_time": work_time, "attributes": attributes or {}}
|
||||||
|
|
||||||
def execute(self):
|
def execute(self) -> None:
|
||||||
for name, value in self.settings["attributes"].items():
|
for name, value in self.settings["attributes"].items():
|
||||||
if name in ("Start", "StartDate"):
|
if name in ("Start", "StartDate"):
|
||||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
|
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
|
||||||
|
# 4 IfcWorktime Start
|
||||||
self.settings["work_time"][4] = value
|
self.settings["work_time"][4] = value
|
||||||
elif name in ("Finish", "FinishDate"):
|
elif name in ("Finish", "FinishDate"):
|
||||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
|
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
|
||||||
|
# 5 IfcWorktime Finish
|
||||||
self.settings["work_time"][5] = value
|
self.settings["work_time"][5] = value
|
||||||
else:
|
else:
|
||||||
setattr(self.settings["work_time"], name, value)
|
setattr(self.settings["work_time"], name, value)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import numbers
|
|||||||
import zipfile
|
import zipfile
|
||||||
import functools
|
import functools
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional
|
from typing import Optional, Any
|
||||||
|
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import ifcopenshell.util.file
|
import ifcopenshell.util.file
|
||||||
@@ -52,7 +52,7 @@ class Transaction:
|
|||||||
self.batch_delete_ids = set()
|
self.batch_delete_ids = set()
|
||||||
self.batch_inverses = []
|
self.batch_inverses = []
|
||||||
|
|
||||||
def serialise_entity_instance(self, element):
|
def serialise_entity_instance(self, element: ifcopenshell.entity_instance) -> dict[str, Any]:
|
||||||
info = element.get_info()
|
info = element.get_info()
|
||||||
for key, value in info.items():
|
for key, value in info.items():
|
||||||
info[key] = self.serialise_value(element, value)
|
info[key] = self.serialise_value(element, value)
|
||||||
@@ -103,7 +103,7 @@ class Transaction:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def store_delete(self, element):
|
def store_delete(self, element: ifcopenshell.entity_instance) -> None:
|
||||||
inverses = {}
|
inverses = {}
|
||||||
if self.is_batched:
|
if self.is_batched:
|
||||||
if element.id() not in self.batch_delete_ids:
|
if element.id() not in self.batch_delete_ids:
|
||||||
|
|||||||
@@ -20,7 +20,20 @@ import datetime
|
|||||||
import ifcopenshell.util.date
|
import ifcopenshell.util.date
|
||||||
from math import floor
|
from math import floor
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from collections import namedtuple
|
from typing import Union, Literal, Optional, Iterator
|
||||||
|
|
||||||
|
|
||||||
|
DURATION_TYPE = Literal["ELAPSEDTIME", "WORKTIME", "NOTDEFINED"]
|
||||||
|
RECURRENCE_TYPE = Literal[
|
||||||
|
"BY_DAY_COUNT",
|
||||||
|
"BY_WEEKDAY_COUNT",
|
||||||
|
"DAILY",
|
||||||
|
"MONTHLY_BY_DAY_OF_MONTH",
|
||||||
|
"MONTHLY_BY_POSITION",
|
||||||
|
"WEEKLY",
|
||||||
|
"YEARLY_BY_DAY_OF_MONTH",
|
||||||
|
"YEARLY_BY_POSITION",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def derive_date(task, attribute_name, date=None, is_earliest=False, is_latest=False):
|
def derive_date(task, attribute_name, date=None, is_earliest=False, is_latest=False):
|
||||||
@@ -49,7 +62,7 @@ def derive_date(task, attribute_name, date=None, is_earliest=False, is_latest=Fa
|
|||||||
return date
|
return date
|
||||||
|
|
||||||
|
|
||||||
def derive_calendar(task):
|
def derive_calendar(task: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
calendar = get_calendar(task)
|
calendar = get_calendar(task)
|
||||||
if calendar:
|
if calendar:
|
||||||
return calendar
|
return calendar
|
||||||
@@ -57,7 +70,7 @@ def derive_calendar(task):
|
|||||||
return derive_calendar(rel.RelatingObject)
|
return derive_calendar(rel.RelatingObject)
|
||||||
|
|
||||||
|
|
||||||
def get_calendar(task):
|
def get_calendar(task: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
calendar = [
|
calendar = [
|
||||||
rel.RelatingControl
|
rel.RelatingControl
|
||||||
for rel in task.HasAssignments or []
|
for rel in task.HasAssignments or []
|
||||||
@@ -68,7 +81,7 @@ def get_calendar(task):
|
|||||||
return calendar[0]
|
return calendar[0]
|
||||||
|
|
||||||
|
|
||||||
def count_working_days(start, finish, calendar):
|
def count_working_days(start, finish, calendar: ifcopenshell.entity_instance) -> int:
|
||||||
result = 0
|
result = 0
|
||||||
if start == finish:
|
if start == finish:
|
||||||
return 0
|
return 0
|
||||||
@@ -88,7 +101,11 @@ def count_working_days(start, finish, calendar):
|
|||||||
|
|
||||||
|
|
||||||
def get_start_or_finish_date(
|
def get_start_or_finish_date(
|
||||||
start, duration, duration_type, calendar, date_type="FINISH"
|
start,
|
||||||
|
duration,
|
||||||
|
duration_type: DURATION_TYPE,
|
||||||
|
calendar: ifcopenshell.entity_instance,
|
||||||
|
date_type: Literal["START", "FINISH"] = "FINISH",
|
||||||
):
|
):
|
||||||
if not duration.days:
|
if not duration.days:
|
||||||
# Typically a milestone will have zero duration, so the start == finish
|
# Typically a milestone will have zero duration, so the start == finish
|
||||||
@@ -107,7 +124,7 @@ def get_start_or_finish_date(
|
|||||||
return datetime.datetime.combine(result, datetime.time(17))
|
return datetime.datetime.combine(result, datetime.time(17))
|
||||||
|
|
||||||
|
|
||||||
def offset_date(start, duration, duration_type, calendar):
|
def offset_date(start, duration, duration_type: DURATION_TYPE, calendar: ifcopenshell.entity_instance):
|
||||||
current_date = start
|
current_date = start
|
||||||
months = getattr(duration, "months", 0)
|
months = getattr(duration, "months", 0)
|
||||||
years = getattr(duration, "years", 0)
|
years = getattr(duration, "years", 0)
|
||||||
@@ -129,7 +146,7 @@ def offset_date(start, duration, duration_type, calendar):
|
|||||||
return current_date
|
return current_date
|
||||||
|
|
||||||
|
|
||||||
def get_soonest_working_day(start, duration_type, calendar):
|
def get_soonest_working_day(start, duration_type: DURATION_TYPE, calendar: ifcopenshell.entity_instance):
|
||||||
if duration_type == "ELAPSEDTIME" or not is_calendar_applicable(start, calendar):
|
if duration_type == "ELAPSEDTIME" or not is_calendar_applicable(start, calendar):
|
||||||
return start
|
return start
|
||||||
while not is_working_day(start, calendar):
|
while not is_working_day(start, calendar):
|
||||||
@@ -139,7 +156,7 @@ def get_soonest_working_day(start, duration_type, calendar):
|
|||||||
return start
|
return start
|
||||||
|
|
||||||
|
|
||||||
def get_recent_working_day(start, duration_type, calendar):
|
def get_recent_working_day(start, duration_type: DURATION_TYPE, calendar: ifcopenshell.entity_instance):
|
||||||
if duration_type == "ELAPSEDTIME" or not is_calendar_applicable(start, calendar):
|
if duration_type == "ELAPSEDTIME" or not is_calendar_applicable(start, calendar):
|
||||||
return start
|
return start
|
||||||
while not is_working_day(start, calendar):
|
while not is_working_day(start, calendar):
|
||||||
@@ -150,7 +167,7 @@ def get_recent_working_day(start, duration_type, calendar):
|
|||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=None)
|
@lru_cache(maxsize=None)
|
||||||
def is_working_day(day, calendar):
|
def is_working_day(day, calendar: ifcopenshell.entity_instance) -> bool:
|
||||||
is_working_day = False
|
is_working_day = False
|
||||||
for work_time in calendar.WorkingTimes or []:
|
for work_time in calendar.WorkingTimes or []:
|
||||||
if is_work_time_applicable_to_day(work_time, day):
|
if is_work_time_applicable_to_day(work_time, day):
|
||||||
@@ -166,7 +183,7 @@ def is_working_day(day, calendar):
|
|||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=None)
|
@lru_cache(maxsize=None)
|
||||||
def is_calendar_applicable(day, calendar):
|
def is_calendar_applicable(day, calendar: ifcopenshell.entity_instance) -> bool:
|
||||||
if not calendar or not calendar.WorkingTimes:
|
if not calendar or not calendar.WorkingTimes:
|
||||||
return False
|
return False
|
||||||
is_applicable = False
|
is_applicable = False
|
||||||
@@ -177,7 +194,7 @@ def is_calendar_applicable(day, calendar):
|
|||||||
return is_applicable
|
return is_applicable
|
||||||
|
|
||||||
|
|
||||||
def is_day_in_work_time(day, work_time):
|
def is_day_in_work_time(day, work_time: ifcopenshell.entity_instance) -> bool:
|
||||||
is_day_in_work_time = True
|
is_day_in_work_time = True
|
||||||
if isinstance(day, datetime.datetime):
|
if isinstance(day, datetime.datetime):
|
||||||
day = datetime.date(day.year, day.month, day.day)
|
day = datetime.date(day.year, day.month, day.day)
|
||||||
@@ -198,7 +215,7 @@ def is_day_in_work_time(day, work_time):
|
|||||||
return is_day_in_work_time
|
return is_day_in_work_time
|
||||||
|
|
||||||
|
|
||||||
def is_work_time_applicable_to_day(work_time, day):
|
def is_work_time_applicable_to_day(work_time: ifcopenshell.entity_instance, day) -> bool:
|
||||||
if not is_day_in_work_time(day, work_time):
|
if not is_day_in_work_time(day, work_time):
|
||||||
return False
|
return False
|
||||||
if not work_time.RecurrencePattern:
|
if not work_time.RecurrencePattern:
|
||||||
@@ -249,7 +266,7 @@ def is_work_time_applicable_to_day(work_time, day):
|
|||||||
return False # TODO
|
return False # TODO
|
||||||
|
|
||||||
|
|
||||||
def get_task_work_schedule(task):
|
def get_task_work_schedule(task: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
parent_task = get_parent_task(task)
|
parent_task = get_parent_task(task)
|
||||||
if parent_task:
|
if parent_task:
|
||||||
return get_task_work_schedule(parent_task) or get_task_work_schedule(task)
|
return get_task_work_schedule(parent_task) or get_task_work_schedule(task)
|
||||||
@@ -262,23 +279,23 @@ def get_task_work_schedule(task):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_nested_tasks(task):
|
def get_nested_tasks(task: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||||
return [object for rel in task.IsNestedBy or [] for object in rel.RelatedObjects]
|
return [object for rel in task.IsNestedBy or [] for object in rel.RelatedObjects]
|
||||||
|
|
||||||
|
|
||||||
def get_parent_task(task):
|
def get_parent_task(task: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
nests = task.Nests
|
nests = task.Nests
|
||||||
if nests and (obj := nests[0].RelatingObject).is_a("IfcTask"):
|
if nests and (obj := nests[0].RelatingObject).is_a("IfcTask"):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
def get_all_nested_tasks(task):
|
def get_all_nested_tasks(task: ifcopenshell.entity_instance) -> Iterator[ifcopenshell.entity_instance]:
|
||||||
for nested_task in get_nested_tasks(task):
|
for nested_task in get_nested_tasks(task):
|
||||||
yield nested_task
|
yield nested_task
|
||||||
yield from get_all_nested_tasks(nested_task)
|
yield from get_all_nested_tasks(nested_task)
|
||||||
|
|
||||||
|
|
||||||
def get_work_schedule_tasks(work_schedule):
|
def get_work_schedule_tasks(work_schedule: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||||
tasks = []
|
tasks = []
|
||||||
for root_task in get_root_tasks(work_schedule):
|
for root_task in get_root_tasks(work_schedule):
|
||||||
nested_tasks = get_all_nested_tasks(root_task)
|
nested_tasks = get_all_nested_tasks(root_task)
|
||||||
@@ -286,7 +303,7 @@ def get_work_schedule_tasks(work_schedule):
|
|||||||
return tasks
|
return tasks
|
||||||
|
|
||||||
|
|
||||||
def get_root_tasks(work_schedule):
|
def get_root_tasks(work_schedule: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||||
return [
|
return [
|
||||||
obj
|
obj
|
||||||
for rel in work_schedule.Controls
|
for rel in work_schedule.Controls
|
||||||
@@ -295,7 +312,7 @@ def get_root_tasks(work_schedule):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_root_tasks_ids(work_schedule):
|
def get_root_tasks_ids(work_schedule: ifcopenshell.entity_instance) -> list[int]:
|
||||||
return [
|
return [
|
||||||
obj.id()
|
obj.id()
|
||||||
for rel in work_schedule.Controls
|
for rel in work_schedule.Controls
|
||||||
@@ -304,7 +321,7 @@ def get_root_tasks_ids(work_schedule):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def guess_date_range(work_schedule):
|
def guess_date_range(work_schedule: ifcopenshell.entity_instance):
|
||||||
earliest = None
|
earliest = None
|
||||||
latest = None
|
latest = None
|
||||||
root_tasks = get_root_tasks(work_schedule)
|
root_tasks = get_root_tasks(work_schedule)
|
||||||
@@ -326,7 +343,7 @@ def guess_date_range(work_schedule):
|
|||||||
return earliest, latest
|
return earliest, latest
|
||||||
|
|
||||||
|
|
||||||
def get_direct_task_outputs(task):
|
def get_direct_task_outputs(task: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||||
return [
|
return [
|
||||||
rel.RelatingProduct
|
rel.RelatingProduct
|
||||||
for rel in task.HasAssignments
|
for rel in task.HasAssignments
|
||||||
@@ -334,7 +351,7 @@ def get_direct_task_outputs(task):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_task_outputs(task, is_deep=False):
|
def get_task_outputs(task: ifcopenshell.entity_instance, is_deep=False):
|
||||||
if not is_deep:
|
if not is_deep:
|
||||||
return get_direct_task_outputs(task)
|
return get_direct_task_outputs(task)
|
||||||
else:
|
else:
|
||||||
@@ -345,7 +362,7 @@ def get_task_outputs(task, is_deep=False):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_task_inputs(task, is_deep=False):
|
def get_task_inputs(task: ifcopenshell.entity_instance, is_deep=False):
|
||||||
if not is_deep:
|
if not is_deep:
|
||||||
return [
|
return [
|
||||||
object
|
object
|
||||||
@@ -368,7 +385,7 @@ def get_task_inputs(task, is_deep=False):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_task_resources(task, is_deep=False):
|
def get_task_resources(task: ifcopenshell.entity_instance, is_deep=False):
|
||||||
if not is_deep:
|
if not is_deep:
|
||||||
return [
|
return [
|
||||||
object
|
object
|
||||||
@@ -391,15 +408,17 @@ def get_task_resources(task, is_deep=False):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def has_task_outputs(task):
|
def has_task_outputs(task: ifcopenshell.entity_instance) -> bool:
|
||||||
return len(get_task_outputs(task)) > 0
|
return len(get_task_outputs(task)) > 0
|
||||||
|
|
||||||
|
|
||||||
def has_task_inputs(task):
|
def has_task_inputs(task: ifcopenshell.entity_instance) -> bool:
|
||||||
return len(get_task_inputs(task)) > 0
|
return len(get_task_inputs(task)) > 0
|
||||||
|
|
||||||
|
|
||||||
def get_tasks_for_product(product, schedule=None):
|
def get_tasks_for_product(
|
||||||
|
product: ifcopenshell.entity_instance, schedule: Optional[ifcopenshell.entity_instance] = None
|
||||||
|
) -> tuple[list[ifcopenshell.entity_instance], list[ifcopenshell.entity_instance]]:
|
||||||
"""
|
"""
|
||||||
Get all tasks assigned to or referenced by the given product.
|
Get all tasks assigned to or referenced by the given product.
|
||||||
|
|
||||||
@@ -441,7 +460,7 @@ def get_tasks_for_product(product, schedule=None):
|
|||||||
return inputs, outputs
|
return inputs, outputs
|
||||||
|
|
||||||
|
|
||||||
def get_sequence_assignment(task, sequence="successor"):
|
def get_sequence_assignment(task: ifcopenshell.entity_instance, sequence="successor"):
|
||||||
if sequence == "successor":
|
if sequence == "successor":
|
||||||
relationship_attr = "IsPredecessorTo"
|
relationship_attr = "IsPredecessorTo"
|
||||||
elif sequence == "predecessor":
|
elif sequence == "predecessor":
|
||||||
|
|||||||
Reference in New Issue
Block a user