mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Generate functions for all API usecases for better static code features. See #2693.
This commit is contained in:
@@ -15,3 +15,47 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .add_task import add_task
|
||||
from .add_task_time import add_task_time
|
||||
from .add_time_period import add_time_period
|
||||
from .add_work_calendar import add_work_calendar
|
||||
from .add_work_plan import add_work_plan
|
||||
from .add_work_schedule import add_work_schedule
|
||||
from .add_work_time import add_work_time
|
||||
from .assign_lag_time import assign_lag_time
|
||||
from .assign_process import assign_process
|
||||
from .assign_product import assign_product
|
||||
from .assign_recurrence_pattern import assign_recurrence_pattern
|
||||
from .assign_sequence import assign_sequence
|
||||
from .assign_workplan import assign_workplan
|
||||
from .calculate_task_duration import calculate_task_duration
|
||||
from .cascade_schedule import cascade_schedule
|
||||
from .create_baseline import create_baseline
|
||||
from .duplicate_task import duplicate_task
|
||||
from .edit_lag_time import edit_lag_time
|
||||
from .edit_recurrence_pattern import edit_recurrence_pattern
|
||||
from .edit_sequence import edit_sequence
|
||||
from .edit_task import edit_task
|
||||
from .edit_task_time import edit_task_time
|
||||
from .edit_work_calendar import edit_work_calendar
|
||||
from .edit_work_plan import edit_work_plan
|
||||
from .edit_work_schedule import edit_work_schedule
|
||||
from .edit_work_time import edit_work_time
|
||||
from .get_related_products import get_related_products
|
||||
|
||||
try:
|
||||
from .recalculate_schedule import recalculate_schedule
|
||||
except ModuleNotFoundError as e:
|
||||
print(f"Note: API not available due to missing dependencies: sequence.recalculate_schedule - {e}")
|
||||
from .remove_task import remove_task
|
||||
from .remove_time_period import remove_time_period
|
||||
from .remove_work_calendar import remove_work_calendar
|
||||
from .remove_work_plan import remove_work_plan
|
||||
from .remove_work_schedule import remove_work_schedule
|
||||
from .remove_work_time import remove_work_time
|
||||
from .unassign_lag_time import unassign_lag_time
|
||||
from .unassign_process import unassign_process
|
||||
from .unassign_product import unassign_product
|
||||
from .unassign_recurrence_pattern import unassign_recurrence_pattern
|
||||
from .unassign_sequence import unassign_sequence
|
||||
|
||||
@@ -20,169 +20,159 @@ import ifcopenshell.api
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(
|
||||
self,
|
||||
def add_task(
|
||||
file,
|
||||
work_schedule=None,
|
||||
parent_task=None,
|
||||
name=None,
|
||||
description=None,
|
||||
identification=None,
|
||||
predefined_type="NOTDEFINED",
|
||||
) -> None:
|
||||
"""Adds a new task
|
||||
|
||||
Tasks are typically used for two purposes: construction scheduling and
|
||||
facility management.
|
||||
|
||||
In construction scheduling, a task represents a job to be done in a work
|
||||
schedule. Tasks are organised in a hierarchical manner known as a work
|
||||
breakdown structure (WBS) and have lots of sequential relationships
|
||||
(e.g. this task must finish before the next task can start) and date
|
||||
information (e.g. durations, start dates). This is often represented as
|
||||
a gantt chart and used to analyse critical paths to try and reduce
|
||||
project time to stay on-time and within budget.
|
||||
|
||||
In facility management, a task represents a maintenance task to maintain
|
||||
a piece of equipment. Tasks are broken down into a punch list, or simply
|
||||
a bulleted or ordered sequence of tasks to be performed (e.g. turn off
|
||||
equipment, check power connection, etc) in order to maintain the
|
||||
equipment. Tasks will also typically have recurring scheduled dates in
|
||||
line with the maintenance schedule. These maintenance tasks and
|
||||
procedures are typically published as part of an operations and
|
||||
maintenance manual.
|
||||
|
||||
All tasks must be grouped in a work schedule, either directly as a root
|
||||
or top-level task, or indirectly as a child or subtask of a parent task.
|
||||
In construction scheduling, tasks may be nested many times to create the
|
||||
work breakdown structure, and the "leaf" tasks (i.e. tasks with no more
|
||||
subtasks) are considered to be the activities with dates, whereas all
|
||||
parent tasks are part of the breakdown structure used for categorisation
|
||||
purposes. In facility management, top-level tasks represent the overall
|
||||
maintenance job to be performed, and child tasks represent an ordered
|
||||
list of things to do for that maintenance. These form a 2-level
|
||||
hierarchy. No further child tasks are recommended.
|
||||
|
||||
:param work_schedule: The work schedule to group the task in, if the
|
||||
task is to be a top-level or root task. This is mutually exclusive
|
||||
with the parent_task parameter.
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:param parent_task: The parent task, if the task is to be a subtask or
|
||||
child task. This is mutually exclusive with the work_schedule
|
||||
parameter.
|
||||
:type parent_task: ifcopenshell.entity_instance
|
||||
:param name: The name of the task.
|
||||
:type name: str,optional
|
||||
:param description: The description of the task.
|
||||
:type description: str,optional
|
||||
:param identification: The identification code of the task.
|
||||
:type identification: str,optional
|
||||
:param predefined_type: The predefined type of the task. Common ones
|
||||
include CONSTRUCTION, DEMOLITION, or MAINTENANCE. Consultant the
|
||||
IFC documentation for IfcTaskTypeEnum for more information.
|
||||
:type predefined_type: str
|
||||
:return: The newly created IfcTask
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Add a root task to represent the design milestones, and major
|
||||
# project phases.
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Milestones", identification="A")
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Design", identification="B")
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's start creating our work breakdown structure.
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Early Works", identification="C1")
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Substructure", identification="C2")
|
||||
superstructure = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Superstructure", identification="C3")
|
||||
|
||||
# Notice how the leaf task is the actual activity
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=superstructure, name="Ground Floor FRP", identification="C3.1")
|
||||
|
||||
# Let's imagine we are digitising an operations and maintenance
|
||||
# manual for the mechanical discipline.
|
||||
maintenance = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Mechanical Maintenance")
|
||||
|
||||
# Imagine we have to clean the condenser coils for a chiller every
|
||||
# month. Like the schedule above, to keep things simple we won't
|
||||
# show scheduling times and calendars. This root task represents the
|
||||
# overall maintenance task.
|
||||
cleaning = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=maintenance, name="Condenser coil cleaning")
|
||||
|
||||
# These subtasks represent the punch list of maintenance tasks.
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="1",
|
||||
description="Prior to work, wear safety shoes, gloves, and goggles.")
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="2",
|
||||
description="Prepare jet pump, screwdriver, hose clamp, and control panel door key.")
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
|
||||
description="Switch OFF the chiller unit.")
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
|
||||
description="Open the isolator switch.")
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
|
||||
description="Setup the water pressure by tapping to a water supply and connecting to a ...")
|
||||
"""
|
||||
settings = {
|
||||
"work_schedule": work_schedule,
|
||||
"parent_task": parent_task,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"identification": identification,
|
||||
"predefined_type": predefined_type,
|
||||
}
|
||||
|
||||
task = ifcopenshell.api.run(
|
||||
"root.create_entity",
|
||||
file,
|
||||
work_schedule=None,
|
||||
parent_task=None,
|
||||
name=None,
|
||||
description=None,
|
||||
identification=None,
|
||||
predefined_type="NOTDEFINED",
|
||||
):
|
||||
"""Adds a new task
|
||||
|
||||
Tasks are typically used for two purposes: construction scheduling and
|
||||
facility management.
|
||||
|
||||
In construction scheduling, a task represents a job to be done in a work
|
||||
schedule. Tasks are organised in a hierarchical manner known as a work
|
||||
breakdown structure (WBS) and have lots of sequential relationships
|
||||
(e.g. this task must finish before the next task can start) and date
|
||||
information (e.g. durations, start dates). This is often represented as
|
||||
a gantt chart and used to analyse critical paths to try and reduce
|
||||
project time to stay on-time and within budget.
|
||||
|
||||
In facility management, a task represents a maintenance task to maintain
|
||||
a piece of equipment. Tasks are broken down into a punch list, or simply
|
||||
a bulleted or ordered sequence of tasks to be performed (e.g. turn off
|
||||
equipment, check power connection, etc) in order to maintain the
|
||||
equipment. Tasks will also typically have recurring scheduled dates in
|
||||
line with the maintenance schedule. These maintenance tasks and
|
||||
procedures are typically published as part of an operations and
|
||||
maintenance manual.
|
||||
|
||||
All tasks must be grouped in a work schedule, either directly as a root
|
||||
or top-level task, or indirectly as a child or subtask of a parent task.
|
||||
In construction scheduling, tasks may be nested many times to create the
|
||||
work breakdown structure, and the "leaf" tasks (i.e. tasks with no more
|
||||
subtasks) are considered to be the activities with dates, whereas all
|
||||
parent tasks are part of the breakdown structure used for categorisation
|
||||
purposes. In facility management, top-level tasks represent the overall
|
||||
maintenance job to be performed, and child tasks represent an ordered
|
||||
list of things to do for that maintenance. These form a 2-level
|
||||
hierarchy. No further child tasks are recommended.
|
||||
|
||||
:param work_schedule: The work schedule to group the task in, if the
|
||||
task is to be a top-level or root task. This is mutually exclusive
|
||||
with the parent_task parameter.
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:param parent_task: The parent task, if the task is to be a subtask or
|
||||
child task. This is mutually exclusive with the work_schedule
|
||||
parameter.
|
||||
:type parent_task: ifcopenshell.entity_instance
|
||||
:param name: The name of the task.
|
||||
:type name: str,optional
|
||||
:param description: The description of the task.
|
||||
:type description: str,optional
|
||||
:param identification: The identification code of the task.
|
||||
:type identification: str,optional
|
||||
:param predefined_type: The predefined type of the task. Common ones
|
||||
include CONSTRUCTION, DEMOLITION, or MAINTENANCE. Consultant the
|
||||
IFC documentation for IfcTaskTypeEnum for more information.
|
||||
:type predefined_type: str
|
||||
:return: The newly created IfcTask
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Add a root task to represent the design milestones, and major
|
||||
# project phases.
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Milestones", identification="A")
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Design", identification="B")
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's start creating our work breakdown structure.
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Early Works", identification="C1")
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Substructure", identification="C2")
|
||||
superstructure = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Superstructure", identification="C3")
|
||||
|
||||
# Notice how the leaf task is the actual activity
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=superstructure, name="Ground Floor FRP", identification="C3.1")
|
||||
|
||||
# Let's imagine we are digitising an operations and maintenance
|
||||
# manual for the mechanical discipline.
|
||||
maintenance = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Mechanical Maintenance")
|
||||
|
||||
# Imagine we have to clean the condenser coils for a chiller every
|
||||
# month. Like the schedule above, to keep things simple we won't
|
||||
# show scheduling times and calendars. This root task represents the
|
||||
# overall maintenance task.
|
||||
cleaning = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=maintenance, name="Condenser coil cleaning")
|
||||
|
||||
# These subtasks represent the punch list of maintenance tasks.
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="1",
|
||||
description="Prior to work, wear safety shoes, gloves, and goggles.")
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="2",
|
||||
description="Prepare jet pump, screwdriver, hose clamp, and control panel door key.")
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
|
||||
description="Switch OFF the chiller unit.")
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
|
||||
description="Open the isolator switch.")
|
||||
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
|
||||
description="Setup the water pressure by tapping to a water supply and connecting to a ...")
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"work_schedule": work_schedule,
|
||||
"parent_task": parent_task,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"identification": identification,
|
||||
"predefined_type": predefined_type,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
task = ifcopenshell.api.run(
|
||||
"root.create_entity",
|
||||
self.file,
|
||||
ifc_class="IfcTask",
|
||||
name=self.settings["name"],
|
||||
predefined_type=self.settings["predefined_type"],
|
||||
ifc_class="IfcTask",
|
||||
name=settings["name"],
|
||||
predefined_type=settings["predefined_type"],
|
||||
)
|
||||
if settings["description"]:
|
||||
task.Description = settings["description"]
|
||||
if settings["identification"]:
|
||||
task.Identification = settings["identification"]
|
||||
task.IsMilestone = False
|
||||
if settings["work_schedule"]:
|
||||
file.create_entity(
|
||||
"IfcRelAssignsToControl",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||
"RelatedObjects": [task],
|
||||
"RelatingControl": settings["work_schedule"],
|
||||
}
|
||||
)
|
||||
if self.settings["description"]:
|
||||
task.Description = self.settings["description"]
|
||||
if self.settings["identification"]:
|
||||
task.Identification = self.settings["identification"]
|
||||
task.IsMilestone = False
|
||||
if self.settings["work_schedule"]:
|
||||
self.file.create_entity(
|
||||
"IfcRelAssignsToControl",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run(
|
||||
"owner.create_owner_history", self.file
|
||||
),
|
||||
"RelatedObjects": [task],
|
||||
"RelatingControl": self.settings["work_schedule"],
|
||||
}
|
||||
)
|
||||
elif self.settings["parent_task"]:
|
||||
rel = ifcopenshell.api.run(
|
||||
"nest.assign_object",
|
||||
self.file,
|
||||
related_objects=[task],
|
||||
relating_object=self.settings["parent_task"],
|
||||
)
|
||||
if self.settings["parent_task"].Identification:
|
||||
task.Identification = (
|
||||
self.settings["parent_task"].Identification
|
||||
+ "."
|
||||
+ str(len(rel.RelatedObjects))
|
||||
)
|
||||
return task
|
||||
elif settings["parent_task"]:
|
||||
rel = ifcopenshell.api.run(
|
||||
"nest.assign_object",
|
||||
file,
|
||||
related_objects=[task],
|
||||
relating_object=settings["parent_task"],
|
||||
)
|
||||
if settings["parent_task"].Identification:
|
||||
task.Identification = settings["parent_task"].Identification + "." + str(len(rel.RelatedObjects))
|
||||
return task
|
||||
|
||||
@@ -17,55 +17,52 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, task=None, is_recurring=False):
|
||||
"""Adds a task time to a task
|
||||
def add_task_time(file, task=None, is_recurring=False) -> None:
|
||||
"""Adds a task time to a task
|
||||
|
||||
Some tasks, such as activities within a work breakdown structure or
|
||||
overall maintenance tasks will have time related information. This
|
||||
includes start dates, durations, end dates, and possible recurring times
|
||||
(especially for maintenance tasks).
|
||||
Some tasks, such as activities within a work breakdown structure or
|
||||
overall maintenance tasks will have time related information. This
|
||||
includes start dates, durations, end dates, and possible recurring times
|
||||
(especially for maintenance tasks).
|
||||
|
||||
:param task: The task to add time data to.
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:param is_recurring: Whether or not the time should recur.
|
||||
:type is_recurring: bool
|
||||
:return: The newly created IfcTaskTime.
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param task: The task to add time data to.
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:param is_recurring: Whether or not the time should recur.
|
||||
:type is_recurring: bool
|
||||
:return: The newly created IfcTaskTime.
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Create a portion of a work breakdown structure.
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
superstructure = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Superstructure", identification="C3")
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=superstructure, name="Ground Floor FRP", identification="C3.1")
|
||||
# Create a portion of a work breakdown structure.
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
superstructure = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Superstructure", identification="C3")
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=superstructure, name="Ground Floor FRP", identification="C3.1")
|
||||
|
||||
# Add time data. Note that time data is blank by default.
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=task)
|
||||
# Add time data. Note that time data is blank by default.
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=task)
|
||||
|
||||
# Let's say our task starts on the first of January when everybody
|
||||
# is still drunk from the new years celebration, and lasts for 2
|
||||
# days. Note we don't need to specify the end date, as that is
|
||||
# derived from the start plus the duration. In this simple example,
|
||||
# no calendar has been specified, so we are working 24/7. Yikes!
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"task": task, "is_recurring": is_recurring}
|
||||
# Let's say our task starts on the first of January when everybody
|
||||
# is still drunk from the new years celebration, and lasts for 2
|
||||
# days. Note we don't need to specify the end date, as that is
|
||||
# derived from the start plus the duration. In this simple example,
|
||||
# no calendar has been specified, so we are working 24/7. Yikes!
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
"""
|
||||
settings = {"task": task, "is_recurring": is_recurring}
|
||||
|
||||
def execute(self):
|
||||
if self.settings["is_recurring"]:
|
||||
task_time = self.file.create_entity("IfcTaskTimeRecurring")
|
||||
else:
|
||||
task_time = self.file.create_entity("IfcTaskTime")
|
||||
self.settings["task"].TaskTime = task_time
|
||||
return task_time
|
||||
if settings["is_recurring"]:
|
||||
task_time = file.create_entity("IfcTaskTimeRecurring")
|
||||
else:
|
||||
task_time = file.create_entity("IfcTaskTime")
|
||||
settings["task"].TaskTime = task_time
|
||||
return task_time
|
||||
|
||||
@@ -23,79 +23,72 @@ from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, recurrence_pattern=None, start_time=None, end_time=None):
|
||||
"""Adds a time period to a recurrence pattern
|
||||
def add_time_period(file, recurrence_pattern=None, start_time=None, end_time=None) -> None:
|
||||
"""Adds a time period to a recurrence pattern
|
||||
|
||||
A recurring time may be an all-day event, or only during certain time
|
||||
periods of the day. For example, you might say that every 1st of January
|
||||
recurring is a public holiday, which is an all-day event. Alternatively,
|
||||
you might say that you work every (i.e. recurringly) Monday to Friday,
|
||||
from 9am to 5pm. The 9am to 5pm is the time period.
|
||||
A recurring time may be an all-day event, or only during certain time
|
||||
periods of the day. For example, you might say that every 1st of January
|
||||
recurring is a public holiday, which is an all-day event. Alternatively,
|
||||
you might say that you work every (i.e. recurringly) Monday to Friday,
|
||||
from 9am to 5pm. The 9am to 5pm is the time period.
|
||||
|
||||
There may also be multiple recurrence patterns, such as from 9am to
|
||||
12pm, and then another from 1pm to 5pm (to indicate an hour break for
|
||||
lunch).
|
||||
There may also be multiple recurrence patterns, such as from 9am to
|
||||
12pm, and then another from 1pm to 5pm (to indicate an hour break for
|
||||
lunch).
|
||||
|
||||
:param recurrence_pattern: The IfcRecurrencePattern to add the time
|
||||
period to. See ifcopenshell.api.sequence.assign_recurrence_pattern.
|
||||
:type recurrence_pattern: ifcopenshell.entity_instance
|
||||
:param start_time: The start time of the time period, in a format
|
||||
compatible with IfcTime, such as an ISO format time string or a
|
||||
datetime.time object.
|
||||
:type start_time: str,datetime.time
|
||||
:param end_time: The end time of the time period, in a format
|
||||
compatible with IfcTime, such as an ISO format time string or a
|
||||
datetime.time object.
|
||||
:type end_time: str,datetime.time
|
||||
:return: The newly created IfcTimePeriod
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param recurrence_pattern: The IfcRecurrencePattern to add the time
|
||||
period to. See ifcopenshell.api.sequence.assign_recurrence_pattern.
|
||||
:type recurrence_pattern: ifcopenshell.entity_instance
|
||||
:param start_time: The start time of the time period, in a format
|
||||
compatible with IfcTime, such as an ISO format time string or a
|
||||
datetime.time object.
|
||||
:type start_time: str,datetime.time
|
||||
:param end_time: The end time of the time period, in a format
|
||||
compatible with IfcTime, such as an ISO format time string or a
|
||||
datetime.time object.
|
||||
:type end_time: str,datetime.time
|
||||
:return: The newly created IfcTimePeriod
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
|
||||
# The morning work session, lunch, then the afternoon work session.
|
||||
ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="09:00", end_time="12:00")
|
||||
ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="13:00", end_time="17:00")
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"recurrence_pattern": recurrence_pattern,
|
||||
"start_time": start_time,
|
||||
"end_time": end_time,
|
||||
}
|
||||
# The morning work session, lunch, then the afternoon work session.
|
||||
ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="09:00", end_time="12:00")
|
||||
ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="13:00", end_time="17:00")
|
||||
"""
|
||||
settings = {
|
||||
"recurrence_pattern": recurrence_pattern,
|
||||
"start_time": start_time,
|
||||
"end_time": end_time,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
time_period = self.file.create_entity("IfcTimePeriod")
|
||||
time_period.StartTime = ifcopenshell.util.date.datetime2ifc(
|
||||
self.settings["start_time"], "IfcTime"
|
||||
)
|
||||
time_period.EndTime = ifcopenshell.util.date.datetime2ifc(
|
||||
self.settings["end_time"], "IfcTime"
|
||||
)
|
||||
time_periods = list(self.settings["recurrence_pattern"].TimePeriods or [])
|
||||
time_periods.append(time_period)
|
||||
self.settings["recurrence_pattern"].TimePeriods = time_periods
|
||||
time_period = file.create_entity("IfcTimePeriod")
|
||||
time_period.StartTime = ifcopenshell.util.date.datetime2ifc(settings["start_time"], "IfcTime")
|
||||
time_period.EndTime = ifcopenshell.util.date.datetime2ifc(settings["end_time"], "IfcTime")
|
||||
time_periods = list(settings["recurrence_pattern"].TimePeriods or [])
|
||||
time_periods.append(time_period)
|
||||
settings["recurrence_pattern"].TimePeriods = time_periods
|
||||
|
||||
ifcopenshell.util.sequence.is_working_day.cache_clear()
|
||||
ifcopenshell.util.sequence.is_calendar_applicable.cache_clear()
|
||||
ifcopenshell.util.sequence.is_working_day.cache_clear()
|
||||
ifcopenshell.util.sequence.is_calendar_applicable.cache_clear()
|
||||
|
||||
return time_period
|
||||
return time_period
|
||||
|
||||
@@ -19,80 +19,77 @@
|
||||
import ifcopenshell.api
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, name="Unnamed", predefined_type="NOTDEFINED"):
|
||||
"""Add a work calendar
|
||||
def add_work_calendar(file, name="Unnamed", predefined_type="NOTDEFINED") -> None:
|
||||
"""Add a work calendar
|
||||
|
||||
A work calendar defines when work is allowed to occur and when the
|
||||
holidays are. This is a fundamental concept in construction planning.
|
||||
Every task in a work schedule will have an associated calendar. Some
|
||||
task and resources work 24/7, whereas others work Monday to Friday, or
|
||||
5.5 day weeks, etc. This is important, as tasks durations may only occur
|
||||
during working times in a work calendar.
|
||||
A work calendar defines when work is allowed to occur and when the
|
||||
holidays are. This is a fundamental concept in construction planning.
|
||||
Every task in a work schedule will have an associated calendar. Some
|
||||
task and resources work 24/7, whereas others work Monday to Friday, or
|
||||
5.5 day weeks, etc. This is important, as tasks durations may only occur
|
||||
during working times in a work calendar.
|
||||
|
||||
Work calendars can also be used to associate with events, such as
|
||||
indicating that during certain days and times of the year, motion
|
||||
sensors should turn on the lights, and other smart building controls.
|
||||
Work calendars can also be used to associate with events, such as
|
||||
indicating that during certain days and times of the year, motion
|
||||
sensors should turn on the lights, and other smart building controls.
|
||||
|
||||
:param name: The name of the calendar. Typically something like
|
||||
"5 Day Working Week" or "24/7".
|
||||
:type name: str, optional
|
||||
:param predefined_type: The type of calendar, typically used to more
|
||||
specifically define shifts, such as FIRSTSHIFT, SECONDSHIFT, or
|
||||
THIRDSHIFT. Leave as NOTDEFINED for basic calendar usage.
|
||||
:return: The newly created IfcWorkCalendar
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param name: The name of the calendar. Typically something like
|
||||
"5 Day Working Week" or "24/7".
|
||||
:type name: str, optional
|
||||
:param predefined_type: The type of calendar, typically used to more
|
||||
specifically define shifts, such as FIRSTSHIFT, SECONDSHIFT, or
|
||||
THIRDSHIFT. Leave as NOTDEFINED for basic calendar usage.
|
||||
:return: The newly created IfcWorkCalendar
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Add a root task to represent the construction tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
# Add a root task to represent the construction tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday), 9am to 5pm
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="09:00", end_time="17:00")
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday), 9am to 5pm
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="09:00", end_time="17:00")
|
||||
|
||||
# We associate the calendar with the construction root task. All
|
||||
# subtasks underneath the construction work task will also inherit
|
||||
# this calendar by default (though you can override them).
|
||||
ifcopenshell.api.run("control.assign_control", model, relating_control=calendar, related_object=task)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"name": name, "predefined_type": predefined_type}
|
||||
# We associate the calendar with the construction root task. All
|
||||
# subtasks underneath the construction work task will also inherit
|
||||
# this calendar by default (though you can override them).
|
||||
ifcopenshell.api.run("control.assign_control", model, relating_control=calendar, related_object=task)
|
||||
"""
|
||||
settings = {"name": name, "predefined_type": predefined_type}
|
||||
|
||||
def execute(self):
|
||||
work_calendar = ifcopenshell.api.run(
|
||||
"root.create_entity",
|
||||
self.file,
|
||||
ifc_class="IfcWorkCalendar",
|
||||
predefined_type=self.settings["predefined_type"],
|
||||
name=self.settings["name"],
|
||||
)
|
||||
context = self.file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration",
|
||||
self.file,
|
||||
definitions=[work_calendar],
|
||||
relating_context=context,
|
||||
)
|
||||
return work_calendar
|
||||
work_calendar = ifcopenshell.api.run(
|
||||
"root.create_entity",
|
||||
file,
|
||||
ifc_class="IfcWorkCalendar",
|
||||
predefined_type=settings["predefined_type"],
|
||||
name=settings["name"],
|
||||
)
|
||||
context = file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration",
|
||||
file,
|
||||
definitions=[work_calendar],
|
||||
relating_context=context,
|
||||
)
|
||||
return work_calendar
|
||||
|
||||
@@ -21,70 +21,63 @@ import ifcopenshell.util.date
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, name=None, predefined_type="NOTDEFINED", start_time=None):
|
||||
"""Add a new work plan
|
||||
def add_work_plan(file, name=None, predefined_type="NOTDEFINED", start_time=None) -> None:
|
||||
"""Add a new work plan
|
||||
|
||||
A work plan is a group of work schedules. Since work schedules may have
|
||||
different purposes, such as for maintenance or construction scheduling,
|
||||
baseline comparison, or phasing, work plans can be used to group related
|
||||
work schedules. At a minimum, it is recommended to use work plans to
|
||||
indicate whether the work schedules are for facility management or for
|
||||
construction scheduling.
|
||||
A work plan is a group of work schedules. Since work schedules may have
|
||||
different purposes, such as for maintenance or construction scheduling,
|
||||
baseline comparison, or phasing, work plans can be used to group related
|
||||
work schedules. At a minimum, it is recommended to use work plans to
|
||||
indicate whether the work schedules are for facility management or for
|
||||
construction scheduling.
|
||||
|
||||
:param name: The name of the work plan. Recommended to be "Maintenance"
|
||||
or "Construction" for the two main purposes.
|
||||
:type name: str, optional
|
||||
:param predefined_type: The type of work plan, used for baselining.
|
||||
Leave as "NOTDEFINED" if unsure.
|
||||
:type predefined_type: str
|
||||
:param start_time: The earliest start time when the schedules grouped
|
||||
within the work plan are relevant.
|
||||
:type start_time: str,datetime.time
|
||||
:return: The newly created IfcWorkPlan
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param name: The name of the work plan. Recommended to be "Maintenance"
|
||||
or "Construction" for the two main purposes.
|
||||
:type name: str, optional
|
||||
:param predefined_type: The type of work plan, used for baselining.
|
||||
Leave as "NOTDEFINED" if unsure.
|
||||
:type predefined_type: str
|
||||
:param start_time: The earliest start time when the schedules grouped
|
||||
within the work plan are relevant.
|
||||
:type start_time: str,datetime.time
|
||||
:return: The newly created IfcWorkPlan
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
|
||||
# This is one of our schedules in our work plan.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
|
||||
name="Construction Schedule A", work_plan=work_plan)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"name": name,
|
||||
"predefined_type": predefined_type,
|
||||
"start_time": start_time or datetime.now(),
|
||||
}
|
||||
# This is one of our schedules in our work plan.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
|
||||
name="Construction Schedule A", work_plan=work_plan)
|
||||
"""
|
||||
settings = {
|
||||
"name": name,
|
||||
"predefined_type": predefined_type,
|
||||
"start_time": start_time or datetime.now(),
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
work_plan = ifcopenshell.api.run(
|
||||
"root.create_entity",
|
||||
self.file,
|
||||
ifc_class="IfcWorkPlan",
|
||||
predefined_type=self.settings["predefined_type"],
|
||||
name=self.settings["name"],
|
||||
)
|
||||
work_plan.CreationDate = ifcopenshell.util.date.datetime2ifc(
|
||||
datetime.now(), "IfcDateTime"
|
||||
)
|
||||
user = ifcopenshell.api.owner.settings.get_user(self.file)
|
||||
if user:
|
||||
work_plan.Creators = [user.ThePerson]
|
||||
work_plan.StartTime = ifcopenshell.util.date.datetime2ifc(
|
||||
self.settings["start_time"], "IfcDateTime"
|
||||
)
|
||||
work_plan = ifcopenshell.api.run(
|
||||
"root.create_entity",
|
||||
file,
|
||||
ifc_class="IfcWorkPlan",
|
||||
predefined_type=settings["predefined_type"],
|
||||
name=settings["name"],
|
||||
)
|
||||
work_plan.CreationDate = ifcopenshell.util.date.datetime2ifc(datetime.now(), "IfcDateTime")
|
||||
user = ifcopenshell.api.owner.settings.get_user(file)
|
||||
if user:
|
||||
work_plan.Creators = [user.ThePerson]
|
||||
work_plan.StartTime = ifcopenshell.util.date.datetime2ifc(settings["start_time"], "IfcDateTime")
|
||||
|
||||
context = self.file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration",
|
||||
self.file,
|
||||
definitions=[work_plan],
|
||||
relating_context=context,
|
||||
)
|
||||
return work_plan
|
||||
context = file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration",
|
||||
file,
|
||||
definitions=[work_plan],
|
||||
relating_context=context,
|
||||
)
|
||||
return work_plan
|
||||
|
||||
@@ -21,104 +21,96 @@ import ifcopenshell.util.date
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(
|
||||
self,
|
||||
def add_work_schedule(
|
||||
file,
|
||||
name="Unnamed",
|
||||
predefined_type="NOTDEFINED",
|
||||
object_type=None,
|
||||
start_time=None,
|
||||
work_plan=None,
|
||||
) -> None:
|
||||
"""Add a new work schedule
|
||||
|
||||
A work schedule is a group of tasks, where the tasks are typically
|
||||
either for maintenance or for construction scheduling.
|
||||
|
||||
:param name: The name of the work schedule.
|
||||
:type name: str
|
||||
:param predefined_type: The type of schedule, chosen from ACTUAL,
|
||||
BASELINE, and PLANNED. Typically you would start with PLANNED, then
|
||||
convert to a BASELINE when changes are made with separate schedules,
|
||||
then have a parallel ACTUAL schedule.
|
||||
:type predefined_type: str
|
||||
:param start_time: The earlier start time when the schedule is relevant.
|
||||
May be represented with an ISO standard string.
|
||||
:type start_time: str,datetime.time,optional
|
||||
:param work_plan: The IfcWorkPlan the schedule will be part of. If not
|
||||
provided, the schedule will not be grouped in a work plan and would
|
||||
exist as a top level schedule in the project. This is not
|
||||
recommended.
|
||||
:type work_plan: ifcopenshell.entity_instance,optional
|
||||
:return: The newly created IfcWorkSchedule
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
|
||||
# Let's imagine this is one of our schedules in our work plan.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
|
||||
name="Construction Schedule A", work_plan=work_plan)
|
||||
|
||||
# Add a root task to represent the design milestones, and major
|
||||
# project phases.
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Milestones", identification="A")
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Design", identification="B")
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
"""
|
||||
settings = {
|
||||
"name": name,
|
||||
"predefined_type": predefined_type,
|
||||
"object_type": object_type,
|
||||
"start_time": start_time or datetime.now(),
|
||||
"work_plan": work_plan,
|
||||
}
|
||||
|
||||
work_schedule = ifcopenshell.api.run(
|
||||
"root.create_entity",
|
||||
file,
|
||||
name="Unnamed",
|
||||
predefined_type="NOTDEFINED",
|
||||
object_type=None,
|
||||
start_time=None,
|
||||
work_plan=None,
|
||||
):
|
||||
"""Add a new work schedule
|
||||
|
||||
A work schedule is a group of tasks, where the tasks are typically
|
||||
either for maintenance or for construction scheduling.
|
||||
|
||||
:param name: The name of the work schedule.
|
||||
:type name: str
|
||||
:param predefined_type: The type of schedule, chosen from ACTUAL,
|
||||
BASELINE, and PLANNED. Typically you would start with PLANNED, then
|
||||
convert to a BASELINE when changes are made with separate schedules,
|
||||
then have a parallel ACTUAL schedule.
|
||||
:type predefined_type: str
|
||||
:param start_time: The earlier start time when the schedule is relevant.
|
||||
May be represented with an ISO standard string.
|
||||
:type start_time: str,datetime.time,optional
|
||||
:param work_plan: The IfcWorkPlan the schedule will be part of. If not
|
||||
provided, the schedule will not be grouped in a work plan and would
|
||||
exist as a top level schedule in the project. This is not
|
||||
recommended.
|
||||
:type work_plan: ifcopenshell.entity_instance,optional
|
||||
:return: The newly created IfcWorkSchedule
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
|
||||
# Let's imagine this is one of our schedules in our work plan.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
|
||||
name="Construction Schedule A", work_plan=work_plan)
|
||||
|
||||
# Add a root task to represent the design milestones, and major
|
||||
# project phases.
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Milestones", identification="A")
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Design", identification="B")
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"name": name,
|
||||
"predefined_type": predefined_type,
|
||||
"object_type": object_type,
|
||||
"start_time": start_time or datetime.now(),
|
||||
"work_plan": work_plan,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
work_schedule = ifcopenshell.api.run(
|
||||
"root.create_entity",
|
||||
self.file,
|
||||
ifc_class="IfcWorkSchedule",
|
||||
predefined_type=self.settings["predefined_type"],
|
||||
name=self.settings["name"],
|
||||
ifc_class="IfcWorkSchedule",
|
||||
predefined_type=settings["predefined_type"],
|
||||
name=settings["name"],
|
||||
)
|
||||
work_schedule.CreationDate = ifcopenshell.util.date.datetime2ifc(datetime.now(), "IfcDateTime")
|
||||
user = ifcopenshell.api.owner.settings.get_user(file)
|
||||
if user:
|
||||
work_schedule.Creators = [user.ThePerson]
|
||||
work_schedule.StartTime = ifcopenshell.util.date.datetime2ifc(settings["start_time"], "IfcDateTime")
|
||||
if settings["object_type"]:
|
||||
work_schedule.ObjectType = settings["object_type"]
|
||||
if settings["work_plan"]:
|
||||
ifcopenshell.api.run(
|
||||
"aggregate.assign_object",
|
||||
file,
|
||||
**{
|
||||
"products": [work_schedule],
|
||||
"relating_object": settings["work_plan"],
|
||||
}
|
||||
)
|
||||
work_schedule.CreationDate = ifcopenshell.util.date.datetime2ifc(
|
||||
datetime.now(), "IfcDateTime"
|
||||
else:
|
||||
# TODO: this is an ambiguity by buildingSMART
|
||||
# See https://forums.buildingsmart.org/t/is-the-ifcworkschedule-project-declaration-mutually-exclusive-to-aggregation-within-a-relating-ifcworkplan/3510
|
||||
context = file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration",
|
||||
file,
|
||||
definitions=[work_schedule],
|
||||
relating_context=context,
|
||||
)
|
||||
user = ifcopenshell.api.owner.settings.get_user(self.file)
|
||||
if user:
|
||||
work_schedule.Creators = [user.ThePerson]
|
||||
work_schedule.StartTime = ifcopenshell.util.date.datetime2ifc(
|
||||
self.settings["start_time"], "IfcDateTime"
|
||||
)
|
||||
if self.settings["object_type"]:
|
||||
work_schedule.ObjectType = self.settings["object_type"]
|
||||
if self.settings["work_plan"]:
|
||||
ifcopenshell.api.run(
|
||||
"aggregate.assign_object",
|
||||
self.file,
|
||||
**{
|
||||
"products": [work_schedule],
|
||||
"relating_object": self.settings["work_plan"],
|
||||
}
|
||||
)
|
||||
else:
|
||||
# TODO: this is an ambiguity by buildingSMART
|
||||
# See https://forums.buildingsmart.org/t/is-the-ifcworkschedule-project-declaration-mutually-exclusive-to-aggregation-within-a-relating-ifcworkplan/3510
|
||||
context = self.file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration",
|
||||
self.file,
|
||||
definitions=[work_schedule],
|
||||
relating_context=context,
|
||||
)
|
||||
return work_schedule
|
||||
return work_schedule
|
||||
|
||||
@@ -17,69 +17,66 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_calendar=None, time_type="WorkingTimes"):
|
||||
"""Add either working times or holiday times to a calendar
|
||||
def add_work_time(file, work_calendar=None, time_type="WorkingTimes") -> None:
|
||||
"""Add either working times or holiday times to a calendar
|
||||
|
||||
A calendar defines when work occurs by defining working times and
|
||||
holiday times. First, the working times are defined, then the holidays
|
||||
may override the working times. For this reason, holidays are also known
|
||||
as exception times. For example, you might define the working times as
|
||||
every Monday to Friday, then define a few holidays in the year, such as
|
||||
the 1st of January. If the 1st of January is on a weekday, it will
|
||||
override the work time.
|
||||
A calendar defines when work occurs by defining working times and
|
||||
holiday times. First, the working times are defined, then the holidays
|
||||
may override the working times. For this reason, holidays are also known
|
||||
as exception times. For example, you might define the working times as
|
||||
every Monday to Friday, then define a few holidays in the year, such as
|
||||
the 1st of January. If the 1st of January is on a weekday, it will
|
||||
override the work time.
|
||||
|
||||
:param work_calendar: The IfcWorkCalendar to add the work or holiday
|
||||
time definition to.
|
||||
:type work_calendar: ifcopenshell.entity_instance
|
||||
:param time_type: Either WorkingTimes or ExceptionTimes, depending on
|
||||
what you want to define.
|
||||
:type time_type: str
|
||||
:return: The newly created IfcWorkTime
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param work_calendar: The IfcWorkCalendar to add the work or holiday
|
||||
time definition to.
|
||||
:type work_calendar: ifcopenshell.entity_instance
|
||||
:param time_type: Either WorkingTimes or ExceptionTimes, depending on
|
||||
what you want to define.
|
||||
:type time_type: str
|
||||
:return: The newly created IfcWorkTime
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
|
||||
# Let's set some holidays
|
||||
holidays = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="ExceptionTimes")
|
||||
# Let's set some holidays
|
||||
holidays = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="ExceptionTimes")
|
||||
|
||||
# We create a yearly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="YEARLY_BY_DAY_OF_MONTH")
|
||||
# We create a yearly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="YEARLY_BY_DAY_OF_MONTH")
|
||||
|
||||
# The holiday is every 1st of January
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"DayComponent": [1], "MonthComponent": [1]})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_calendar": work_calendar, "time_type": time_type}
|
||||
# The holiday is every 1st of January
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"DayComponent": [1], "MonthComponent": [1]})
|
||||
"""
|
||||
settings = {"work_calendar": work_calendar, "time_type": time_type}
|
||||
|
||||
def execute(self):
|
||||
work_time = self.file.create_entity("IfcWorkTime")
|
||||
if self.settings["time_type"] == "WorkingTimes":
|
||||
working_times = list(self.settings["work_calendar"].WorkingTimes or [])
|
||||
working_times.append(work_time)
|
||||
self.settings["work_calendar"].WorkingTimes = working_times
|
||||
elif self.settings["time_type"] == "ExceptionTimes":
|
||||
exception_times = list(self.settings["work_calendar"].ExceptionTimes or [])
|
||||
exception_times.append(work_time)
|
||||
self.settings["work_calendar"].ExceptionTimes = exception_times
|
||||
return work_time
|
||||
work_time = file.create_entity("IfcWorkTime")
|
||||
if settings["time_type"] == "WorkingTimes":
|
||||
working_times = list(settings["work_calendar"].WorkingTimes or [])
|
||||
working_times.append(work_time)
|
||||
settings["work_calendar"].WorkingTimes = working_times
|
||||
elif settings["time_type"] == "ExceptionTimes":
|
||||
exception_times = list(settings["work_calendar"].ExceptionTimes or [])
|
||||
exception_times.append(work_time)
|
||||
settings["work_calendar"].ExceptionTimes = exception_times
|
||||
return work_time
|
||||
|
||||
@@ -19,88 +19,78 @@
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, rel_sequence=None, lag_value=None, duration_type="WORKTIME"):
|
||||
"""Assign a lag time to a sequence relationship between tasks
|
||||
def assign_lag_time(file, rel_sequence=None, lag_value=None, duration_type="WORKTIME") -> None:
|
||||
"""Assign a lag time to a sequence relationship between tasks
|
||||
|
||||
A task sequence (e.g. finish to start) may optionally have a lag time
|
||||
defined. This is a fundamental concept in construction scheduling. The
|
||||
lag is defined as a duration, and the duration is typically either
|
||||
calendar based (i.e. follows the working times and holidays of the
|
||||
calendar) or elapsed time based (i.e. 24/7).
|
||||
A task sequence (e.g. finish to start) may optionally have a lag time
|
||||
defined. This is a fundamental concept in construction scheduling. The
|
||||
lag is defined as a duration, and the duration is typically either
|
||||
calendar based (i.e. follows the working times and holidays of the
|
||||
calendar) or elapsed time based (i.e. 24/7).
|
||||
|
||||
A sequence may only have a single lag time defined. Negative lag times
|
||||
are allowed.
|
||||
A sequence may only have a single lag time defined. Negative lag times
|
||||
are allowed.
|
||||
|
||||
:param rel_sequence: The IfcRelSequence to assign the lag time to.
|
||||
:type rel_sequence: ifcopenshell.entity_instance
|
||||
:param lag_value: An ISO standardised duration string.
|
||||
:type lag_value: str
|
||||
:param duration_type: Choose from WORKTIME for the associated
|
||||
calendar-based lag times (this is the most common scenario and is
|
||||
recommended as a default), or ELAPSEDTIME to not follow the
|
||||
calendar. You may also choose NOTDEFINED but the behaviour of this
|
||||
is unclear.
|
||||
:type duration_type: str
|
||||
:return: The newly created IfcLagTime
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param rel_sequence: The IfcRelSequence to assign the lag time to.
|
||||
:type rel_sequence: ifcopenshell.entity_instance
|
||||
:param lag_value: An ISO standardised duration string.
|
||||
:type lag_value: str
|
||||
:param duration_type: Choose from WORKTIME for the associated
|
||||
calendar-based lag times (this is the most common scenario and is
|
||||
recommended as a default), or ELAPSEDTIME to not follow the
|
||||
calendar. You may also choose NOTDEFINED but the behaviour of this
|
||||
is unclear.
|
||||
:type duration_type: str
|
||||
:return: The newly created IfcLagTime
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's imagine we're doing a typically formwork, reinforcement,
|
||||
# pour sequence. Let's start with the formwork. It'll take us 2
|
||||
# days.
|
||||
formwork = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Formwork", identification="C.1")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
# Let's imagine we're doing a typically formwork, reinforcement,
|
||||
# pour sequence. Let's start with the formwork. It'll take us 2
|
||||
# days.
|
||||
formwork = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Formwork", identification="C.1")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
|
||||
# Now let's do the reinforcement. It'll take us another 2 days.
|
||||
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Reinforcement", identification="C.2")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
# Now let's do the reinforcement. It'll take us another 2 days.
|
||||
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Reinforcement", identification="C.2")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
|
||||
# Now let's say the formwork must finish before the reinforcement
|
||||
# can start. This is a typical finish to start relationship (FS).
|
||||
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=formwork, related_process=reinforcement)
|
||||
# Now let's say the formwork must finish before the reinforcement
|
||||
# can start. This is a typical finish to start relationship (FS).
|
||||
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=formwork, related_process=reinforcement)
|
||||
|
||||
# Now typically there would be no lag time between formwork and
|
||||
# reinforcement, but let's pretend that we had to allow 1 day gap
|
||||
# for whatever reason.
|
||||
ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1D")
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"rel_sequence": rel_sequence,
|
||||
"lag_value": lag_value,
|
||||
"duration_type": duration_type,
|
||||
}
|
||||
# Now typically there would be no lag time between formwork and
|
||||
# reinforcement, but let's pretend that we had to allow 1 day gap
|
||||
# for whatever reason.
|
||||
ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1D")
|
||||
"""
|
||||
settings = {
|
||||
"rel_sequence": rel_sequence,
|
||||
"lag_value": lag_value,
|
||||
"duration_type": duration_type,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
lag_value = self.file.createIfcDuration(
|
||||
ifcopenshell.util.date.datetime2ifc(self.settings["lag_value"], "IfcDuration")
|
||||
)
|
||||
lag_time = self.file.create_entity(
|
||||
"IfcLagTime", DurationType=self.settings["duration_type"], LagValue=lag_value
|
||||
)
|
||||
if self.settings["rel_sequence"].is_a("IfcRelSequence"):
|
||||
if (
|
||||
self.settings["rel_sequence"].TimeLag
|
||||
and len(self.file.get_inverse(self.settings["rel_sequence"].TimeLag)) == 1
|
||||
):
|
||||
self.file.remove(self.settings["rel_sequence"].TimeLag)
|
||||
self.settings["rel_sequence"].TimeLag = lag_time
|
||||
lag_value = file.createIfcDuration(ifcopenshell.util.date.datetime2ifc(settings["lag_value"], "IfcDuration"))
|
||||
lag_time = file.create_entity("IfcLagTime", DurationType=settings["duration_type"], LagValue=lag_value)
|
||||
if settings["rel_sequence"].is_a("IfcRelSequence"):
|
||||
if settings["rel_sequence"].TimeLag and len(file.get_inverse(settings["rel_sequence"].TimeLag)) == 1:
|
||||
file.remove(settings["rel_sequence"].TimeLag)
|
||||
settings["rel_sequence"].TimeLag = lag_time
|
||||
|
||||
@@ -20,109 +20,99 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, relating_process=None, related_object=None):
|
||||
"""Assigns an object to be related to a process, typically a construction task
|
||||
def assign_process(file, relating_process=None, related_object=None) -> None:
|
||||
"""Assigns an object to be related to a process, typically a construction task
|
||||
|
||||
Processes work using the ICOM (Input, Controls, Outputs, Mechanisms)
|
||||
paradigm in IFC. This process model is commonly used in modeling
|
||||
manufacturing functions.
|
||||
Processes work using the ICOM (Input, Controls, Outputs, Mechanisms)
|
||||
paradigm in IFC. This process model is commonly used in modeling
|
||||
manufacturing functions.
|
||||
|
||||
For example, processes (such as tasks) consume Inputs and transform them
|
||||
into Outputs. The process may only occur within the limits of Controls
|
||||
(e.g. cost items) and may require Mechanisms (ISO9000 calls them
|
||||
Mechanisms, whereas IFC calls them resources, such as raw materials,
|
||||
labour, or equipment).
|
||||
For example, processes (such as tasks) consume Inputs and transform them
|
||||
into Outputs. The process may only occur within the limits of Controls
|
||||
(e.g. cost items) and may require Mechanisms (ISO9000 calls them
|
||||
Mechanisms, whereas IFC calls them resources, such as raw materials,
|
||||
labour, or equipment).
|
||||
|
||||
+----------+
|
||||
| Controls |
|
||||
+----------+
|
||||
|
|
||||
V
|
||||
+--------+ +---------+ +---------+
|
||||
| Inputs | --> | Process | --> | Outputs |
|
||||
+--------+ +---------+ +---------+
|
||||
^
|
||||
|
|
||||
+-----------+
|
||||
| Resources |
|
||||
+-----------+
|
||||
+----------+
|
||||
| Controls |
|
||||
+----------+
|
||||
|
|
||||
V
|
||||
+--------+ +---------+ +---------+
|
||||
| Inputs | --> | Process | --> | Outputs |
|
||||
+--------+ +---------+ +---------+
|
||||
^
|
||||
|
|
||||
+-----------+
|
||||
| Resources |
|
||||
+-----------+
|
||||
|
||||
There are three main scenarios where an object may be related to a
|
||||
task: defining inputs, controls, and resources of a process.
|
||||
There are three main scenarios where an object may be related to a
|
||||
task: defining inputs, controls, and resources of a process.
|
||||
|
||||
For inputs, a product (i.e. wall) may be defined as an input to a task,
|
||||
such as when the task is to demolish the wall (i.e. the wall is an
|
||||
input, and there is no output).
|
||||
For inputs, a product (i.e. wall) may be defined as an input to a task,
|
||||
such as when the task is to demolish the wall (i.e. the wall is an
|
||||
input, and there is no output).
|
||||
|
||||
For controls, a cost item may be defined as a control to a task.
|
||||
For controls, a cost item may be defined as a control to a task.
|
||||
|
||||
For resources, any construction resource may be assigned to a task.
|
||||
For resources, any construction resource may be assigned to a task.
|
||||
|
||||
:param relating_process: The IfcProcess (typically IfcTask) that the
|
||||
input, control, or resource is related to.
|
||||
:type relating_process: ifcopenshell.entity_instance
|
||||
:param related_object: The IfcProduct (for input), IfcCostItem (for
|
||||
control) or IfcConstructionResource (for resource).
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: The newly created IfcRelAssignsToProcess relationship
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param relating_process: The IfcProcess (typically IfcTask) that the
|
||||
input, control, or resource is related to.
|
||||
:type relating_process: ifcopenshell.entity_instance
|
||||
:param related_object: The IfcProduct (for input), IfcCostItem (for
|
||||
control) or IfcConstructionResource (for resource).
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: The newly created IfcRelAssignsToProcess relationship
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Demolish existing", identification="A", predefined_type="DEMOLITION")
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Demolish existing", identification="A", predefined_type="DEMOLITION")
|
||||
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
|
||||
# Let's demolish that wall!
|
||||
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=wall)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"relating_process": relating_process,
|
||||
"related_object": related_object,
|
||||
}
|
||||
# Let's demolish that wall!
|
||||
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=wall)
|
||||
"""
|
||||
settings = {
|
||||
"relating_process": relating_process,
|
||||
"related_object": related_object,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
if self.settings["related_object"].HasAssignments:
|
||||
for assignment in self.settings["related_object"].HasAssignments:
|
||||
if (
|
||||
assignment.is_a("IfcRelAssignsToProcess")
|
||||
and assignment.RelatingProcess == self.settings["relating_process"]
|
||||
):
|
||||
return
|
||||
if settings["related_object"].HasAssignments:
|
||||
for assignment in settings["related_object"].HasAssignments:
|
||||
if assignment.is_a("IfcRelAssignsToProcess") and assignment.RelatingProcess == settings["relating_process"]:
|
||||
return
|
||||
|
||||
operates_on = None
|
||||
if self.settings["relating_process"].OperatesOn:
|
||||
operates_on = self.settings["relating_process"].OperatesOn[0]
|
||||
operates_on = None
|
||||
if settings["relating_process"].OperatesOn:
|
||||
operates_on = settings["relating_process"].OperatesOn[0]
|
||||
|
||||
if operates_on:
|
||||
related_objects = list(operates_on.RelatedObjects)
|
||||
related_objects.append(self.settings["related_object"])
|
||||
operates_on.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run(
|
||||
"owner.update_owner_history", self.file, **{"element": operates_on}
|
||||
)
|
||||
else:
|
||||
operates_on = self.file.create_entity(
|
||||
"IfcRelAssignsToProcess",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run(
|
||||
"owner.create_owner_history", self.file
|
||||
),
|
||||
"RelatedObjects": [self.settings["related_object"]],
|
||||
"RelatingProcess": self.settings["relating_process"],
|
||||
}
|
||||
)
|
||||
return operates_on
|
||||
if operates_on:
|
||||
related_objects = list(operates_on.RelatedObjects)
|
||||
related_objects.append(settings["related_object"])
|
||||
operates_on.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": operates_on})
|
||||
else:
|
||||
operates_on = file.create_entity(
|
||||
"IfcRelAssignsToProcess",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||
"RelatedObjects": [settings["related_object"]],
|
||||
"RelatingProcess": settings["relating_process"],
|
||||
}
|
||||
)
|
||||
return operates_on
|
||||
|
||||
@@ -20,85 +20,75 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, relating_product=None, related_object=None):
|
||||
"""Assigns a product to be produced as a result of a process
|
||||
def assign_product(file, relating_product=None, related_object=None) -> None:
|
||||
"""Assigns a product to be produced as a result of a process
|
||||
|
||||
A construction task may result in products (e.g. a wall) being
|
||||
constructed. These task "Outputs" are defined in IFC through product
|
||||
relationships.
|
||||
A construction task may result in products (e.g. a wall) being
|
||||
constructed. These task "Outputs" are defined in IFC through product
|
||||
relationships.
|
||||
|
||||
Not all tasks have Outputs. For example, maintenance tasks will
|
||||
typically not have any outputs.
|
||||
Not all tasks have Outputs. For example, maintenance tasks will
|
||||
typically not have any outputs.
|
||||
|
||||
See ifcopenshell.api.sequence.assign_process for Inputs and other types
|
||||
of process relationships that can be described in manufacturing
|
||||
process modeling.
|
||||
See ifcopenshell.api.sequence.assign_process for Inputs and other types
|
||||
of process relationships that can be described in manufacturing
|
||||
process modeling.
|
||||
|
||||
:param relating_product: The IfcProduct that was constructed as a result
|
||||
of the task.
|
||||
:type relating_product: ifcopenshell.entity_instance
|
||||
:param related_object: The IfcProcess (typically IfcTask) of the
|
||||
construction task.
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: The newly created IfcRelAssignsToProduct relationship
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param relating_product: The IfcProduct that was constructed as a result
|
||||
of the task.
|
||||
:type relating_product: ifcopenshell.entity_instance
|
||||
:param related_object: The IfcProcess (typically IfcTask) of the
|
||||
construction task.
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: The newly created IfcRelAssignsToProduct relationship
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
|
||||
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
|
||||
# Let's construct that wall!
|
||||
ifcopenshell.api.run("sequence.assign_product", model, relating_product=wall, related_object=task)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"relating_product": relating_product,
|
||||
"related_object": related_object,
|
||||
}
|
||||
# Let's construct that wall!
|
||||
ifcopenshell.api.run("sequence.assign_product", model, relating_product=wall, related_object=task)
|
||||
"""
|
||||
settings = {
|
||||
"relating_product": relating_product,
|
||||
"related_object": related_object,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
if self.settings["related_object"].HasAssignments:
|
||||
for assignment in self.settings["related_object"].HasAssignments:
|
||||
if (
|
||||
assignment.is_a("IfcRelAssignsToProduct")
|
||||
and assignment.RelatingProduct == self.settings["relating_product"]
|
||||
):
|
||||
return
|
||||
if settings["related_object"].HasAssignments:
|
||||
for assignment in settings["related_object"].HasAssignments:
|
||||
if assignment.is_a("IfcRelAssignsToProduct") and assignment.RelatingProduct == settings["relating_product"]:
|
||||
return
|
||||
|
||||
referenced_by = None
|
||||
if self.settings["relating_product"].ReferencedBy:
|
||||
referenced_by = self.settings["relating_product"].ReferencedBy[0]
|
||||
referenced_by = None
|
||||
if settings["relating_product"].ReferencedBy:
|
||||
referenced_by = settings["relating_product"].ReferencedBy[0]
|
||||
|
||||
if referenced_by:
|
||||
related_objects = list(referenced_by.RelatedObjects)
|
||||
related_objects.append(self.settings["related_object"])
|
||||
referenced_by.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run(
|
||||
"owner.update_owner_history", self.file, **{"element": referenced_by}
|
||||
)
|
||||
else:
|
||||
referenced_by = self.file.create_entity(
|
||||
"IfcRelAssignsToProduct",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run(
|
||||
"owner.create_owner_history", self.file
|
||||
),
|
||||
"RelatedObjects": [self.settings["related_object"]],
|
||||
"RelatingProduct": self.settings["relating_product"],
|
||||
}
|
||||
)
|
||||
return referenced_by
|
||||
if referenced_by:
|
||||
related_objects = list(referenced_by.RelatedObjects)
|
||||
related_objects.append(settings["related_object"])
|
||||
referenced_by.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": referenced_by})
|
||||
else:
|
||||
referenced_by = file.create_entity(
|
||||
"IfcRelAssignsToProduct",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||
"RelatedObjects": [settings["related_object"]],
|
||||
"RelatingProduct": settings["relating_product"],
|
||||
}
|
||||
)
|
||||
return referenced_by
|
||||
|
||||
@@ -17,112 +17,101 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, parent=None, recurrence_type="WEEKLY"):
|
||||
"""Define a time to recur at a particular interval
|
||||
def assign_recurrence_pattern(file, parent=None, recurrence_type="WEEKLY") -> None:
|
||||
"""Define a time to recur at a particular interval
|
||||
|
||||
There are two scenarios where you might want to define a recurring time
|
||||
pattern.
|
||||
There are two scenarios where you might want to define a recurring time
|
||||
pattern.
|
||||
|
||||
You might want a task to be scheduled at a recurring interval,
|
||||
this is common for maintenance tasks which need to be performed monthly,
|
||||
every 6 months, every year, etc.
|
||||
You might want a task to be scheduled at a recurring interval,
|
||||
this is common for maintenance tasks which need to be performed monthly,
|
||||
every 6 months, every year, etc.
|
||||
|
||||
Alternatively, you might be defining a work calendar, which defines
|
||||
working days or holidays. The working days might be every week from
|
||||
monday to friday ("every" week means it recurs every week), or the
|
||||
holidays might be the same every year.
|
||||
Alternatively, you might be defining a work calendar, which defines
|
||||
working days or holidays. The working days might be every week from
|
||||
monday to friday ("every" week means it recurs every week), or the
|
||||
holidays might be the same every year.
|
||||
|
||||
The types of recurrence are:
|
||||
The types of recurrence are:
|
||||
|
||||
- DAILY: every Nth (interval) day for up to X (Occurrences) occurrences.
|
||||
e.g. Every day, every 2 days, every day up to 5 times, etc
|
||||
- WEEKLY: every Nth (interval) MTWTFSS (WeekdayComponent) for up to X
|
||||
(Occurrences) occurrences. e.g. Every Monday, every weekday, every
|
||||
other saturday, etc
|
||||
- MONTHLY_BY_DAY_OF_MONTH: every Nth (DayComponent) of every Xth
|
||||
(Interval) Month up to Y (Occurrences) occurrences. e.g. Every 15th of
|
||||
the Month.
|
||||
- MONTHLY_BY_POSITION: Every Nth (Position) MTWTFSS (WeekdayComponent)
|
||||
of every Xth (Interval) Month up to Y (Occurrences) occurrences. e.g.
|
||||
Every second Tuesday of the Month.
|
||||
- YEARLY_BY_DAY_OF_MONTH: every Nth (DayComponent) of every JFMAMJJASOND
|
||||
(MonthComponent) month of every Yth (Interval) Year up to Z
|
||||
(Occurrences) occurrences. e.g. every 25th of December.
|
||||
- YEARLY_BY_POSITION: every Nth (Position) MTWTFSS (WeekdayComponent) of
|
||||
every JFMAMJJASOND (MonthComponent) month of every Yth (Interval)
|
||||
Year up to Z (Occurrences) occurrences. e.g. every third Wednesday
|
||||
of January.
|
||||
- DAILY: every Nth (interval) day for up to X (Occurrences) occurrences.
|
||||
e.g. Every day, every 2 days, every day up to 5 times, etc
|
||||
- WEEKLY: every Nth (interval) MTWTFSS (WeekdayComponent) for up to X
|
||||
(Occurrences) occurrences. e.g. Every Monday, every weekday, every
|
||||
other saturday, etc
|
||||
- MONTHLY_BY_DAY_OF_MONTH: every Nth (DayComponent) of every Xth
|
||||
(Interval) Month up to Y (Occurrences) occurrences. e.g. Every 15th of
|
||||
the Month.
|
||||
- MONTHLY_BY_POSITION: Every Nth (Position) MTWTFSS (WeekdayComponent)
|
||||
of every Xth (Interval) Month up to Y (Occurrences) occurrences. e.g.
|
||||
Every second Tuesday of the Month.
|
||||
- YEARLY_BY_DAY_OF_MONTH: every Nth (DayComponent) of every JFMAMJJASOND
|
||||
(MonthComponent) month of every Yth (Interval) Year up to Z
|
||||
(Occurrences) occurrences. e.g. every 25th of December.
|
||||
- YEARLY_BY_POSITION: every Nth (Position) MTWTFSS (WeekdayComponent) of
|
||||
every JFMAMJJASOND (MonthComponent) month of every Yth (Interval)
|
||||
Year up to Z (Occurrences) occurrences. e.g. every third Wednesday
|
||||
of January.
|
||||
|
||||
These recurrence patterns are fairly standard in all calendar and
|
||||
scheduling applications.
|
||||
These recurrence patterns are fairly standard in all calendar and
|
||||
scheduling applications.
|
||||
|
||||
:param parent: Either an IfcTaskTimeRecurring if you are defining a
|
||||
recurring schedule for a task, or IfcWorkTime if you are defining a
|
||||
recurring pattern for a workdays or holidays in a calendar.
|
||||
:type parent: ifcopenshell.entity_instance
|
||||
:param recurrence_type: One of the types of recurrences.
|
||||
:type recurrence_type: str
|
||||
:return: The newly created IfcRecurrencePattern
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param parent: Either an IfcTaskTimeRecurring if you are defining a
|
||||
recurring schedule for a task, or IfcWorkTime if you are defining a
|
||||
recurring pattern for a workdays or holidays in a calendar.
|
||||
:type parent: ifcopenshell.entity_instance
|
||||
:param recurrence_type: One of the types of recurrences.
|
||||
:type recurrence_type: str
|
||||
:return: The newly created IfcRecurrencePattern
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
|
||||
# Let's imagine we are creating a maintenance schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Equipment Maintenance")
|
||||
# Let's imagine we are creating a maintenance schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Equipment Maintenance")
|
||||
|
||||
# Now let's imagine we have a task to maintain the chillers
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Chiller maintenance")
|
||||
# Now let's imagine we have a task to maintain the chillers
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Chiller maintenance")
|
||||
|
||||
# Because it is a maintenance task, we must schedule a recurring time
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=task, is_recurring=True)
|
||||
# Because it is a maintenance task, we must schedule a recurring time
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=task, is_recurring=True)
|
||||
|
||||
# We create a monthly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="MONTHLY_BY_DAY_OF_MONTH")
|
||||
# We create a monthly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="MONTHLY_BY_DAY_OF_MONTH")
|
||||
|
||||
# Specifically, the maintenance task must occur every 6 months
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"DayComponent": [1], "Interval": 6})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"parent": parent, "recurrence_type": recurrence_type}
|
||||
# Specifically, the maintenance task must occur every 6 months
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"DayComponent": [1], "Interval": 6})
|
||||
"""
|
||||
settings = {"parent": parent, "recurrence_type": recurrence_type}
|
||||
|
||||
def execute(self):
|
||||
recurrence = self.file.createIfcRecurrencePattern(
|
||||
self.settings["recurrence_type"]
|
||||
)
|
||||
recurrence = file.createIfcRecurrencePattern(settings["recurrence_type"])
|
||||
|
||||
if self.settings["parent"].is_a("IfcWorkTime"):
|
||||
if (
|
||||
self.settings["parent"].RecurrencePattern
|
||||
and len(
|
||||
self.file.get_inverse(self.settings["parent"].RecurrencePattern)
|
||||
)
|
||||
== 1
|
||||
):
|
||||
self.file.remove(self.settings["parent"].RecurrencePattern)
|
||||
self.settings["parent"].RecurrencePattern = recurrence
|
||||
elif self.settings["parent"].is_a("IfcTaskTimeRecurring"):
|
||||
if len(self.file.get_inverse(self.settings["parent"].Recurrence)) == 1:
|
||||
self.file.remove(self.settings["parent"].Recurrence)
|
||||
self.settings["parent"].Recurrence = recurrence
|
||||
return recurrence
|
||||
if settings["parent"].is_a("IfcWorkTime"):
|
||||
if settings["parent"].RecurrencePattern and len(file.get_inverse(settings["parent"].RecurrencePattern)) == 1:
|
||||
file.remove(settings["parent"].RecurrencePattern)
|
||||
settings["parent"].RecurrencePattern = recurrence
|
||||
elif settings["parent"].is_a("IfcTaskTimeRecurring"):
|
||||
if len(file.get_inverse(settings["parent"].Recurrence)) == 1:
|
||||
file.remove(settings["parent"].Recurrence)
|
||||
settings["parent"].Recurrence = recurrence
|
||||
return recurrence
|
||||
|
||||
@@ -20,119 +20,111 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(
|
||||
self,
|
||||
file,
|
||||
relating_process=None,
|
||||
related_process=None,
|
||||
sequence_type="FINISH_START",
|
||||
):
|
||||
"""Assign a sequential relationship between tasks
|
||||
def assign_sequence(
|
||||
file,
|
||||
relating_process=None,
|
||||
related_process=None,
|
||||
sequence_type="FINISH_START",
|
||||
) -> None:
|
||||
"""Assign a sequential relationship between tasks
|
||||
|
||||
Tasks in construction sequencing typically have sequence relationships
|
||||
between them, indicating that one task must happen after another. This
|
||||
is used to automatically compute new start and end dates and cascade
|
||||
changes when dates are changed. This is also used to calculate critical
|
||||
paths and floats.
|
||||
Tasks in construction sequencing typically have sequence relationships
|
||||
between them, indicating that one task must happen after another. This
|
||||
is used to automatically compute new start and end dates and cascade
|
||||
changes when dates are changed. This is also used to calculate critical
|
||||
paths and floats.
|
||||
|
||||
There are four types of sequence relationships, known as finish to
|
||||
start, finish to finish, start to start, and start to finish, sometimes
|
||||
abbreviated as a (FS, FF, SS, and SF). The most common is the finish to
|
||||
start relationship, indicating that the previous task must finish before
|
||||
the next task can start.
|
||||
There are four types of sequence relationships, known as finish to
|
||||
start, finish to finish, start to start, and start to finish, sometimes
|
||||
abbreviated as a (FS, FF, SS, and SF). The most common is the finish to
|
||||
start relationship, indicating that the previous task must finish before
|
||||
the next task can start.
|
||||
|
||||
You must not create cyclical task sequences. This makes the computer
|
||||
unhappy.
|
||||
You must not create cyclical task sequences. This makes the computer
|
||||
unhappy.
|
||||
|
||||
Note that "previous" or "next" does not necessarily mean the task
|
||||
chronologically happens before or after. They simply indicate the order
|
||||
of the sequence relationship. For this reason, they are often called
|
||||
predecessor and successor tasks in the planning profession.
|
||||
Note that "previous" or "next" does not necessarily mean the task
|
||||
chronologically happens before or after. They simply indicate the order
|
||||
of the sequence relationship. For this reason, they are often called
|
||||
predecessor and successor tasks in the planning profession.
|
||||
|
||||
:param relating_process: The previous / predecessor task.
|
||||
:type relating_process: ifcopenshell.entity_instance
|
||||
:param related_process: The next / successor task.
|
||||
:type related_process: ifcopenshell.entity_instance
|
||||
:param sequence_type: Choose from FINISH_START, FINISH_FINISH,
|
||||
START_START, or START_FINISH.
|
||||
:return: The newly created IfcRelSequence
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param relating_process: The previous / predecessor task.
|
||||
:type relating_process: ifcopenshell.entity_instance
|
||||
:param related_process: The next / successor task.
|
||||
:type related_process: ifcopenshell.entity_instance
|
||||
:param sequence_type: Choose from FINISH_START, FINISH_FINISH,
|
||||
START_START, or START_FINISH.
|
||||
:return: The newly created IfcRelSequence
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's imagine we're doing a typically formwork, reinforcement,
|
||||
# pour sequence. Let's start with the formwork. It'll take us 2
|
||||
# days.
|
||||
formwork = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Formwork", identification="C.1")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
# Let's imagine we're doing a typically formwork, reinforcement,
|
||||
# pour sequence. Let's start with the formwork. It'll take us 2
|
||||
# days.
|
||||
formwork = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Formwork", identification="C.1")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
|
||||
# Now let's do the reinforcement. It'll take us another 2 days.
|
||||
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Reinforcement", identification="C.2")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
# Now let's do the reinforcement. It'll take us another 2 days.
|
||||
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Reinforcement", identification="C.2")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
|
||||
# Now the pour itself. It'll only take 1 day.
|
||||
pour = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Reinforcement", identification="C.3")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=pour)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P1D"})
|
||||
# Now the pour it It'll only take 1 day.
|
||||
pour = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Reinforcement", identification="C.3")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=pour)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P1D"})
|
||||
|
||||
# Now let's say the formwork must finish before the reinforcement
|
||||
# can start, and the reinforcement must finish before the pour can
|
||||
# start. This is a typical finish to start relationship (FS).
|
||||
ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=formwork, related_process=reinforcement)
|
||||
ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=reinforcement, related_process=pour)
|
||||
# Now let's say the formwork must finish before the reinforcement
|
||||
# can start, and the reinforcement must finish before the pour can
|
||||
# start. This is a typical finish to start relationship (FS).
|
||||
ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=formwork, related_process=reinforcement)
|
||||
ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=reinforcement, related_process=pour)
|
||||
|
||||
# Notice how we set all the scheduled start dates arbitrarily at
|
||||
# 2000-01-01. This is because we can ask IfcOpenShell to
|
||||
# automatically cascade the dates, starting from any task. This will
|
||||
# update the reinforcement date to be 2000-01-03 and the pour date
|
||||
# to be 2000-01-05.
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", model, task=formwork)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"relating_process": relating_process,
|
||||
"related_process": related_process,
|
||||
"sequence_type": sequence_type,
|
||||
# Notice how we set all the scheduled start dates arbitrarily at
|
||||
# 2000-01-01. This is because we can ask IfcOpenShell to
|
||||
# automatically cascade the dates, starting from any task. This will
|
||||
# update the reinforcement date to be 2000-01-03 and the pour date
|
||||
# to be 2000-01-05.
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", model, task=formwork)
|
||||
"""
|
||||
settings = {
|
||||
"relating_process": relating_process,
|
||||
"related_process": related_process,
|
||||
"sequence_type": sequence_type,
|
||||
}
|
||||
|
||||
for rel in settings["related_process"].IsSuccessorFrom or []:
|
||||
if rel.RelatingProcess == settings["relating_process"]:
|
||||
return rel
|
||||
rel = file.create_entity(
|
||||
"IfcRelSequence",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||
"RelatingProcess": settings["relating_process"],
|
||||
"RelatedProcess": settings["related_process"],
|
||||
"SequenceType": settings["sequence_type"],
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
for rel in self.settings["related_process"].IsSuccessorFrom or []:
|
||||
if rel.RelatingProcess == self.settings["relating_process"]:
|
||||
return rel
|
||||
rel = self.file.create_entity(
|
||||
"IfcRelSequence",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run(
|
||||
"owner.create_owner_history", self.file
|
||||
),
|
||||
"RelatingProcess": self.settings["relating_process"],
|
||||
"RelatedProcess": self.settings["related_process"],
|
||||
"SequenceType": self.settings["sequence_type"],
|
||||
}
|
||||
)
|
||||
ifcopenshell.api.run(
|
||||
"sequence.cascade_schedule", self.file, task=self.settings["relating_process"]
|
||||
)
|
||||
return rel
|
||||
)
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", file, task=settings["relating_process"])
|
||||
return rel
|
||||
|
||||
@@ -20,52 +20,49 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_schedule=None, work_plan=None):
|
||||
"""Assigns a work schedule to a work plan
|
||||
def assign_workplan(file, work_schedule=None, work_plan=None) -> None:
|
||||
"""Assigns a work schedule to a work plan
|
||||
|
||||
Typically, work schedules would be assigned to a work plan at creation.
|
||||
However you may also delay this and do it manually afterwards.
|
||||
Typically, work schedules would be assigned to a work plan at creation.
|
||||
However you may also delay this and do it manually afterwards.
|
||||
|
||||
:param work_schedule: The IfcWorkSchedule that will be assigned to the
|
||||
work plan.
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:param work_plan: The IfcWorkPlan for the schedule to be assigned to.
|
||||
:type work_plan: ifcopenshell.entity_instance
|
||||
:return: The IfcRelAggregates relationship
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
:param work_schedule: The IfcWorkSchedule that will be assigned to the
|
||||
work plan.
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:param work_plan: The IfcWorkPlan for the schedule to be assigned to.
|
||||
:type work_plan: ifcopenshell.entity_instance
|
||||
:return: The IfcRelAggregates relationship
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
|
||||
# Alternatively, if you create a schedule without a work plan ...
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Alternatively, if you create a schedule without a work plan ...
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# ... you can assign the work plan afterwards.
|
||||
ifcopenshell.api.run("sequence.assign_workplan", work_schedule=schedule, work_plan=work_plan)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_schedule": work_schedule, "work_plan": work_plan}
|
||||
# ... you can assign the work plan afterwards.
|
||||
ifcopenshell.api.run("sequence.assign_workplan", work_schedule=schedule, work_plan=work_plan)
|
||||
"""
|
||||
settings = {"work_schedule": work_schedule, "work_plan": work_plan}
|
||||
|
||||
def execute(self):
|
||||
# TODO: this is an ambiguity by buildingSMART
|
||||
# See https://forums.buildingsmart.org/t/is-the-ifcworkschedule-project-declaration-mutually-exclusive-to-aggregation-within-a-relating-ifcworkplan/3510
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
self.file,
|
||||
definitions=[self.settings["work_schedule"]],
|
||||
relating_context=self.file.by_type("IfcContext")[0],
|
||||
)
|
||||
rel_aggregates = ifcopenshell.api.run(
|
||||
"aggregate.assign_object",
|
||||
self.file,
|
||||
**{
|
||||
"products": [self.settings["work_schedule"]],
|
||||
"relating_object": self.settings["work_plan"],
|
||||
}
|
||||
)
|
||||
return rel_aggregates
|
||||
# TODO: this is an ambiguity by buildingSMART
|
||||
# See https://forums.buildingsmart.org/t/is-the-ifcworkschedule-project-declaration-mutually-exclusive-to-aggregation-within-a-relating-ifcworkplan/3510
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
file,
|
||||
definitions=[settings["work_schedule"]],
|
||||
relating_context=file.by_type("IfcContext")[0],
|
||||
)
|
||||
rel_aggregates = ifcopenshell.api.run(
|
||||
"aggregate.assign_object",
|
||||
file,
|
||||
**{
|
||||
"products": [settings["work_schedule"]],
|
||||
"relating_object": settings["work_plan"],
|
||||
}
|
||||
)
|
||||
return rel_aggregates
|
||||
|
||||
@@ -22,68 +22,71 @@ import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
def calculate_task_duration(file, task=None) -> None:
|
||||
"""Calculates the task duration based on resource usage
|
||||
|
||||
If a task has labour or equipment resources assigned to it, its duration
|
||||
may be parametrically derived from the scheduled work of the resource.
|
||||
For example, a labour resource with scheduled work of 10 working days
|
||||
and a resource utilisation of 200% (i.e. two labour teams) will imply
|
||||
that the task duration is 5 working days.
|
||||
|
||||
If this data is not available, such as if the task has no resources,
|
||||
then nothing happens.
|
||||
|
||||
:param task: The IfcTask to calculate the duration for.
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some labour to our crew.
|
||||
labour = ifcopenshell.api.run("resource.add_resource", model,
|
||||
parent_resource=crew, ifc_class="IfcLaborResource")
|
||||
|
||||
# Labour resource is quantified in terms of time.
|
||||
quantity = ifcopenshell.api.run("resource.add_resource_quantity", model,
|
||||
resource=labour, ifc_class="IfcQuantityTime")
|
||||
|
||||
# Store the unit time used in hours
|
||||
ifcopenshell.api.run("resource.edit_resource_quantity", model,
|
||||
physical_quantity=quantity, attributes={"TimeValue": 8.0})
|
||||
|
||||
# Let's imagine we've used the resource for 10 days with a
|
||||
# utilisation of 200%.
|
||||
time = ifcopenshell.api.run("resource.add_resource_time", model, resource=labour)
|
||||
ifcopenshell.api.run("resource.edit_resource_time", model,
|
||||
resource_time=time, attributes={"ScheduleWork": "PT80H", "ScheduleUsage": 2})
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Foundations", identification="A")
|
||||
|
||||
# Assign our resource to the task.
|
||||
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=labour)
|
||||
|
||||
# Now we can calculate the task duration based on the resource. This
|
||||
# will set task.TaskTime.ScheduleDuration to be P5D.
|
||||
ifcopenshell.api.run("sequence.calculate_task_duration", model, task=task)
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"task": task}
|
||||
return usecase.execute()
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, task=None):
|
||||
"""Calculates the task duration based on resource usage
|
||||
|
||||
If a task has labour or equipment resources assigned to it, its duration
|
||||
may be parametrically derived from the scheduled work of the resource.
|
||||
For example, a labour resource with scheduled work of 10 working days
|
||||
and a resource utilisation of 200% (i.e. two labour teams) will imply
|
||||
that the task duration is 5 working days.
|
||||
|
||||
If this data is not available, such as if the task has no resources,
|
||||
then nothing happens.
|
||||
|
||||
:param task: The IfcTask to calculate the duration for.
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some labour to our crew.
|
||||
labour = ifcopenshell.api.run("resource.add_resource", model,
|
||||
parent_resource=crew, ifc_class="IfcLaborResource")
|
||||
|
||||
# Labour resource is quantified in terms of time.
|
||||
quantity = ifcopenshell.api.run("resource.add_resource_quantity", model,
|
||||
resource=labour, ifc_class="IfcQuantityTime")
|
||||
|
||||
# Store the unit time used in hours
|
||||
ifcopenshell.api.run("resource.edit_resource_quantity", model,
|
||||
physical_quantity=quantity, attributes={"TimeValue": 8.0})
|
||||
|
||||
# Let's imagine we've used the resource for 10 days with a
|
||||
# utilisation of 200%.
|
||||
time = ifcopenshell.api.run("resource.add_resource_time", model, resource=labour)
|
||||
ifcopenshell.api.run("resource.edit_resource_time", model,
|
||||
resource_time=time, attributes={"ScheduleWork": "PT80H", "ScheduleUsage": 2})
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Foundations", identification="A")
|
||||
|
||||
# Assign our resource to the task.
|
||||
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=labour)
|
||||
|
||||
# Now we can calculate the task duration based on the resource. This
|
||||
# will set task.TaskTime.ScheduleDuration to be P5D.
|
||||
ifcopenshell.api.run("sequence.calculate_task_duration", model, task=task)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"task": task}
|
||||
|
||||
def execute(self):
|
||||
self.seconds_per_workday = self.calculate_seconds_per_workday()
|
||||
duration = self.calculate_max_resource_usage_duration()
|
||||
@@ -93,9 +96,7 @@ class Usecase:
|
||||
def calculate_seconds_per_workday(self):
|
||||
def get_work_schedule(task):
|
||||
for rel in task.HasAssignments or []:
|
||||
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a(
|
||||
"IfcWorkSchedule"
|
||||
):
|
||||
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcWorkSchedule"):
|
||||
return rel.RelatingControl
|
||||
for rel in task.Nests or []:
|
||||
return get_work_schedule(rel.RelatingObject)
|
||||
@@ -111,9 +112,7 @@ class Usecase:
|
||||
or "WorkDayDuration" not in psets["Pset_WorkControlCommon"]
|
||||
):
|
||||
return default_seconds_per_workday
|
||||
work_day_duration = ifcopenshell.util.date.ifc2datetime(
|
||||
psets["Pset_WorkControlCommon"]["WorkDayDuration"]
|
||||
)
|
||||
work_day_duration = ifcopenshell.util.date.ifc2datetime(psets["Pset_WorkControlCommon"]["WorkDayDuration"])
|
||||
return work_day_duration.seconds
|
||||
|
||||
def calculate_max_resource_usage_duration(self):
|
||||
@@ -133,23 +132,15 @@ class Usecase:
|
||||
if not resource.Usage or not resource.Usage.ScheduleWork:
|
||||
return
|
||||
schedule_usage = resource.Usage.ScheduleUsage or 1
|
||||
schedule_duration = ifcopenshell.util.date.ifc2datetime(
|
||||
resource.Usage.ScheduleWork
|
||||
)
|
||||
schedule_duration = ifcopenshell.util.date.ifc2datetime(resource.Usage.ScheduleWork)
|
||||
if is_hourly_work(resource.Usage.ScheduleWork):
|
||||
schedule_seconds = (
|
||||
schedule_duration.days * 24 * 60 * 60
|
||||
) + schedule_duration.seconds
|
||||
schedule_seconds = (schedule_duration.days * 24 * 60 * 60) + schedule_duration.seconds
|
||||
else:
|
||||
partial_days = schedule_duration.seconds / (24 * 60 * 60)
|
||||
schedule_seconds = (
|
||||
schedule_duration.days + partial_days
|
||||
) * self.seconds_per_workday
|
||||
schedule_seconds = (schedule_duration.days + partial_days) * self.seconds_per_workday
|
||||
return math.ceil((schedule_seconds / self.seconds_per_workday) / schedule_usage)
|
||||
|
||||
def set_task_duration(self, duration):
|
||||
if not self.settings["task"].TaskTime:
|
||||
ifcopenshell.api.run(
|
||||
"sequence.add_task_time", self.file, task=self.settings["task"]
|
||||
)
|
||||
ifcopenshell.api.run("sequence.add_task_time", self.file, task=self.settings["task"])
|
||||
self.settings["task"].TaskTime.ScheduleDuration = f"P{duration}D"
|
||||
|
||||
@@ -21,90 +21,93 @@ import ifcopenshell.util.date
|
||||
import ifcopenshell.util.sequence
|
||||
|
||||
|
||||
def cascade_schedule(file, task=None) -> None:
|
||||
"""Cascades start and end dates of tasks based on durations
|
||||
|
||||
Given a start task with a start date and duration, the end date, and the
|
||||
start and end of all successor tasks with durations may be automatically
|
||||
computed.
|
||||
|
||||
Using this automatic computation is recommended is an alternative to
|
||||
manually specifying dates. It is useful for doing edits and cascading
|
||||
changes.
|
||||
|
||||
Dates can only cascade from predecessor to successors, not backwards.
|
||||
Cyclical relationships are invalid and will result in a recursion error
|
||||
being raised.
|
||||
|
||||
Note that there may be differences between how different planning
|
||||
software calculate start and end dates. Some may consider Monday 5pm to
|
||||
be equivalent to be Tuesday 8am, for instance.
|
||||
|
||||
:param task: The start task to begin cascading from.
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Define a convenience function to add a task chained to a predecessor
|
||||
def add_task(model, name, predecessor, work_schedule):
|
||||
# Add a construction task
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=work_schedule, name=name, predefined_type="CONSTRUCTION")
|
||||
|
||||
# Give it a time
|
||||
task_time = ifcopenshell.api.run("sequence.add_task_time", model, task=task)
|
||||
|
||||
# Arbitrarily set the task's scheduled time duration to be 1 week
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model, task_time=task_time,
|
||||
attributes={"ScheduleStart": datetime.date(2000, 1, 1), "ScheduleDuration": "P1W"})
|
||||
|
||||
# If a predecessor exists, create a finish to start relationship
|
||||
if predecessor:
|
||||
ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=predecessor, related_process=task)
|
||||
|
||||
return task
|
||||
|
||||
# Open an existing IFC4 model you have of a building
|
||||
model = ifcopenshell.open("/path/to/existing/model.ifc")
|
||||
|
||||
# Create a new construction schedule
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction")
|
||||
|
||||
# Let's imagine a starting task for site establishment.
|
||||
task = add_task(model, "Site establishment", None, schedule)
|
||||
start_task = task
|
||||
|
||||
# Get all our storeys sorted by elevation ascending.
|
||||
storeys = sorted(model.by_type("IfcBuildingStorey"), key=lambda s: get_storey_elevation(s))
|
||||
|
||||
# For each storey ...
|
||||
for storey in storeys:
|
||||
|
||||
# Add a construction task to construct that storey, using our convenience function
|
||||
task = add_task(model, f"Construct {storey.Name}", task, schedule)
|
||||
|
||||
# Assign all the products in that storey to the task as construction outputs.
|
||||
for product in get_decomposition(storey):
|
||||
ifcopenshell.api.run("sequence.assign_product", model, relating_product=product, related_object=task)
|
||||
|
||||
# Ask the computer to calculate all the dates for us from the start task.
|
||||
# For example, if the first task started on the 1st of January and took a
|
||||
# week, the next task will start on the 8th of January. This saves us
|
||||
# manually doing date calculations.
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", model, task=start_task)
|
||||
|
||||
# Calculate the critical path and floats.
|
||||
ifcopenshell.api.run("sequence.recalculate_schedule", model, work_schedule=schedule)
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"task": task}
|
||||
return usecase.execute()
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, task=None):
|
||||
"""Cascades start and end dates of tasks based on durations
|
||||
|
||||
Given a start task with a start date and duration, the end date, and the
|
||||
start and end of all successor tasks with durations may be automatically
|
||||
computed.
|
||||
|
||||
Using this automatic computation is recommended is an alternative to
|
||||
manually specifying dates. It is useful for doing edits and cascading
|
||||
changes.
|
||||
|
||||
Dates can only cascade from predecessor to successors, not backwards.
|
||||
Cyclical relationships are invalid and will result in a recursion error
|
||||
being raised.
|
||||
|
||||
Note that there may be differences between how different planning
|
||||
software calculate start and end dates. Some may consider Monday 5pm to
|
||||
be equivalent to be Tuesday 8am, for instance.
|
||||
|
||||
:param task: The start task to begin cascading from.
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Define a convenience function to add a task chained to a predecessor
|
||||
def add_task(model, name, predecessor, work_schedule):
|
||||
# Add a construction task
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=work_schedule, name=name, predefined_type="CONSTRUCTION")
|
||||
|
||||
# Give it a time
|
||||
task_time = ifcopenshell.api.run("sequence.add_task_time", model, task=task)
|
||||
|
||||
# Arbitrarily set the task's scheduled time duration to be 1 week
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model, task_time=task_time,
|
||||
attributes={"ScheduleStart": datetime.date(2000, 1, 1), "ScheduleDuration": "P1W"})
|
||||
|
||||
# If a predecessor exists, create a finish to start relationship
|
||||
if predecessor:
|
||||
ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=predecessor, related_process=task)
|
||||
|
||||
return task
|
||||
|
||||
# Open an existing IFC4 model you have of a building
|
||||
model = ifcopenshell.open("/path/to/existing/model.ifc")
|
||||
|
||||
# Create a new construction schedule
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction")
|
||||
|
||||
# Let's imagine a starting task for site establishment.
|
||||
task = add_task(model, "Site establishment", None, schedule)
|
||||
start_task = task
|
||||
|
||||
# Get all our storeys sorted by elevation ascending.
|
||||
storeys = sorted(model.by_type("IfcBuildingStorey"), key=lambda s: get_storey_elevation(s))
|
||||
|
||||
# For each storey ...
|
||||
for storey in storeys:
|
||||
|
||||
# Add a construction task to construct that storey, using our convenience function
|
||||
task = add_task(model, f"Construct {storey.Name}", task, schedule)
|
||||
|
||||
# Assign all the products in that storey to the task as construction outputs.
|
||||
for product in get_decomposition(storey):
|
||||
ifcopenshell.api.run("sequence.assign_product", model, relating_product=product, related_object=task)
|
||||
|
||||
# Ask the computer to calculate all the dates for us from the start task.
|
||||
# For example, if the first task started on the 1st of January and took a
|
||||
# week, the next task will start on the 8th of January. This saves us
|
||||
# manually doing date calculations.
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", model, task=start_task)
|
||||
|
||||
# Calculate the critical path and floats.
|
||||
ifcopenshell.api.run("sequence.recalculate_schedule", model, work_schedule=schedule)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"task": task}
|
||||
|
||||
def execute(self):
|
||||
self.calendar_cache = {}
|
||||
self.cascade_task(self.settings["task"], is_first_task=True)
|
||||
@@ -135,14 +138,10 @@ class Usecase:
|
||||
finishes = []
|
||||
starts = []
|
||||
|
||||
for rel in ifcopenshell.util.sequence.get_sequence_assignment(
|
||||
task, "predecessor"
|
||||
):
|
||||
for rel in ifcopenshell.util.sequence.get_sequence_assignment(task, "predecessor"):
|
||||
predecessor = rel.RelatingProcess
|
||||
predecessor_duration = (
|
||||
ifcopenshell.util.date.ifc2datetime(
|
||||
predecessor.TaskTime.ScheduleDuration
|
||||
)
|
||||
ifcopenshell.util.date.ifc2datetime(predecessor.TaskTime.ScheduleDuration)
|
||||
if predecessor.TaskTime and predecessor.TaskTime.ScheduleDuration
|
||||
else datetime.timedelta()
|
||||
)
|
||||
@@ -154,14 +153,16 @@ class Usecase:
|
||||
duration_type = "WORKTIME"
|
||||
if rel.TimeLag:
|
||||
# updated to handle IfcRatioMeasure as a TimeLag value
|
||||
days += self.get_lag_time_days(rel.TimeLag) if rel.TimeLag.LagValue.is_a("IfcDuration") else predecessor_duration.days * rel.TimeLag.LagValue.wrappedValue
|
||||
days += (
|
||||
self.get_lag_time_days(rel.TimeLag)
|
||||
if rel.TimeLag.LagValue.is_a("IfcDuration")
|
||||
else predecessor_duration.days * rel.TimeLag.LagValue.wrappedValue
|
||||
)
|
||||
duration_type = rel.TimeLag.DurationType
|
||||
if days:
|
||||
starts.append(
|
||||
datetime.datetime.combine(
|
||||
self.offset_date(
|
||||
finish, days, duration_type, self.get_calendar(task)
|
||||
),
|
||||
self.offset_date(finish, days, duration_type, self.get_calendar(task)),
|
||||
datetime.time(9),
|
||||
)
|
||||
)
|
||||
@@ -183,18 +184,14 @@ class Usecase:
|
||||
if not start:
|
||||
continue
|
||||
if rel.TimeLag:
|
||||
days = self.get_lag_time_days(rel.TimeLag) if rel.TimeLag.LagValue.is_a("IfcDuration") else predecessor_duration.days * rel.TimeLag.LagValue.wrappedValue
|
||||
days = (
|
||||
self.get_lag_time_days(rel.TimeLag)
|
||||
if rel.TimeLag.LagValue.is_a("IfcDuration")
|
||||
else predecessor_duration.days * rel.TimeLag.LagValue.wrappedValue
|
||||
)
|
||||
duration_type = rel.TimeLag.DurationType
|
||||
starts.append(
|
||||
self.offset_date(
|
||||
start, days, duration_type, self.get_calendar(task)
|
||||
)
|
||||
)
|
||||
starts.append(
|
||||
self.offset_date(
|
||||
start, days, duration_type, self.get_calendar(predecessor)
|
||||
)
|
||||
)
|
||||
starts.append(self.offset_date(start, days, duration_type, self.get_calendar(task)))
|
||||
starts.append(self.offset_date(start, days, duration_type, self.get_calendar(predecessor)))
|
||||
else:
|
||||
starts.append(start)
|
||||
elif rel.SequenceType == "FINISH_FINISH":
|
||||
@@ -202,18 +199,14 @@ class Usecase:
|
||||
if not finish:
|
||||
continue
|
||||
if rel.TimeLag:
|
||||
days = self.get_lag_time_days(rel.TimeLag) if rel.TimeLag.LagValue.is_a("IfcDuration") else predecessor_duration.days * rel.TimeLag.LagValue.wrappedValue
|
||||
days = (
|
||||
self.get_lag_time_days(rel.TimeLag)
|
||||
if rel.TimeLag.LagValue.is_a("IfcDuration")
|
||||
else predecessor_duration.days * rel.TimeLag.LagValue.wrappedValue
|
||||
)
|
||||
duration_type = rel.TimeLag.DurationType
|
||||
finishes.append(
|
||||
self.offset_date(
|
||||
finish, days, duration_type, self.get_calendar(task)
|
||||
)
|
||||
)
|
||||
finishes.append(
|
||||
self.offset_date(
|
||||
finish, days, duration_type, self.get_calendar(predecessor)
|
||||
)
|
||||
)
|
||||
finishes.append(self.offset_date(finish, days, duration_type, self.get_calendar(task)))
|
||||
finishes.append(self.offset_date(finish, days, duration_type, self.get_calendar(predecessor)))
|
||||
else:
|
||||
finishes.append(finish)
|
||||
elif rel.SequenceType == "START_FINISH":
|
||||
@@ -223,14 +216,16 @@ class Usecase:
|
||||
days = -1
|
||||
duration_type = "WORKTIME"
|
||||
if rel.TimeLag:
|
||||
days += self.get_lag_time_days(rel.TimeLag) if rel.TimeLag.LagValue.is_a("IfcDuration") else predecessor_duration.days * rel.TimeLag.LagValue.wrappedValue
|
||||
days += (
|
||||
self.get_lag_time_days(rel.TimeLag)
|
||||
if rel.TimeLag.LagValue.is_a("IfcDuration")
|
||||
else predecessor_duration.days * rel.TimeLag.LagValue.wrappedValue
|
||||
)
|
||||
duration_type = rel.TimeLag.DurationType
|
||||
if days or rel.TimeLag:
|
||||
finishes.append(
|
||||
datetime.datetime.combine(
|
||||
self.offset_date(
|
||||
start, days, duration_type, self.get_calendar(task)
|
||||
),
|
||||
self.offset_date(start, days, duration_type, self.get_calendar(task)),
|
||||
datetime.time(17),
|
||||
)
|
||||
)
|
||||
@@ -263,9 +258,7 @@ class Usecase:
|
||||
if task.TaskTime.ScheduleStart == start_ifc and not is_first_task:
|
||||
return
|
||||
task.TaskTime.ScheduleStart = start_ifc
|
||||
task.TaskTime.ScheduleFinish = ifcopenshell.util.date.datetime2ifc(
|
||||
potential_finish, "IfcDateTime"
|
||||
)
|
||||
task.TaskTime.ScheduleFinish = ifcopenshell.util.date.datetime2ifc(potential_finish, "IfcDateTime")
|
||||
else:
|
||||
finish_ifc = ifcopenshell.util.date.datetime2ifc(finish, "IfcDateTime")
|
||||
if task.TaskTime.ScheduleFinish == finish_ifc and not is_first_task:
|
||||
@@ -328,15 +321,11 @@ class Usecase:
|
||||
|
||||
def get_calendar(self, task):
|
||||
if task.id() not in self.calendar_cache:
|
||||
self.calendar_cache[task.id()] = ifcopenshell.util.sequence.derive_calendar(
|
||||
task
|
||||
)
|
||||
self.calendar_cache[task.id()] = ifcopenshell.util.sequence.derive_calendar(task)
|
||||
return self.calendar_cache[task.id()]
|
||||
|
||||
def offset_date(self, date, days, duration_type, calendar):
|
||||
return ifcopenshell.util.sequence.offset_date(
|
||||
date, datetime.timedelta(days=days), duration_type, calendar
|
||||
)
|
||||
return ifcopenshell.util.sequence.offset_date(date, datetime.timedelta(days=days), duration_type, calendar)
|
||||
|
||||
def get_task_time_attribute(self, task, attribute):
|
||||
if task.TaskTime:
|
||||
|
||||
@@ -21,38 +21,41 @@ import ifcopenshell.util.system
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
def create_baseline(file, work_schedule=None, name=None) -> None:
|
||||
"""Creates a baseline for your Work Schedule
|
||||
|
||||
Using a IfcWorkSchdule having PredefinedType=PLANNED,
|
||||
We can create a baseline for our work schedule. This IfcWorkSchedule will have PredefinedType=BASELINE
|
||||
and the IfcWorkSchedule.CreationDate indicating the date of the baseline creation, and IfcWorkSchedule.Name indicating the name of the baseline.
|
||||
|
||||
The following relationships are also baselined:
|
||||
|
||||
* Same Tasks & attributes
|
||||
* Same Task Relationships
|
||||
* Same Construction Resources
|
||||
* Same Resource Relationships
|
||||
|
||||
:param work_schedule: The planned work_schedule to baseline
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:return: The baseline work_schedule
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
.. code:: python
|
||||
|
||||
# We have a Work Schedule
|
||||
planned_work_schedule = WorkSchedule(name="Design new feature",predefinedType="PLANNED", deadline="2023-03-01")
|
||||
|
||||
# And now we have a baseline for our Work Schedule
|
||||
baseline_work_schedule = ifcopenshell.api.run("sequence.create_baseline",file, work_schedule= planned_work_schedule, name="Baseline 1")
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"work_schedule": work_schedule, "name": name}
|
||||
return usecase.execute()
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_schedule=None, name=None):
|
||||
"""Creates a baseline for your Work Schedule
|
||||
|
||||
Using a IfcWorkSchdule having PredefinedType=PLANNED,
|
||||
We can create a baseline for our work schedule. This IfcWorkSchedule will have PredefinedType=BASELINE
|
||||
and the IfcWorkSchedule.CreationDate indicating the date of the baseline creation, and IfcWorkSchedule.Name indicating the name of the baseline.
|
||||
|
||||
The following relationships are also baselined:
|
||||
|
||||
* Same Tasks & attributes
|
||||
* Same Task Relationships
|
||||
* Same Construction Resources
|
||||
* Same Resource Relationships
|
||||
|
||||
:param work_schedule: The planned work_schedule to baseline
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:return: The baseline work_schedule
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
.. code:: python
|
||||
|
||||
# We have a Work Schedule
|
||||
planned_work_schedule = WorkSchedule(name="Design new feature",predefinedType="PLANNED", deadline="2023-03-01")
|
||||
|
||||
# And now we have a baseline for our Work Schedule
|
||||
baseline_work_schedule = ifcopenshell.api.run("sequence.create_baseline",file, work_schedule= planned_work_schedule, name="Baseline 1")
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_schedule": work_schedule, "name": name}
|
||||
|
||||
def execute(self):
|
||||
result = self.create_baseline_work_schedule(self.settings["work_schedule"])
|
||||
return result
|
||||
@@ -92,17 +95,13 @@ class Usecase:
|
||||
related_objects = list(referenced_by.RelatedObjects)
|
||||
related_objects.append(related_object)
|
||||
referenced_by.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run(
|
||||
"owner.update_owner_history", self.file, **{"element": referenced_by}
|
||||
)
|
||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": referenced_by})
|
||||
else:
|
||||
referenced_by = self.file.create_entity(
|
||||
"IfcRelDefinesByObject",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run(
|
||||
"owner.create_owner_history", self.file
|
||||
),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatedObjects": [related_object],
|
||||
"RelatingObject": relating_object,
|
||||
}
|
||||
|
||||
@@ -22,33 +22,36 @@ import ifcopenshell.util.element
|
||||
import ifcopenshell.util.sequence
|
||||
|
||||
|
||||
def duplicate_task(file, task=None) -> None:
|
||||
"""Duplicates a task in the project
|
||||
|
||||
The following relationships are also duplicated:
|
||||
|
||||
* The copy will have the same attributes and property sets as the original task
|
||||
* The copy will be assigned to the parent task or work schedule
|
||||
* The copy will have duplicated nested tasks
|
||||
|
||||
:param task: The task to be duplicated
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:return: The duplicated task or the list of duplicated tasks if the latter has children
|
||||
:rtype: ifcopenshell.entity_instance or list of ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
.. code:: python
|
||||
|
||||
# We have a task
|
||||
original_task = Task(name="Design new feature", deadline="2023-03-01")
|
||||
|
||||
# And now we have two
|
||||
duplicated_task = project.duplicate_task(original_task)
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"task": task}
|
||||
return usecase.execute()
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, task=None):
|
||||
"""Duplicates a task in the project
|
||||
|
||||
The following relationships are also duplicated:
|
||||
|
||||
* The copy will have the same attributes and property sets as the original task
|
||||
* The copy will be assigned to the parent task or work schedule
|
||||
* The copy will have duplicated nested tasks
|
||||
|
||||
:param task: The task to be duplicated
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:return: The duplicated task or the list of duplicated tasks if the latter has children
|
||||
:rtype: ifcopenshell.entity_instance or list of ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
.. code:: python
|
||||
|
||||
# We have a task
|
||||
original_task = Task(name="Design new feature", deadline="2023-03-01")
|
||||
|
||||
# And now we have two
|
||||
duplicated_task = project.duplicate_task(original_task)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"task": task}
|
||||
|
||||
def execute(self):
|
||||
self.tracker = {"current": [], "duplicate": []}
|
||||
self.duplicate_task(self.settings["task"])
|
||||
|
||||
@@ -20,79 +20,68 @@ import ifcopenshell.api
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, lag_time=None, attributes=None):
|
||||
"""Edits the attributes of an IfcLagTime
|
||||
def edit_lag_time(file, lag_time=None, attributes=None) -> None:
|
||||
"""Edits the attributes of an IfcLagTime
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcLagTime, consult the IFC documentation.
|
||||
For more information about the attributes and data types of an
|
||||
IfcLagTime, consult the IFC documentation.
|
||||
|
||||
:param lag_time: The IfcLagTime entity you want to edit
|
||||
:type lag_time: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param lag_time: The IfcLagTime entity you want to edit
|
||||
:type lag_time: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's imagine we're doing a typically formwork, reinforcement,
|
||||
# pour sequence. Let's start with the formwork. It'll take us 2
|
||||
# days.
|
||||
formwork = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Formwork", identification="C.1")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
# Let's imagine we're doing a typically formwork, reinforcement,
|
||||
# pour sequence. Let's start with the formwork. It'll take us 2
|
||||
# days.
|
||||
formwork = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Formwork", identification="C.1")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
|
||||
# Now let's do the reinforcement. It'll take us another 2 days.
|
||||
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Reinforcement", identification="C.2")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
# Now let's do the reinforcement. It'll take us another 2 days.
|
||||
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Reinforcement", identification="C.2")
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
|
||||
# Now let's say the formwork must finish before the reinforcement
|
||||
# can start. This is a typical finish to start relationship (FS).
|
||||
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=formwork, related_process=reinforcement)
|
||||
# Now let's say the formwork must finish before the reinforcement
|
||||
# can start. This is a typical finish to start relationship (FS).
|
||||
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=formwork, related_process=reinforcement)
|
||||
|
||||
# Now typically there would be no lag time between formwork and
|
||||
# reinforcement, but let's pretend that we had to allow 1 day gap
|
||||
# for whatever reason.
|
||||
lag = ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1D")
|
||||
# Now typically there would be no lag time between formwork and
|
||||
# reinforcement, but let's pretend that we had to allow 1 day gap
|
||||
# for whatever reason.
|
||||
lag = ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1D")
|
||||
|
||||
# Or, let's make it 2 days instead.
|
||||
ifcopenshell.api.run("sequence.edit_lag_time", model, lag_time=lag, attributes={"LagValue": "P2D"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"lag_time": lag_time, "attributes": attributes or {}}
|
||||
# Or, let's make it 2 days instead.
|
||||
ifcopenshell.api.run("sequence.edit_lag_time", model, lag_time=lag, attributes={"LagValue": "P2D"})
|
||||
"""
|
||||
settings = {"lag_time": lag_time, "attributes": attributes or {}}
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
if name == "LagValue" and value is not None:
|
||||
if isinstance(value, float):
|
||||
value = self.file.createIfcRatioMeasure(value)
|
||||
else:
|
||||
value = self.file.createIfcDuration(
|
||||
ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
)
|
||||
setattr(self.settings["lag_time"], name, value)
|
||||
for rel in [
|
||||
r
|
||||
for r in self.file.get_inverse(self.settings["lag_time"])
|
||||
if r.is_a("IfcRelSequence")
|
||||
]:
|
||||
ifcopenshell.api.run(
|
||||
"sequence.cascade_schedule", self.file, task=rel.RelatedProcess
|
||||
)
|
||||
for name, value in settings["attributes"].items():
|
||||
if name == "LagValue" and value is not None:
|
||||
if isinstance(value, float):
|
||||
value = file.createIfcRatioMeasure(value)
|
||||
else:
|
||||
value = file.createIfcDuration(ifcopenshell.util.date.datetime2ifc(value, "IfcDuration"))
|
||||
setattr(settings["lag_time"], name, value)
|
||||
for rel in [r for r in file.get_inverse(settings["lag_time"]) if r.is_a("IfcRelSequence")]:
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", file, task=rel.RelatedProcess)
|
||||
|
||||
@@ -20,48 +20,45 @@ import ifcopenshell
|
||||
import ifcopenshell.util.sequence
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, recurrence_pattern=None, attributes=None):
|
||||
"""Edits the attributes of an IfcRecurrencePattern
|
||||
def edit_recurrence_pattern(file, recurrence_pattern=None, attributes=None) -> None:
|
||||
"""Edits the attributes of an IfcRecurrencePattern
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcRecurrencePattern, consult the IFC documentation.
|
||||
For more information about the attributes and data types of an
|
||||
IfcRecurrencePattern, consult the IFC documentation.
|
||||
|
||||
:param recurrence_pattern: The IfcRecurrencePattern entity you want to edit
|
||||
:type recurrence_pattern: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param recurrence_pattern: The IfcRecurrencePattern entity you want to edit
|
||||
:type recurrence_pattern: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"recurrence_pattern": recurrence_pattern,
|
||||
"attributes": attributes or {},
|
||||
}
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
"""
|
||||
settings = {
|
||||
"recurrence_pattern": recurrence_pattern,
|
||||
"attributes": attributes or {},
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["recurrence_pattern"], name, value)
|
||||
for name, value in settings["attributes"].items():
|
||||
setattr(settings["recurrence_pattern"], name, value)
|
||||
|
||||
ifcopenshell.util.sequence.is_working_day.cache_clear()
|
||||
ifcopenshell.util.sequence.is_calendar_applicable.cache_clear()
|
||||
ifcopenshell.util.sequence.is_working_day.cache_clear()
|
||||
ifcopenshell.util.sequence.is_calendar_applicable.cache_clear()
|
||||
|
||||
@@ -20,55 +20,52 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, rel_sequence=None, attributes=None):
|
||||
"""Edits the attributes of an IfcRelSequence
|
||||
def edit_sequence(file, rel_sequence=None, attributes=None) -> None:
|
||||
"""Edits the attributes of an IfcRelSequence
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcRelSequence, consult the IFC documentation.
|
||||
For more information about the attributes and data types of an
|
||||
IfcRelSequence, consult the IFC documentation.
|
||||
|
||||
:param rel_sequence: The IfcRelSequence entity you want to edit
|
||||
:type rel_sequence: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param rel_sequence: The IfcRelSequence entity you want to edit
|
||||
:type rel_sequence: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's imagine we're building 2 zones, one after another.
|
||||
zone1 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 1", identification="C.1")
|
||||
zone2 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 2", identification="C.2")
|
||||
# Let's imagine we're building 2 zones, one after another.
|
||||
zone1 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 1", identification="C.1")
|
||||
zone2 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 2", identification="C.2")
|
||||
|
||||
# Zone 1 finishes, then zone 2 starts.
|
||||
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=zone1, related_process=zone2)
|
||||
# Zone 1 finishes, then zone 2 starts.
|
||||
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=zone1, related_process=zone2)
|
||||
|
||||
# What if they both started at the same time?
|
||||
ifcopenshell.api.run("sequence.edit_sequence", model,
|
||||
rel_sequence=sequence, attributes={"SequenceType": "START_START"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"rel_sequence": rel_sequence, "attributes": attributes or {}}
|
||||
# What if they both started at the same time?
|
||||
ifcopenshell.api.run("sequence.edit_sequence", model,
|
||||
rel_sequence=sequence, attributes={"SequenceType": "START_START"})
|
||||
"""
|
||||
settings = {"rel_sequence": rel_sequence, "attributes": attributes or {}}
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["rel_sequence"], name, value)
|
||||
if "SequenceType" in self.settings["attributes"].keys():
|
||||
ifcopenshell.api.run(
|
||||
"sequence.cascade_schedule",
|
||||
self.file,
|
||||
task=self.settings["rel_sequence"].RelatedProcess,
|
||||
)
|
||||
for name, value in settings["attributes"].items():
|
||||
setattr(settings["rel_sequence"], name, value)
|
||||
if "SequenceType" in settings["attributes"].keys():
|
||||
ifcopenshell.api.run(
|
||||
"sequence.cascade_schedule",
|
||||
file,
|
||||
task=settings["rel_sequence"].RelatedProcess,
|
||||
)
|
||||
|
||||
@@ -17,39 +17,36 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, task=None, attributes=None):
|
||||
"""Edits the attributes of an IfcTask
|
||||
def edit_task(file, task=None, attributes=None) -> None:
|
||||
"""Edits the attributes of an IfcTask
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcTask, consult the IFC documentation.
|
||||
For more information about the attributes and data types of an
|
||||
IfcTask, consult the IFC documentation.
|
||||
|
||||
:param task: The IfcTask entity you want to edit
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param task: The IfcTask entity you want to edit
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Add a root task to represent the design milestones, and major
|
||||
# project phases.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Milestones", identification="A")
|
||||
# Add a root task to represent the design milestones, and major
|
||||
# project phases.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Milestones", identification="A")
|
||||
|
||||
# Change the identification
|
||||
ifcopenshell.api.run("sequence.edit_task", model, task=task, attributes={"Identification": "M"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"task": task, "attributes": attributes or {}}
|
||||
# Change the identification
|
||||
ifcopenshell.api.run("sequence.edit_task", model, task=task, attributes={"Identification": "M"})
|
||||
"""
|
||||
settings = {"task": task, "attributes": attributes or {}}
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["task"], name, value)
|
||||
for name, value in settings["attributes"].items():
|
||||
setattr(settings["task"], name, value)
|
||||
|
||||
@@ -23,46 +23,48 @@ import ifcopenshell.util.sequence
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
def edit_task_time(
|
||||
file: ifcopenshell.file,
|
||||
task_time: ifcopenshell.entity_instance,
|
||||
attributes: Optional[dict[str, Any]] = None,
|
||||
) -> None:
|
||||
"""Edits the attributes of an IfcTaskTime
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcTaskTime, consult the IFC documentation.
|
||||
|
||||
:param task_time: The IfcTaskTime entity you want to edit
|
||||
:type task_time: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Create a task to do formwork
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Formwork", identification="A")
|
||||
|
||||
# Let's say it takes 2 days and starts on the 1st of January, 2000
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"task_time": task_time, "attributes": attributes or {}}
|
||||
return usecase.execute()
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(
|
||||
self,
|
||||
file: ifcopenshell.file,
|
||||
task_time: ifcopenshell.entity_instance,
|
||||
attributes: Optional[dict[str, Any]] = None,
|
||||
):
|
||||
"""Edits the attributes of an IfcTaskTime
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcTaskTime, consult the IFC documentation.
|
||||
|
||||
:param task_time: The IfcTaskTime entity you want to edit
|
||||
:type task_time: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Create a task to do formwork
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Formwork", identification="A")
|
||||
|
||||
# Let's say it takes 2 days and starts on the 1st of January, 2000
|
||||
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
|
||||
ifcopenshell.api.run("sequence.edit_task_time", model,
|
||||
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"task_time": task_time, "attributes": attributes or {}}
|
||||
|
||||
def execute(self) -> None:
|
||||
def execute(self):
|
||||
self.task = self.get_task()
|
||||
self.calendar = ifcopenshell.util.sequence.derive_calendar(self.task)
|
||||
|
||||
@@ -73,17 +75,13 @@ class Usecase:
|
||||
):
|
||||
del self.settings["attributes"]["ScheduleFinish"]
|
||||
|
||||
duration_type = self.settings["attributes"].get(
|
||||
"DurationType", self.settings["task_time"].DurationType
|
||||
)
|
||||
duration_type = self.settings["attributes"].get("DurationType", self.settings["task_time"].DurationType)
|
||||
finish = self.settings["attributes"].get("ScheduleFinish", None)
|
||||
if finish:
|
||||
if isinstance(finish, str):
|
||||
finish = datetime.datetime.fromisoformat(finish)
|
||||
self.settings["attributes"]["ScheduleFinish"] = datetime.datetime.combine(
|
||||
ifcopenshell.util.sequence.get_soonest_working_day(
|
||||
finish, duration_type, self.calendar
|
||||
),
|
||||
ifcopenshell.util.sequence.get_soonest_working_day(finish, duration_type, self.calendar),
|
||||
datetime.time(17),
|
||||
)
|
||||
start = self.settings["attributes"].get("ScheduleStart", None)
|
||||
@@ -91,9 +89,7 @@ class Usecase:
|
||||
if isinstance(start, str):
|
||||
start = datetime.datetime.fromisoformat(start)
|
||||
self.settings["attributes"]["ScheduleStart"] = datetime.datetime.combine(
|
||||
ifcopenshell.util.sequence.get_soonest_working_day(
|
||||
start, duration_type, self.calendar
|
||||
),
|
||||
ifcopenshell.util.sequence.get_soonest_working_day(start, duration_type, self.calendar),
|
||||
datetime.time(9),
|
||||
)
|
||||
|
||||
@@ -101,11 +97,7 @@ class Usecase:
|
||||
if value is not None:
|
||||
if "Start" in name or "Finish" in name or name == "StatusTime":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
elif (
|
||||
name == "ScheduleDuration"
|
||||
or name == "ActualDuration"
|
||||
or name == "RemainingTime"
|
||||
):
|
||||
elif name == "ScheduleDuration" or name == "ActualDuration" or name == "RemainingTime":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(self.settings["task_time"], name, value)
|
||||
|
||||
@@ -115,15 +107,9 @@ class Usecase:
|
||||
and self.settings["task_time"].ScheduleStart
|
||||
):
|
||||
self.calculate_finish()
|
||||
elif (
|
||||
self.settings["attributes"].get("ScheduleStart", None)
|
||||
and self.settings["task_time"].ScheduleDuration
|
||||
):
|
||||
elif self.settings["attributes"].get("ScheduleStart", None) and self.settings["task_time"].ScheduleDuration:
|
||||
self.calculate_finish()
|
||||
elif (
|
||||
self.settings["attributes"].get("ScheduleFinish", None)
|
||||
and self.settings["task_time"].ScheduleStart
|
||||
):
|
||||
elif self.settings["attributes"].get("ScheduleFinish", None) and self.settings["task_time"].ScheduleStart:
|
||||
self.calculate_duration()
|
||||
|
||||
if self.settings["task_time"].ScheduleDuration and (
|
||||
@@ -137,57 +123,36 @@ class Usecase:
|
||||
|
||||
def calculate_finish(self):
|
||||
finish = ifcopenshell.util.sequence.get_start_or_finish_date(
|
||||
ifcopenshell.util.date.ifc2datetime(
|
||||
self.settings["task_time"].ScheduleStart
|
||||
),
|
||||
ifcopenshell.util.date.ifc2datetime(
|
||||
self.settings["task_time"].ScheduleDuration
|
||||
),
|
||||
ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleStart),
|
||||
ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleDuration),
|
||||
self.settings["task_time"].DurationType,
|
||||
self.calendar,
|
||||
date_type="FINISH",
|
||||
)
|
||||
self.settings["task_time"].ScheduleFinish = ifcopenshell.util.date.datetime2ifc(
|
||||
finish, "IfcDateTime"
|
||||
)
|
||||
self.settings["task_time"].ScheduleFinish = ifcopenshell.util.date.datetime2ifc(finish, "IfcDateTime")
|
||||
|
||||
def calculate_duration(self):
|
||||
start = ifcopenshell.util.date.ifc2datetime(
|
||||
self.settings["task_time"].ScheduleStart
|
||||
)
|
||||
finish = ifcopenshell.util.date.ifc2datetime(
|
||||
self.settings["task_time"].ScheduleFinish
|
||||
)
|
||||
start = ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleStart)
|
||||
finish = ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleFinish)
|
||||
current_date = datetime.date(start.year, start.month, start.day)
|
||||
finish_date = datetime.date(finish.year, finish.month, finish.day)
|
||||
duration = datetime.timedelta(days=1)
|
||||
while current_date < finish_date:
|
||||
if (
|
||||
self.settings["task_time"].DurationType == "ELAPSEDTIME"
|
||||
or not self.calendar
|
||||
):
|
||||
if self.settings["task_time"].DurationType == "ELAPSEDTIME" or not self.calendar:
|
||||
duration += datetime.timedelta(days=1)
|
||||
elif ifcopenshell.util.sequence.is_working_day(current_date, self.calendar):
|
||||
duration += datetime.timedelta(days=1)
|
||||
current_date += datetime.timedelta(days=1)
|
||||
self.settings[
|
||||
"task_time"
|
||||
].ScheduleDuration = ifcopenshell.util.date.datetime2ifc(
|
||||
duration, "IfcDuration"
|
||||
)
|
||||
self.settings["task_time"].ScheduleDuration = ifcopenshell.util.date.datetime2ifc(duration, "IfcDuration")
|
||||
|
||||
def get_task(self) -> ifcopenshell.entity_instance:
|
||||
return next(
|
||||
e
|
||||
for e in self.file.get_inverse(self.settings["task_time"])
|
||||
if e.is_a("IfcTask")
|
||||
)
|
||||
return next(e for e in self.file.get_inverse(self.settings["task_time"]) if e.is_a("IfcTask"))
|
||||
|
||||
def handle_resource_calculation(self):
|
||||
resources = ifcopenshell.util.sequence.get_task_resources(self.task, is_deep=False)
|
||||
for resource in resources:
|
||||
if ifcopenshell.util.constraint.is_attribute_locked(resource, "Usage.ScheduleWork"):
|
||||
ifcopenshell.api.run("resource.calculate_resource_usage", self.file, resource=resource)
|
||||
#TODO: If the duration changes, this implies the productivity rate must change to accomModate the new Schedule Work to be calculated.
|
||||
# TODO: If the duration changes, this implies the productivity rate must change to accomModate the new Schedule Work to be calculated.
|
||||
# elif ifcopenshell.util.constraint.is_attribute_locked(resource, "Usage.ScheduleUsage"):
|
||||
# ifcopenshell.api.run("resource.calculate_resource_work", self.file, resource=resource)
|
||||
|
||||
@@ -17,34 +17,31 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_calendar=None, attributes=None):
|
||||
"""Edits the attributes of an IfcWorkCalendar
|
||||
def edit_work_calendar(file, work_calendar=None, attributes=None) -> None:
|
||||
"""Edits the attributes of an IfcWorkCalendar
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcWorkCalendar, consult the IFC documentation.
|
||||
For more information about the attributes and data types of an
|
||||
IfcWorkCalendar, consult the IFC documentation.
|
||||
|
||||
:param work_calendar: The IfcWorkCalendar entity you want to edit
|
||||
:type work_calendar: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param work_calendar: The IfcWorkCalendar entity you want to edit
|
||||
:type work_calendar: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
|
||||
|
||||
# Let's give it a description
|
||||
ifcopenshell.api.run("sequence.edit_work_calendar", model,
|
||||
work_calendar=calendar, attributes={"Description": "Monday to Friday 8 hour days"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_calendar": work_calendar, "attributes": attributes or {}}
|
||||
# Let's give it a description
|
||||
ifcopenshell.api.run("sequence.edit_work_calendar", model,
|
||||
work_calendar=calendar, attributes={"Description": "Monday to Friday 8 hour days"})
|
||||
"""
|
||||
settings = {"work_calendar": work_calendar, "attributes": attributes or {}}
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["work_calendar"], name, value)
|
||||
for name, value in settings["attributes"].items():
|
||||
setattr(settings["work_calendar"], name, value)
|
||||
|
||||
@@ -19,39 +19,36 @@
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_plan=None, attributes=None):
|
||||
"""Edits the attributes of an IfcWorkPlan
|
||||
def edit_work_plan(file, work_plan=None, attributes=None) -> None:
|
||||
"""Edits the attributes of an IfcWorkPlan
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcWorkPlan, consult the IFC documentation.
|
||||
For more information about the attributes and data types of an
|
||||
IfcWorkPlan, consult the IFC documentation.
|
||||
|
||||
:param work_plan: The IfcWorkPlan entity you want to edit
|
||||
:type work_plan: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param work_plan: The IfcWorkPlan entity you want to edit
|
||||
:type work_plan: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
|
||||
# Let's give it a description
|
||||
ifcopenshell.api.run("sequence.edit_work_plan", model,
|
||||
work_plan=work_plan, attributes={"Description": "Construction of phase 1"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_plan": work_plan, "attributes": attributes or {}}
|
||||
# Let's give it a description
|
||||
ifcopenshell.api.run("sequence.edit_work_plan", model,
|
||||
work_plan=work_plan, attributes={"Description": "Construction of phase 1"})
|
||||
"""
|
||||
settings = {"work_plan": work_plan, "attributes": attributes or {}}
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
if value:
|
||||
if "Date" in name or "Time" in name:
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
elif name == "Duration" or name == "TotalFloat":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(self.settings["work_plan"], name, value)
|
||||
for name, value in settings["attributes"].items():
|
||||
if value:
|
||||
if "Date" in name or "Time" in name:
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
elif name == "Duration" or name == "TotalFloat":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(settings["work_plan"], name, value)
|
||||
|
||||
@@ -19,43 +19,40 @@
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_schedule=None, attributes=None):
|
||||
"""Edits the attributes of an IfcWorkSchedule
|
||||
def edit_work_schedule(file, work_schedule=None, attributes=None) -> None:
|
||||
"""Edits the attributes of an IfcWorkSchedule
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcWorkSchedule, consult the IFC documentation.
|
||||
For more information about the attributes and data types of an
|
||||
IfcWorkSchedule, consult the IFC documentation.
|
||||
|
||||
:param work_schedule: The IfcWorkSchedule entity you want to edit
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param work_schedule: The IfcWorkSchedule entity you want to edit
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
|
||||
# Let's imagine this is one of our schedules in our work plan.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
|
||||
name="Construction Schedule A", work_plan=work_plan)
|
||||
# Let's imagine this is one of our schedules in our work plan.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
|
||||
name="Construction Schedule A", work_plan=work_plan)
|
||||
|
||||
# Let's give it a description
|
||||
ifcopenshell.api.run("sequence.edit_work_schedule", model,
|
||||
work_schedule=work_schedule, attributes={"Description": "3 crane design option"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_schedule": work_schedule, "attributes": attributes or {}}
|
||||
# Let's give it a description
|
||||
ifcopenshell.api.run("sequence.edit_work_schedule", model,
|
||||
work_schedule=work_schedule, attributes={"Description": "3 crane design option"})
|
||||
"""
|
||||
settings = {"work_schedule": work_schedule, "attributes": attributes or {}}
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
if value:
|
||||
if "Date" in name or "Time" in name:
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
elif name == "Duration" or name == "TotalFloat":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(self.settings["work_schedule"], name, value)
|
||||
for name, value in settings["attributes"].items():
|
||||
if value:
|
||||
if "Date" in name or "Time" in name:
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
elif name == "Duration" or name == "TotalFloat":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(settings["work_schedule"], name, value)
|
||||
|
||||
@@ -20,54 +20,50 @@ import ifcopenshell.util.date
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(
|
||||
self,
|
||||
file: ifcopenshell.file,
|
||||
work_time: ifcopenshell.entity_instance,
|
||||
attributes: Optional[dict[str, Any]] = None,
|
||||
):
|
||||
"""Edits the attributes of an IfcWorkTime
|
||||
def edit_work_time(
|
||||
file: ifcopenshell.file,
|
||||
work_time: ifcopenshell.entity_instance,
|
||||
attributes: Optional[dict[str, Any]] = None,
|
||||
) -> None:
|
||||
"""Edits the attributes of an IfcWorkTime
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcWorkTime, consult the IFC documentation.
|
||||
For more information about the attributes and data types of an
|
||||
IfcWorkTime, consult the IFC documentation.
|
||||
|
||||
:param work_time: The IfcWorkTime entity you want to edit
|
||||
:type work_time: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param work_time: The IfcWorkTime entity you want to edit
|
||||
:type work_time: ifcopenshell.entity_instance
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:type attributes: dict, optional
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# If we don't specify any recurring time periods in our work time,
|
||||
# we need to specify a start and end date of the work time. It
|
||||
# starts at 0:00 on the start date and 24:00 at the end date.
|
||||
ifcopenshell.api.run("sequence.edit_work_time", model,
|
||||
work_time=work_time, attributes={"StartDate": "2000-01-01", "FinishDate": "2000-01-02"})
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_time": work_time, "attributes": attributes or {}}
|
||||
# If we don't specify any recurring time periods in our work time,
|
||||
# we need to specify a start and end date of the work time. It
|
||||
# starts at 0:00 on the start date and 24:00 at the end date.
|
||||
ifcopenshell.api.run("sequence.edit_work_time", model,
|
||||
work_time=work_time, attributes={"StartDate": "2000-01-01", "FinishDate": "2000-01-02"})
|
||||
"""
|
||||
settings = {"work_time": work_time, "attributes": attributes or {}}
|
||||
|
||||
def execute(self) -> None:
|
||||
for name, value in self.settings["attributes"].items():
|
||||
if name in ("Start", "StartDate"):
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
|
||||
# 4 IfcWorktime Start
|
||||
self.settings["work_time"][4] = value
|
||||
elif name in ("Finish", "FinishDate"):
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
|
||||
# 5 IfcWorktime Finish
|
||||
self.settings["work_time"][5] = value
|
||||
else:
|
||||
setattr(self.settings["work_time"], name, value)
|
||||
for name, value in settings["attributes"].items():
|
||||
if name in ("Start", "StartDate"):
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
|
||||
# 4 IfcWorktime Start
|
||||
settings["work_time"][4] = value
|
||||
elif name in ("Finish", "FinishDate"):
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
|
||||
# 5 IfcWorktime Finish
|
||||
settings["work_time"][5] = value
|
||||
else:
|
||||
setattr(settings["work_time"], name, value)
|
||||
|
||||
@@ -19,61 +19,58 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, relating_product=None, related_object=None):
|
||||
"""Gets the related products being output by a task
|
||||
def get_related_products(file, relating_product=None, related_object=None) -> None:
|
||||
"""Gets the related products being output by a task
|
||||
|
||||
This API function will be removed in the future and migrated to a
|
||||
utility module.
|
||||
This API function will be removed in the future and migrated to a
|
||||
utility module.
|
||||
|
||||
:param relating_product: One of the products already output by the task.
|
||||
:type relating_product: ifcopenshell.entity_instance
|
||||
:param related_object: The IfcTask that you want to get all the related
|
||||
products for.
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: A set of IfcProducts output by the IfcTask.
|
||||
:rtype: set[ifcopenshell.entity_instance]
|
||||
:param relating_product: One of the products already output by the task.
|
||||
:type relating_product: ifcopenshell.entity_instance
|
||||
:param related_object: The IfcTask that you want to get all the related
|
||||
products for.
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: A set of IfcProducts output by the IfcTask.
|
||||
:rtype: set[ifcopenshell.entity_instance]
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
|
||||
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
|
||||
# Let's construct that wall!
|
||||
ifcopenshell.api.run("sequence.assign_product", relating_product=wall, related_object=task)
|
||||
# Let's construct that wall!
|
||||
ifcopenshell.api.run("sequence.assign_product", relating_product=wall, related_object=task)
|
||||
|
||||
# This will give us a set with that wall in it.
|
||||
products = ifcopenshell.api.run("sequence.get_related_products", model, related_object=task)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"relating_product": relating_product,
|
||||
"related_object": related_object,
|
||||
}
|
||||
# This will give us a set with that wall in it.
|
||||
products = ifcopenshell.api.run("sequence.get_related_products", model, related_object=task)
|
||||
"""
|
||||
settings = {
|
||||
"relating_product": relating_product,
|
||||
"related_object": related_object,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
products = set()
|
||||
related_object = None
|
||||
if self.settings["related_object"]:
|
||||
related_object = self.settings["related_object"]
|
||||
elif self.settings["relating_product"]:
|
||||
for reference in self.settings["relating_product"].ReferencedBy:
|
||||
if reference.is_a("IfcRelAssignsToProduct"):
|
||||
related_object = reference.RelatedObjects[0]
|
||||
if related_object:
|
||||
assignments = self.settings["related_object"].HasAssignments
|
||||
for assignment in assignments:
|
||||
if assignment.is_a("IfcRelAssignsToProduct"):
|
||||
products.add(assignment.RelatingProduct.id())
|
||||
return products
|
||||
products = set()
|
||||
related_object = None
|
||||
if settings["related_object"]:
|
||||
related_object = settings["related_object"]
|
||||
elif settings["relating_product"]:
|
||||
for reference in settings["relating_product"].ReferencedBy:
|
||||
if reference.is_a("IfcRelAssignsToProduct"):
|
||||
related_object = reference.RelatedObjects[0]
|
||||
if related_object:
|
||||
assignments = settings["related_object"].HasAssignments
|
||||
for assignment in assignments:
|
||||
if assignment.is_a("IfcRelAssignsToProduct"):
|
||||
products.add(assignment.RelatingProduct.id())
|
||||
return products
|
||||
|
||||
@@ -23,35 +23,38 @@ import ifcopenshell.util.date
|
||||
import ifcopenshell.util.sequence
|
||||
|
||||
|
||||
def recalculate_schedule(file, work_schedule=None) -> None:
|
||||
"""Calculate the critical path and floats for a work schedule
|
||||
|
||||
This implements critical path analysis, using the forward pass and
|
||||
backward pass method. When run, any tasks that have no float will be
|
||||
marked as critical, and both the total and free floats will be
|
||||
populated for all task times.
|
||||
|
||||
Cyclical relationships are detected and will result in a recursion
|
||||
error.
|
||||
|
||||
:param work_schedule: The IfcWorkSchedule to perform the calculation on.
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# See the example for ifcopenshell.api.sequence.cascade_schedule for
|
||||
# details of how to set up a basic set of tasks and calculate the
|
||||
# critical path. Typically cascade_schedule is run prior to ensure
|
||||
# that dates are correct.
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"work_schedule": work_schedule}
|
||||
return usecase.execute()
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_schedule=None):
|
||||
"""Calculate the critical path and floats for a work schedule
|
||||
|
||||
This implements critical path analysis, using the forward pass and
|
||||
backward pass method. When run, any tasks that have no float will be
|
||||
marked as critical, and both the total and free floats will be
|
||||
populated for all task times.
|
||||
|
||||
Cyclical relationships are detected and will result in a recursion
|
||||
error.
|
||||
|
||||
:param work_schedule: The IfcWorkSchedule to perform the calculation on.
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# See the example for ifcopenshell.api.sequence.cascade_schedule for
|
||||
# details of how to set up a basic set of tasks and calculate the
|
||||
# critical path. Typically cascade_schedule is run prior to ensure
|
||||
# that dates are correct.
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_schedule": work_schedule}
|
||||
|
||||
def execute(self):
|
||||
# The method implemented is the same as shown here:
|
||||
# https://www.youtube.com/watch?v=qTErIV6OqLg
|
||||
@@ -84,9 +87,7 @@ class Usecase:
|
||||
break # We have an infinite loop due to a cyclic graph
|
||||
|
||||
if is_cyclic:
|
||||
raise RecursionError(
|
||||
"Task graph is cyclic and so critical path method cannot be performed."
|
||||
)
|
||||
raise RecursionError("Task graph is cyclic and so critical path method cannot be performed.")
|
||||
return
|
||||
|
||||
self.pending_nodes = set(self.g.nodes)
|
||||
@@ -112,9 +113,7 @@ class Usecase:
|
||||
self.g = nx.DiGraph()
|
||||
self.edges = []
|
||||
self.g.add_node("start", duration=0, duration_type="ELAPSEDTIME", calendar=None)
|
||||
self.g.add_node(
|
||||
"finish", duration=0, duration_type="ELAPSEDTIME", calendar=None
|
||||
)
|
||||
self.g.add_node("finish", duration=0, duration_type="ELAPSEDTIME", calendar=None)
|
||||
for rel in self.settings["work_schedule"].Controls:
|
||||
for related_object in rel.RelatedObjects:
|
||||
if not related_object.is_a("IfcTask"):
|
||||
@@ -129,9 +128,7 @@ class Usecase:
|
||||
return
|
||||
|
||||
if task.TaskTime and task.TaskTime.ScheduleDuration:
|
||||
duration = ifcopenshell.util.date.ifc2datetime(
|
||||
task.TaskTime.ScheduleDuration
|
||||
).days
|
||||
duration = ifcopenshell.util.date.ifc2datetime(task.TaskTime.ScheduleDuration).days
|
||||
duration_type = task.TaskTime.DurationType
|
||||
else:
|
||||
duration = 0
|
||||
@@ -150,11 +147,11 @@ class Usecase:
|
||||
rel.RelatingProcess.id(),
|
||||
task.id(),
|
||||
{
|
||||
"lag_time": 0
|
||||
if not rel.TimeLag
|
||||
else ifcopenshell.util.date.ifc2datetime(
|
||||
rel.TimeLag.LagValue.wrappedValue
|
||||
).days,
|
||||
"lag_time": (
|
||||
0
|
||||
if not rel.TimeLag
|
||||
else ifcopenshell.util.date.ifc2datetime(rel.TimeLag.LagValue.wrappedValue).days
|
||||
),
|
||||
"type": self.sequence_type_map[rel.SequenceType],
|
||||
},
|
||||
)
|
||||
@@ -162,16 +159,20 @@ class Usecase:
|
||||
]
|
||||
)
|
||||
|
||||
predecessor_types = [rel.SequenceType for rel in ifcopenshell.util.sequence.get_sequence_assignment(task, "predecessor")]
|
||||
successor_types = [rel.SequenceType for rel in ifcopenshell.util.sequence.get_sequence_assignment(task, "successor")]
|
||||
predecessor_types = [
|
||||
rel.SequenceType for rel in ifcopenshell.util.sequence.get_sequence_assignment(task, "predecessor")
|
||||
]
|
||||
successor_types = [
|
||||
rel.SequenceType for rel in ifcopenshell.util.sequence.get_sequence_assignment(task, "successor")
|
||||
]
|
||||
|
||||
if not predecessor_types:
|
||||
self.edges.append(("start", task.id(), {"lag_time": 0, "type": "FS"}))
|
||||
if task.TaskTime and task.TaskTime.ScheduleStart:
|
||||
self.start_dates.append(
|
||||
ifcopenshell.util.date.ifc2datetime(task.TaskTime.ScheduleStart)
|
||||
)
|
||||
self.g.nodes[task.id()]["early_start"] = ifcopenshell.util.date.ifc2datetime(task.TaskTime.ScheduleStart) # we assume this task is constrained to start on this date
|
||||
self.start_dates.append(ifcopenshell.util.date.ifc2datetime(task.TaskTime.ScheduleStart))
|
||||
self.g.nodes[task.id()]["early_start"] = ifcopenshell.util.date.ifc2datetime(
|
||||
task.TaskTime.ScheduleStart
|
||||
) # we assume this task is constrained to start on this date
|
||||
if not successor_types:
|
||||
self.edges.append((task.id(), "finish", {"lag_time": 0, "type": "FF"}))
|
||||
|
||||
@@ -188,25 +189,13 @@ class Usecase:
|
||||
self.file,
|
||||
task_time=task.TaskTime,
|
||||
attributes={
|
||||
"FreeFloat": ifcopenshell.util.date.datetime2ifc(
|
||||
data["free_float"], "IfcDuration"
|
||||
),
|
||||
"TotalFloat": ifcopenshell.util.date.datetime2ifc(
|
||||
data["total_float"], "IfcDuration"
|
||||
),
|
||||
"FreeFloat": ifcopenshell.util.date.datetime2ifc(data["free_float"], "IfcDuration"),
|
||||
"TotalFloat": ifcopenshell.util.date.datetime2ifc(data["total_float"], "IfcDuration"),
|
||||
"IsCritical": data["total_float"].days == 0,
|
||||
"EarlyStart": ifcopenshell.util.date.datetime2ifc(
|
||||
data["early_start"], "IfcDateTime"
|
||||
),
|
||||
"EarlyFinish": ifcopenshell.util.date.datetime2ifc(
|
||||
data["early_finish"], "IfcDateTime"
|
||||
),
|
||||
"LateStart": ifcopenshell.util.date.datetime2ifc(
|
||||
data["late_start"], "IfcDateTime"
|
||||
),
|
||||
"LateFinish": ifcopenshell.util.date.datetime2ifc(
|
||||
data["late_finish"], "IfcDateTime"
|
||||
),
|
||||
"EarlyStart": ifcopenshell.util.date.datetime2ifc(data["early_start"], "IfcDateTime"),
|
||||
"EarlyFinish": ifcopenshell.util.date.datetime2ifc(data["early_finish"], "IfcDateTime"),
|
||||
"LateStart": ifcopenshell.util.date.datetime2ifc(data["late_start"], "IfcDateTime"),
|
||||
"LateFinish": ifcopenshell.util.date.datetime2ifc(data["late_finish"], "IfcDateTime"),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -246,11 +235,7 @@ class Usecase:
|
||||
if edge["lag_time"]:
|
||||
days += edge["lag_time"]
|
||||
if days:
|
||||
starts.append(
|
||||
datetime.datetime.combine(
|
||||
self.offset_date(finish, days, data), datetime.time(9)
|
||||
)
|
||||
)
|
||||
starts.append(datetime.datetime.combine(self.offset_date(finish, days, data), datetime.time(9)))
|
||||
starts.append(
|
||||
datetime.datetime.combine(
|
||||
self.offset_date(finish, days, predecessor_data),
|
||||
@@ -265,9 +250,7 @@ class Usecase:
|
||||
return
|
||||
if edge["lag_time"]:
|
||||
starts.append(self.offset_date(start, edge["lag_time"], data))
|
||||
starts.append(
|
||||
self.offset_date(start, edge["lag_time"], predecessor_data)
|
||||
)
|
||||
starts.append(self.offset_date(start, edge["lag_time"], predecessor_data))
|
||||
else:
|
||||
starts.append(start)
|
||||
elif edge["type"] == "FF":
|
||||
@@ -275,12 +258,8 @@ class Usecase:
|
||||
if finish is None:
|
||||
return
|
||||
if edge["lag_time"]:
|
||||
finishes.append(
|
||||
self.offset_date(finish, edge["lag_time"], data)
|
||||
)
|
||||
finishes.append(
|
||||
self.offset_date(finish, edge["lag_time"], predecessor_data)
|
||||
)
|
||||
finishes.append(self.offset_date(finish, edge["lag_time"], data))
|
||||
finishes.append(self.offset_date(finish, edge["lag_time"], predecessor_data))
|
||||
else:
|
||||
finishes.append(finish)
|
||||
elif edge["type"] == "SF":
|
||||
@@ -292,9 +271,7 @@ class Usecase:
|
||||
days += edge["lag_time"]
|
||||
if days or edge["lag_time"]:
|
||||
finishes.append(
|
||||
datetime.datetime.combine(
|
||||
self.offset_date(start, days, data), datetime.time(17)
|
||||
)
|
||||
datetime.datetime.combine(self.offset_date(start, days, data), datetime.time(17))
|
||||
)
|
||||
finishes.append(
|
||||
datetime.datetime.combine(
|
||||
@@ -317,9 +294,7 @@ class Usecase:
|
||||
if potential_finish > data["early_finish"]:
|
||||
data["early_finish"] = potential_finish
|
||||
else:
|
||||
data[
|
||||
"early_start"
|
||||
] = ifcopenshell.util.sequence.get_start_or_finish_date(
|
||||
data["early_start"] = ifcopenshell.util.sequence.get_start_or_finish_date(
|
||||
data["early_finish"],
|
||||
datetime.timedelta(days=data["duration"]),
|
||||
data["duration_type"],
|
||||
@@ -375,9 +350,7 @@ class Usecase:
|
||||
days += edge["lag_time"]
|
||||
if days or edge["lag_time"]:
|
||||
finishes.append(
|
||||
datetime.datetime.combine(
|
||||
self.offset_date(start, -days, data), datetime.time(17)
|
||||
)
|
||||
datetime.datetime.combine(self.offset_date(start, -days, data), datetime.time(17))
|
||||
)
|
||||
finishes.append(
|
||||
datetime.datetime.combine(
|
||||
@@ -402,9 +375,7 @@ class Usecase:
|
||||
return
|
||||
if edge["lag_time"]:
|
||||
starts.append(self.offset_date(start, -edge["lag_time"], data))
|
||||
starts.append(
|
||||
self.offset_date(start, -edge["lag_time"], successor_data)
|
||||
)
|
||||
starts.append(self.offset_date(start, -edge["lag_time"], successor_data))
|
||||
else:
|
||||
starts.append(start)
|
||||
free_floats.append(
|
||||
@@ -421,12 +392,8 @@ class Usecase:
|
||||
if finish is None:
|
||||
return
|
||||
if edge["lag_time"]:
|
||||
finishes.append(
|
||||
self.offset_date(finish, -edge["lag_time"], data)
|
||||
)
|
||||
finishes.append(
|
||||
self.offset_date(finish, -edge["lag_time"], successor_data)
|
||||
)
|
||||
finishes.append(self.offset_date(finish, -edge["lag_time"], data))
|
||||
finishes.append(self.offset_date(finish, -edge["lag_time"], successor_data))
|
||||
else:
|
||||
finishes.append(finish)
|
||||
free_floats.append(
|
||||
@@ -447,9 +414,7 @@ class Usecase:
|
||||
days += edge["lag_time"]
|
||||
if days:
|
||||
starts.append(
|
||||
datetime.datetime.combine(
|
||||
self.offset_date(finish, -days, data), datetime.time(9)
|
||||
)
|
||||
datetime.datetime.combine(self.offset_date(finish, -days, data), datetime.time(9))
|
||||
)
|
||||
starts.append(
|
||||
datetime.datetime.combine(
|
||||
@@ -471,13 +436,8 @@ class Usecase:
|
||||
if starts and finishes:
|
||||
data["late_start"] = min(starts)
|
||||
data["late_finish"] = min(finishes)
|
||||
if (
|
||||
self.offset_date(data["late_start"], data["duration"], data)
|
||||
< data["late_finish"]
|
||||
):
|
||||
data[
|
||||
"late_finish"
|
||||
] = ifcopenshell.util.sequence.get_start_or_finish_date(
|
||||
if self.offset_date(data["late_start"], data["duration"], data) < data["late_finish"]:
|
||||
data["late_finish"] = ifcopenshell.util.sequence.get_start_or_finish_date(
|
||||
data["late_start"],
|
||||
datetime.timedelta(days=data["duration"]),
|
||||
data["duration_type"],
|
||||
@@ -485,9 +445,7 @@ class Usecase:
|
||||
date_type="FINISH",
|
||||
)
|
||||
else:
|
||||
data[
|
||||
"late_start"
|
||||
] = ifcopenshell.util.sequence.get_start_or_finish_date(
|
||||
data["late_start"] = ifcopenshell.util.sequence.get_start_or_finish_date(
|
||||
data["late_finish"],
|
||||
datetime.timedelta(days=data["duration"]),
|
||||
data["duration_type"],
|
||||
@@ -528,9 +486,7 @@ class Usecase:
|
||||
data["total_float"] = data["late_finish"] - data["early_finish"]
|
||||
# If the float is within the span of a single day, it may show as a 8 hours
|
||||
if data["total_float"].seconds == 60 * 60 * 8:
|
||||
data["total_float"] = datetime.timedelta(
|
||||
days=data["total_float"].days + 1
|
||||
)
|
||||
data["total_float"] = datetime.timedelta(days=data["total_float"].days + 1)
|
||||
|
||||
data["free_float"] = min(free_floats) if free_floats else None
|
||||
# If the float is within the span of a single day, it may show as a 8 hours
|
||||
|
||||
@@ -21,124 +21,121 @@ import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, task=None):
|
||||
"""Removes a task
|
||||
def remove_task(file, task=None) -> None:
|
||||
"""Removes a task
|
||||
|
||||
All subtasks are also removed recursively. Any relationships such as
|
||||
sequences or controls are also removed.
|
||||
All subtasks are also removed recursively. Any relationships such as
|
||||
sequences or controls are also removed.
|
||||
|
||||
:param task: The IfcTask to remove.
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param task: The IfcTask to remove.
|
||||
:type task: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Add a root task to represent the design milestones, and major
|
||||
# project phases.
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Milestones", identification="A")
|
||||
design = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Design", identification="B")
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
# Add a root task to represent the design milestones, and major
|
||||
# project phases.
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Milestones", identification="A")
|
||||
design = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Design", identification="B")
|
||||
ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Ah, let's delete the design section, who needs it anyway we'll
|
||||
# just fix it on site.
|
||||
ifcopenshell.api.run("sequence.remove_task", model, task=design)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"task": task}
|
||||
# Ah, let's delete the design section, who needs it anyway we'll
|
||||
# just fix it on site.
|
||||
ifcopenshell.api.run("sequence.remove_task", model, task=design)
|
||||
"""
|
||||
settings = {"task": task}
|
||||
|
||||
def execute(self):
|
||||
# TODO: do a deep purge
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
self.file,
|
||||
definitions=[self.settings["task"]],
|
||||
relating_context=self.file.by_type("IfcContext")[0],
|
||||
)
|
||||
if self.settings["task"].TaskTime:
|
||||
self.file.remove(self.settings["task"].TaskTime)
|
||||
for inverse in self.file.get_inverse(self.settings["task"]):
|
||||
if inverse.is_a("IfcRelSequence"):
|
||||
# TODO: do a deep purge
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
file,
|
||||
definitions=[settings["task"]],
|
||||
relating_context=file.by_type("IfcContext")[0],
|
||||
)
|
||||
if settings["task"].TaskTime:
|
||||
file.remove(settings["task"].TaskTime)
|
||||
for inverse in file.get_inverse(settings["task"]):
|
||||
if inverse.is_a("IfcRelSequence"):
|
||||
history = inverse.OwnerHistory
|
||||
file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
elif inverse.is_a("IfcRelNests"):
|
||||
if inverse.RelatingObject == settings["task"]:
|
||||
for related_object in inverse.RelatedObjects:
|
||||
ifcopenshell.api.run("sequence.remove_task", file, task=related_object)
|
||||
elif not inverse.RelatedObjects:
|
||||
history = inverse.OwnerHistory
|
||||
self.file.remove(inverse)
|
||||
file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
elif inverse.is_a("IfcRelNests"):
|
||||
if inverse.RelatingObject == self.settings["task"]:
|
||||
for related_object in inverse.RelatedObjects:
|
||||
ifcopenshell.api.run("sequence.remove_task", self.file, task=related_object)
|
||||
elif not inverse.RelatedObjects:
|
||||
history = inverse.OwnerHistory
|
||||
self.file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
elif self.settings["task"] in inverse.RelatedObjects:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(self.settings["task"])
|
||||
if not related_objects:
|
||||
self.file.remove(inverse)
|
||||
else:
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelAssignsToControl"):
|
||||
if inverse.RelatingControl == self.settings["task"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
self.file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
elif settings["task"] in inverse.RelatedObjects:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(settings["task"])
|
||||
if not related_objects:
|
||||
file.remove(inverse)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(self.settings["task"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelDefinesByProperties"):
|
||||
ifcopenshell.api.run(
|
||||
"pset.remove_pset",
|
||||
self.file,
|
||||
product=self.settings["task"],
|
||||
pset=inverse.RelatingPropertyDefinition,
|
||||
)
|
||||
elif inverse.is_a("IfcRelAssignsToProcess"):
|
||||
if inverse.RelatingProcess == self.settings["task"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
self.file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
elif inverse.is_a("IfcRelAssignsToProduct"):
|
||||
if inverse.RelatingProduct == self.settings["task"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
self.file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(self.settings["task"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelAssignsToObject"):
|
||||
if inverse.RelatingObject == self.settings["task"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
self.file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(self.settings["task"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelAssignsToProcess"):
|
||||
elif inverse.is_a("IfcRelAssignsToControl"):
|
||||
if inverse.RelatingControl == settings["task"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
self.file.remove(inverse)
|
||||
file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(settings["task"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelDefinesByProperties"):
|
||||
ifcopenshell.api.run(
|
||||
"pset.remove_pset",
|
||||
file,
|
||||
product=settings["task"],
|
||||
pset=inverse.RelatingPropertyDefinition,
|
||||
)
|
||||
elif inverse.is_a("IfcRelAssignsToProcess"):
|
||||
if inverse.RelatingProcess == settings["task"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
elif inverse.is_a("IfcRelAssignsToProduct"):
|
||||
if inverse.RelatingProduct == settings["task"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(settings["task"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelAssignsToObject"):
|
||||
if inverse.RelatingObject == settings["task"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(settings["task"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelAssignsToProcess"):
|
||||
history = inverse.OwnerHistory
|
||||
file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
|
||||
history = self.settings["task"].OwnerHistory
|
||||
self.file.remove(self.settings["task"])
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
history = settings["task"].OwnerHistory
|
||||
file.remove(settings["task"])
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
|
||||
@@ -19,45 +19,42 @@
|
||||
import ifcopenshell.api
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, time_period=None):
|
||||
"""Removes a time period
|
||||
def remove_time_period(file, time_period=None) -> None:
|
||||
"""Removes a time period
|
||||
|
||||
:param time_period: The IfcTimePeriod to remove.
|
||||
:type time_period: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param time_period: The IfcTimePeriod to remove.
|
||||
:type time_period: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
|
||||
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
|
||||
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
|
||||
|
||||
# The morning work session, lunch, then the afternoon work session.
|
||||
morning = ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="09:00", end_time="12:00")
|
||||
afternoon = ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="13:00", end_time="17:00")
|
||||
# The morning work session, lunch, then the afternoon work session.
|
||||
morning = ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="09:00", end_time="12:00")
|
||||
afternoon = ifcopenshell.api.run("sequence.add_time_period", model,
|
||||
recurrence_pattern=pattern, start_time="13:00", end_time="17:00")
|
||||
|
||||
# Let's take the afternoon off!
|
||||
ifcopenshell.api.run("sequence.remove_time_period", model, time_period=afternoon)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"time_period": time_period}
|
||||
# Let's take the afternoon off!
|
||||
ifcopenshell.api.run("sequence.remove_time_period", model, time_period=afternoon)
|
||||
"""
|
||||
settings = {"time_period": time_period}
|
||||
|
||||
def execute(self):
|
||||
self.file.remove(self.settings["time_period"])
|
||||
file.remove(settings["time_period"])
|
||||
|
||||
@@ -20,49 +20,46 @@ import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_calendar=None):
|
||||
"""Removes a work calendar
|
||||
def remove_work_calendar(file, work_calendar=None) -> None:
|
||||
"""Removes a work calendar
|
||||
|
||||
All relationships are also removed, such as if a task is set to use that
|
||||
calendar.
|
||||
All relationships are also removed, such as if a task is set to use that
|
||||
calendar.
|
||||
|
||||
:param work_calendar: The IfcWorkCalendar to remove
|
||||
:type work_calendar: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param work_calendar: The IfcWorkCalendar to remove
|
||||
:type work_calendar: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
|
||||
|
||||
# And remove it immediately
|
||||
ifcopenshell.api.run("sequence.remove_work_calendar", model, work_calendar=calendar)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_calendar": work_calendar}
|
||||
# And remove it immediately
|
||||
ifcopenshell.api.run("sequence.remove_work_calendar", model, work_calendar=calendar)
|
||||
"""
|
||||
settings = {"work_calendar": work_calendar}
|
||||
|
||||
def execute(self):
|
||||
# TODO: do a deep purge
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
self.file,
|
||||
definitions=[self.settings["work_calendar"]],
|
||||
relating_context=self.file.by_type("IfcContext")[0],
|
||||
)
|
||||
if self.settings["work_calendar"].Controls:
|
||||
for rel in self.settings["work_calendar"].Controls:
|
||||
for related_object in rel.RelatedObjects:
|
||||
ifcopenshell.api.run(
|
||||
"control.unassign_control",
|
||||
self.file,
|
||||
relating_control=self.settings["work_calendar"],
|
||||
related_object=related_object,
|
||||
)
|
||||
history = self.settings["work_calendar"].OwnerHistory
|
||||
self.file.remove(self.settings["work_calendar"])
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
# TODO: do a deep purge
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
file,
|
||||
definitions=[settings["work_calendar"]],
|
||||
relating_context=file.by_type("IfcContext")[0],
|
||||
)
|
||||
if settings["work_calendar"].Controls:
|
||||
for rel in settings["work_calendar"].Controls:
|
||||
for related_object in rel.RelatedObjects:
|
||||
ifcopenshell.api.run(
|
||||
"control.unassign_control",
|
||||
file,
|
||||
relating_control=settings["work_calendar"],
|
||||
related_object=related_object,
|
||||
)
|
||||
history = settings["work_calendar"].OwnerHistory
|
||||
file.remove(settings["work_calendar"])
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
|
||||
@@ -20,40 +20,37 @@ import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_plan=None):
|
||||
"""Removes a work plan
|
||||
def remove_work_plan(file, work_plan=None) -> None:
|
||||
"""Removes a work plan
|
||||
|
||||
Note that schedules that are grouped under the work plan are not
|
||||
removed.
|
||||
Note that schedules that are grouped under the work plan are not
|
||||
removed.
|
||||
|
||||
:param work_plan: The IfcWorkPlan to remove.
|
||||
:type work_plan: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param work_plan: The IfcWorkPlan to remove.
|
||||
:type work_plan: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
|
||||
# And remove it immediately
|
||||
ifcopenshell.api.run("sequence.remove_work_plan", model, work_plan=work_plan)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_plan": work_plan}
|
||||
# And remove it immediately
|
||||
ifcopenshell.api.run("sequence.remove_work_plan", model, work_plan=work_plan)
|
||||
"""
|
||||
settings = {"work_plan": work_plan}
|
||||
|
||||
def execute(self):
|
||||
# TODO: do a deep purge
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
self.file,
|
||||
definitions=[self.settings["work_plan"]],
|
||||
relating_context=self.file.by_type("IfcContext")[0],
|
||||
)
|
||||
history = self.settings["work_plan"].OwnerHistory
|
||||
self.file.remove(self.settings["work_plan"])
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
# TODO: do a deep purge
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
file,
|
||||
definitions=[settings["work_plan"]],
|
||||
relating_context=file.by_type("IfcContext")[0],
|
||||
)
|
||||
history = settings["work_plan"].OwnerHistory
|
||||
file.remove(settings["work_plan"])
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
|
||||
@@ -21,69 +21,66 @@ import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_schedule=None):
|
||||
"""Removes a work schedule
|
||||
def remove_work_schedule(file, work_schedule=None) -> None:
|
||||
"""Removes a work schedule
|
||||
|
||||
All tasks in the work schedule are also removed recursively.
|
||||
All tasks in the work schedule are also removed recursively.
|
||||
|
||||
:param work_schedule: The IfcWorkSchedule to remove.
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param work_schedule: The IfcWorkSchedule to remove.
|
||||
:type work_schedule: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
# This will hold all our construction schedules
|
||||
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
|
||||
|
||||
# Let's imagine this is one of our schedules in our work plan.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
|
||||
name="Construction Schedule A", work_plan=work_plan)
|
||||
# Let's imagine this is one of our schedules in our work plan.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
|
||||
name="Construction Schedule A", work_plan=work_plan)
|
||||
|
||||
# And remove it immediately
|
||||
ifcopenshell.api.run("sequence.remove_work_schedule", model, work_schedule=schedule)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_schedule": work_schedule}
|
||||
# And remove it immediately
|
||||
ifcopenshell.api.run("sequence.remove_work_schedule", model, work_schedule=schedule)
|
||||
"""
|
||||
settings = {"work_schedule": work_schedule}
|
||||
|
||||
def execute(self):
|
||||
# TODO: do a deep purge
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
self.file,
|
||||
definitions=[self.settings["work_schedule"]],
|
||||
relating_context=self.file.by_type("IfcContext")[0],
|
||||
)
|
||||
if self.settings["work_schedule"].Declares:
|
||||
for rel in self.settings["work_schedule"].Declares:
|
||||
for work_schedule in rel.RelatedObjects:
|
||||
ifcopenshell.api.run(
|
||||
"sequence.remove_work_schedule",
|
||||
self.file,
|
||||
work_schedule=work_schedule,
|
||||
)
|
||||
for inverse in self.file.get_inverse(self.settings["work_schedule"]):
|
||||
if inverse.is_a("IfcRelDefinesByObject"):
|
||||
if inverse.RelatingObject == self.settings["work_schedule"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
self.file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(self.settings["work_schedule"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelAssignsToControl"):
|
||||
[
|
||||
ifcopenshell.api.run("sequence.remove_task", self.file, task=related_object)
|
||||
for related_object in inverse.RelatedObjects
|
||||
if related_object.is_a("IfcTask")
|
||||
]
|
||||
# TODO: do a deep purge
|
||||
ifcopenshell.api.run(
|
||||
"project.unassign_declaration",
|
||||
file,
|
||||
definitions=[settings["work_schedule"]],
|
||||
relating_context=file.by_type("IfcContext")[0],
|
||||
)
|
||||
if settings["work_schedule"].Declares:
|
||||
for rel in settings["work_schedule"].Declares:
|
||||
for work_schedule in rel.RelatedObjects:
|
||||
ifcopenshell.api.run(
|
||||
"sequence.remove_work_schedule",
|
||||
file,
|
||||
work_schedule=work_schedule,
|
||||
)
|
||||
for inverse in file.get_inverse(settings["work_schedule"]):
|
||||
if inverse.is_a("IfcRelDefinesByObject"):
|
||||
if inverse.RelatingObject == settings["work_schedule"] or len(inverse.RelatedObjects) == 1:
|
||||
history = inverse.OwnerHistory
|
||||
file.remove(inverse)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(settings["work_schedule"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelAssignsToControl"):
|
||||
[
|
||||
ifcopenshell.api.run("sequence.remove_task", file, task=related_object)
|
||||
for related_object in inverse.RelatedObjects
|
||||
if related_object.is_a("IfcTask")
|
||||
]
|
||||
|
||||
history = self.settings["work_schedule"].OwnerHistory
|
||||
self.file.remove(self.settings["work_schedule"])
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
history = settings["work_schedule"].OwnerHistory
|
||||
file.remove(settings["work_schedule"])
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
|
||||
@@ -17,31 +17,28 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, work_time=None):
|
||||
"""Removes a work time
|
||||
def remove_work_time(file, work_time=None) -> None:
|
||||
"""Removes a work time
|
||||
|
||||
:param work_time: The IfcWorkTime to remove.
|
||||
:type work_time: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param work_time: The IfcWorkTime to remove.
|
||||
:type work_time: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# And remove it immediately
|
||||
ifcopenshell.api.run("sequence.remove_work_time", model, work_time=work_time)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"work_time": work_time}
|
||||
# And remove it immediately
|
||||
ifcopenshell.api.run("sequence.remove_work_time", model, work_time=work_time)
|
||||
"""
|
||||
settings = {"work_time": work_time}
|
||||
|
||||
def execute(self):
|
||||
self.file.remove(self.settings["work_time"])
|
||||
file.remove(settings["work_time"])
|
||||
|
||||
@@ -19,57 +19,54 @@
|
||||
import ifcopenshell.api
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, rel_sequence=None):
|
||||
"""Removes any lag time in a sequence
|
||||
def unassign_lag_time(file, rel_sequence=None) -> None:
|
||||
"""Removes any lag time in a sequence
|
||||
|
||||
The schedule is cascaded afterwards.
|
||||
The schedule is cascaded afterwards.
|
||||
|
||||
:param rel_sequence: The sequence to remove the lag time from.
|
||||
:type rel_sequence: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param rel_sequence: The sequence to remove the lag time from.
|
||||
:type rel_sequence: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's imagine we're building 2 zones, one after another.
|
||||
zone1 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 1", identification="C.1")
|
||||
zone2 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 2", identification="C.2")
|
||||
# Let's imagine we're building 2 zones, one after another.
|
||||
zone1 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 1", identification="C.1")
|
||||
zone2 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 2", identification="C.2")
|
||||
|
||||
# Zone 1 finishes, then zone 2 starts.
|
||||
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=zone1, related_process=zone2)
|
||||
# Zone 1 finishes, then zone 2 starts.
|
||||
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
|
||||
relating_process=zone1, related_process=zone2)
|
||||
|
||||
# What if you had to wait 1 week before you could start zone 2?
|
||||
ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1W")
|
||||
# What if you had to wait 1 week before you could start zone 2?
|
||||
ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1W")
|
||||
|
||||
# What if you didn't?
|
||||
ifcopenshell.api.run("sequence.unassign_lag_time", model, rel_sequence=sequence)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"rel_sequence": rel_sequence,
|
||||
}
|
||||
# What if you didn't?
|
||||
ifcopenshell.api.run("sequence.unassign_lag_time", model, rel_sequence=sequence)
|
||||
"""
|
||||
settings = {
|
||||
"rel_sequence": rel_sequence,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
if len(self.file.get_inverse(self.settings["rel_sequence"].TimeLag)) == 1:
|
||||
self.file.remove(self.settings["rel_sequence"].TimeLag)
|
||||
else:
|
||||
self.settings["rel_sequence"].TimeLag = None
|
||||
ifcopenshell.api.run(
|
||||
"sequence.cascade_schedule",
|
||||
self.file,
|
||||
task=self.settings["rel_sequence"].RelatedProcess,
|
||||
)
|
||||
if len(file.get_inverse(settings["rel_sequence"].TimeLag)) == 1:
|
||||
file.remove(settings["rel_sequence"].TimeLag)
|
||||
else:
|
||||
settings["rel_sequence"].TimeLag = None
|
||||
ifcopenshell.api.run(
|
||||
"sequence.cascade_schedule",
|
||||
file,
|
||||
task=settings["rel_sequence"].RelatedProcess,
|
||||
)
|
||||
|
||||
@@ -21,59 +21,56 @@ import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, relating_process=None, related_object=None):
|
||||
"""Unassigns a process and object relationship
|
||||
def unassign_process(file, relating_process=None, related_object=None) -> None:
|
||||
"""Unassigns a process and object relationship
|
||||
|
||||
See ifcopenshell.api.sequence.assign_process for details.
|
||||
See ifcopenshell.api.sequence.assign_process for details.
|
||||
|
||||
:param relating_process: The IfcTask in the relationship.
|
||||
:type relating_process: ifcopenshell.entity_instance
|
||||
:param related_object: The related object.
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param relating_process: The IfcTask in the relationship.
|
||||
:type relating_process: ifcopenshell.entity_instance
|
||||
:param related_object: The related object.
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Demolish existing", identification="A", predefined_type="DEMOLITION")
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Demolish existing", identification="A", predefined_type="DEMOLITION")
|
||||
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
|
||||
# Let's demolish that wall!
|
||||
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=wall)
|
||||
# Let's demolish that wall!
|
||||
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=wall)
|
||||
|
||||
# Change our mind.
|
||||
ifcopenshell.api.run("sequence.unassign_process", model, relating_process=task, related_object=wall)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"relating_process": relating_process,
|
||||
"related_object": related_object,
|
||||
}
|
||||
# Change our mind.
|
||||
ifcopenshell.api.run("sequence.unassign_process", model, relating_process=task, related_object=wall)
|
||||
"""
|
||||
settings = {
|
||||
"relating_process": relating_process,
|
||||
"related_object": related_object,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
for rel in self.settings["related_object"].HasAssignments or []:
|
||||
if not rel.is_a("IfcRelAssignsToProcess") or rel.RelatingProcess != self.settings["relating_process"]:
|
||||
continue
|
||||
if len(rel.RelatedObjects) == 1:
|
||||
history = rel.OwnerHistory
|
||||
self.file.remove(rel)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
return
|
||||
related_objects = list(rel.RelatedObjects)
|
||||
related_objects.remove(self.settings["related_object"])
|
||||
rel.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel)
|
||||
return rel
|
||||
for rel in settings["related_object"].HasAssignments or []:
|
||||
if not rel.is_a("IfcRelAssignsToProcess") or rel.RelatingProcess != settings["relating_process"]:
|
||||
continue
|
||||
if len(rel.RelatedObjects) == 1:
|
||||
history = rel.OwnerHistory
|
||||
file.remove(rel)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
return
|
||||
related_objects = list(rel.RelatedObjects)
|
||||
related_objects.remove(settings["related_object"])
|
||||
rel.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run("owner.update_owner_history", file, element=rel)
|
||||
return rel
|
||||
|
||||
@@ -21,59 +21,56 @@ import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, relating_product=None, related_object=None):
|
||||
"""Unassigns a product and object relationship
|
||||
def unassign_product(file, relating_product=None, related_object=None) -> None:
|
||||
"""Unassigns a product and object relationship
|
||||
|
||||
See ifcopenshell.api.sequence.assign_product for details.
|
||||
See ifcopenshell.api.sequence.assign_product for details.
|
||||
|
||||
:param relating_product: The IfcProduct in the relationship.
|
||||
:type relating_product: ifcopenshell.entity_instance
|
||||
:param related_object: The IfcTask in the relationship.
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param relating_product: The IfcProduct in the relationship.
|
||||
:type relating_product: ifcopenshell.entity_instance
|
||||
:param related_object: The IfcTask in the relationship.
|
||||
:type related_object: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
|
||||
# Let's create a construction task. Note that the predefined type is
|
||||
# important to distinguish types of tasks.
|
||||
task = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
|
||||
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
# Let's say we have a wall somewhere.
|
||||
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
|
||||
|
||||
# Let's construct that wall!
|
||||
ifcopenshell.api.run("sequence.assign_product", relating_product=wall, related_object=task)
|
||||
# Let's construct that wall!
|
||||
ifcopenshell.api.run("sequence.assign_product", relating_product=wall, related_object=task)
|
||||
|
||||
# Change our mind.
|
||||
ifcopenshell.api.run("sequence.unassign_product", relating_product=wall, related_object=task)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"relating_product": relating_product,
|
||||
"related_object": related_object,
|
||||
}
|
||||
# Change our mind.
|
||||
ifcopenshell.api.run("sequence.unassign_product", relating_product=wall, related_object=task)
|
||||
"""
|
||||
settings = {
|
||||
"relating_product": relating_product,
|
||||
"related_object": related_object,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
for rel in self.settings["related_object"].HasAssignments or []:
|
||||
if not rel.is_a("IfcRelAssignsToProduct") or rel.RelatingProduct != self.settings["relating_product"]:
|
||||
continue
|
||||
if len(rel.RelatedObjects) == 1:
|
||||
history = rel.OwnerHistory
|
||||
self.file.remove(rel)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
return
|
||||
related_objects = list(rel.RelatedObjects)
|
||||
related_objects.remove(self.settings["related_object"])
|
||||
rel.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel)
|
||||
return rel
|
||||
for rel in settings["related_object"].HasAssignments or []:
|
||||
if not rel.is_a("IfcRelAssignsToProduct") or rel.RelatingProduct != settings["relating_product"]:
|
||||
continue
|
||||
if len(rel.RelatedObjects) == 1:
|
||||
history = rel.OwnerHistory
|
||||
file.remove(rel)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
return
|
||||
related_objects = list(rel.RelatedObjects)
|
||||
related_objects.remove(settings["related_object"])
|
||||
rel.RelatedObjects = related_objects
|
||||
ifcopenshell.api.run("owner.update_owner_history", file, element=rel)
|
||||
return rel
|
||||
|
||||
@@ -17,40 +17,37 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, recurrence_pattern=None):
|
||||
"""Unassigns a recurrence pattern
|
||||
def unassign_recurrence_pattern(file, recurrence_pattern=None) -> None:
|
||||
"""Unassigns a recurrence pattern
|
||||
|
||||
Note that a recurring task time must have a recurrence pattern, so if
|
||||
you remove it, be sure to clean up after yourself.
|
||||
Note that a recurring task time must have a recurrence pattern, so if
|
||||
you remove it, be sure to clean up after your
|
||||
|
||||
:param recurrence_pattern: The IfcRecurrencePattern to remove.
|
||||
:type recurrence_pattern: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param recurrence_pattern: The IfcRecurrencePattern to remove.
|
||||
:type recurrence_pattern: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
# Let's create a new calendar.
|
||||
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
|
||||
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
# Let's start defining the times that we work during the week.
|
||||
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
|
||||
work_calendar=calendar, time_type="WorkingTimes")
|
||||
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
# We create a weekly recurrence
|
||||
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
|
||||
parent=work_time, recurrence_type="WEEKLY")
|
||||
|
||||
# Change our mind, let's just maintain it whenever we feel like it.
|
||||
ifcopenshell.api.run("sequence.unassign_recurrence_pattern", recurrence_pattern=pattern)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {"recurrence_pattern": recurrence_pattern}
|
||||
# Change our mind, let's just maintain it whenever we feel like it.
|
||||
ifcopenshell.api.run("sequence.unassign_recurrence_pattern", recurrence_pattern=pattern)
|
||||
"""
|
||||
settings = {"recurrence_pattern": recurrence_pattern}
|
||||
|
||||
def execute(self):
|
||||
for time_period in self.settings["recurrence_pattern"].TimePeriods or []:
|
||||
self.file.remove(time_period)
|
||||
self.file.remove(self.settings["recurrence_pattern"])
|
||||
for time_period in settings["recurrence_pattern"].TimePeriods or []:
|
||||
file.remove(time_period)
|
||||
file.remove(settings["recurrence_pattern"])
|
||||
|
||||
@@ -21,53 +21,50 @@ import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, relating_process=None, related_process=None):
|
||||
"""Removes a sequence relationship between tasks
|
||||
def unassign_sequence(file, relating_process=None, related_process=None) -> None:
|
||||
"""Removes a sequence relationship between tasks
|
||||
|
||||
:param relating_process: The previous / predecessor task.
|
||||
:type relating_process: ifcopenshell.entity_instance
|
||||
:param related_process: The next / successor task.
|
||||
:type related_process: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
:param relating_process: The previous / predecessor task.
|
||||
:type relating_process: ifcopenshell.entity_instance
|
||||
:param related_process: The next / successor task.
|
||||
:type related_process: ifcopenshell.entity_instance
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
.. code:: python
|
||||
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
# Let's imagine we are creating a construction schedule. All tasks
|
||||
# need to be part of a work schedule.
|
||||
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
|
||||
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
# Let's imagine a root construction task
|
||||
construction = ifcopenshell.api.run("sequence.add_task", model,
|
||||
work_schedule=schedule, name="Construction", identification="C")
|
||||
|
||||
# Let's imagine we're building 2 zones, one after another.
|
||||
zone1 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 1", identification="C.1")
|
||||
zone2 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 2", identification="C.2")
|
||||
# Let's imagine we're building 2 zones, one after another.
|
||||
zone1 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 1", identification="C.1")
|
||||
zone2 = ifcopenshell.api.run("sequence.add_task", model,
|
||||
parent_task=construction, name="Zone 2", identification="C.2")
|
||||
|
||||
# Zone 1 finishes, then zone 2 starts.
|
||||
ifcopenshell.api.run("sequence.assign_sequence", model, relating_process=zone1, related_process=zone2)
|
||||
# Zone 1 finishes, then zone 2 starts.
|
||||
ifcopenshell.api.run("sequence.assign_sequence", model, relating_process=zone1, related_process=zone2)
|
||||
|
||||
# Let's make them unrelated
|
||||
ifcopenshell.api.run("sequence.unassign_sequence", model,
|
||||
relating_process=zone1, related_process=zone2)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"relating_process": relating_process,
|
||||
"related_process": related_process,
|
||||
}
|
||||
# Let's make them unrelated
|
||||
ifcopenshell.api.run("sequence.unassign_sequence", model,
|
||||
relating_process=zone1, related_process=zone2)
|
||||
"""
|
||||
settings = {
|
||||
"relating_process": relating_process,
|
||||
"related_process": related_process,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
for rel in self.settings["related_process"].IsSuccessorFrom or []:
|
||||
if rel.RelatingProcess == self.settings["relating_process"]:
|
||||
history = rel.OwnerHistory
|
||||
self.file.remove(rel)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", self.file, task=self.settings["related_process"])
|
||||
for rel in settings["related_process"].IsSuccessorFrom or []:
|
||||
if rel.RelatingProcess == settings["relating_process"]:
|
||||
history = rel.OwnerHistory
|
||||
file.remove(rel)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
ifcopenshell.api.run("sequence.cascade_schedule", file, task=settings["related_process"])
|
||||
|
||||
Reference in New Issue
Block a user