First Commit
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Manage construction and maintenance resources
|
||||
|
||||
Resources include equipment (cranes, etc), labour, material, and products. They
|
||||
are typically referenced in construction planning, maintenance schedules, or
|
||||
cost items.
|
||||
"""
|
||||
|
||||
from .. import wrap_usecases
|
||||
from .add_resource import add_resource
|
||||
from .add_resource_quantity import add_resource_quantity
|
||||
from .add_resource_time import add_resource_time
|
||||
from .assign_resource import assign_resource
|
||||
from .calculate_resource_usage import calculate_resource_usage
|
||||
from .calculate_resource_work import calculate_resource_work
|
||||
from .edit_resource import edit_resource
|
||||
from .edit_resource_quantity import edit_resource_quantity
|
||||
from .edit_resource_time import edit_resource_time
|
||||
from .remove_resource import remove_resource
|
||||
from .remove_resource_quantity import remove_resource_quantity
|
||||
from .unassign_resource import unassign_resource
|
||||
|
||||
wrap_usecases(__path__, __name__)
|
||||
|
||||
__all__ = [
|
||||
"add_resource",
|
||||
"add_resource_quantity",
|
||||
"add_resource_time",
|
||||
"assign_resource",
|
||||
"calculate_resource_usage",
|
||||
"calculate_resource_work",
|
||||
"edit_resource",
|
||||
"edit_resource_quantity",
|
||||
"edit_resource_time",
|
||||
"remove_resource",
|
||||
"remove_resource_quantity",
|
||||
"unassign_resource",
|
||||
]
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,89 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import ifcopenshell.api.nest
|
||||
import ifcopenshell.api.project
|
||||
import ifcopenshell.api.root
|
||||
|
||||
|
||||
def add_resource(
|
||||
file: ifcopenshell.file,
|
||||
parent_resource: Optional[ifcopenshell.entity_instance] = None,
|
||||
ifc_class: str = "IfcCrewResource",
|
||||
name: Optional[str] = None,
|
||||
predefined_type: str = "NOTDEFINED",
|
||||
) -> ifcopenshell.entity_instance:
|
||||
"""Add a new construction resource
|
||||
|
||||
Construction resources may be managed and connected to cost schedules
|
||||
and construction schedules. This allows calculations to be done on
|
||||
resource utilisation, cost optimisation (e.g. labour rates), and
|
||||
optioneering on build strategies.
|
||||
|
||||
There are typically two types of resources. Crew resources are resources
|
||||
where you manage your own crew and you have full control over the
|
||||
equipment, labour, products, and materials used by your crew.
|
||||
Alternatively, there are subcontractor resources, where you simply
|
||||
delegate all the details to a subcontractor and it is not decomposed
|
||||
into further levels of detail.
|
||||
|
||||
This means when adding resources, you'd first either add a crew or
|
||||
subcontract resource. If it is a crew resource, you'd then add child
|
||||
resources to that crew, such as equipment (cranes, excavators, hoists,
|
||||
etc), material (wood, concrete, etc), and labour (rigging crews,
|
||||
formworkers, etc).
|
||||
|
||||
:param parent_resource: If this is a child resource (typically to a crew
|
||||
resource), then nominate the parent IfcConstructionResource here.
|
||||
:param ifc_class: The class of resource chosen from
|
||||
IfcConstructionEquipmentResource, IfcConstructionMaterialResource,
|
||||
IfcConstructionProductResource, IfcCrewResource, IfcLaborResource,
|
||||
or IfcSubContractResource.
|
||||
:param name: The name of the resource
|
||||
:param predefined_type: Consult the IFC documentation for the valid
|
||||
predefined types for each type of resource class.
|
||||
:return: The newly created resource depending on the nominated IFC
|
||||
class.
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some labour to our crew.
|
||||
ifcopenshell.api.resource.add_resource(model, parent_resource=crew, ifc_class="IfcLaborResource")
|
||||
"""
|
||||
|
||||
resource = ifcopenshell.api.root.create_entity(
|
||||
file,
|
||||
ifc_class=ifc_class,
|
||||
predefined_type=predefined_type,
|
||||
name=name or "Unnamed",
|
||||
)
|
||||
# TODO: this is an ambiguity by buildingSMART: Can we nest an IfcCrewResource under an IfcCrewResource ?
|
||||
# https://forums.buildingsmart.org/t/what-are-allowed-to-be-root-level-construction-resources/3550
|
||||
if parent_resource:
|
||||
ifcopenshell.api.nest.assign_object(file, related_objects=[resource], relating_object=parent_resource)
|
||||
elif file.schema != "IFC2X3":
|
||||
context = file.by_type("IfcContext")[0]
|
||||
ifcopenshell.api.project.assign_declaration(file, definitions=[resource], relating_context=context)
|
||||
return resource
|
||||
@@ -0,0 +1,83 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.resource
|
||||
|
||||
|
||||
def add_resource_quantity(
|
||||
file: ifcopenshell.file, resource: ifcopenshell.entity_instance, ifc_class: str = "IfcQuantityCount"
|
||||
) -> ifcopenshell.entity_instance:
|
||||
"""Adds a quantity to a resource
|
||||
|
||||
The quantity of a resource represents the "unit quantity" of that
|
||||
resource. For example, labour might be hired on a daily basis (8 hours).
|
||||
There are different types of quantities (e.g. volume, count, or time).
|
||||
Which quantity is used depends on the type of resource. Material
|
||||
resources may be quantified in terms of length, area, volume, or weight.
|
||||
Equipment and labour resources are quantified in terms of time. Products
|
||||
resources are quantified in terms of counts.
|
||||
|
||||
This base quantity is then used in other calculations.
|
||||
|
||||
:param resource: The IfcConstructionResource to add a quantity to.
|
||||
:param ifc_class: The type of quantity to add, chosen from
|
||||
IfcQuantityArea (for material), IfcQuantityCount (for products),
|
||||
IfcQuantityLength (for material), IfcQuantityTime (for equipment or
|
||||
labour), IfcQuantityVolume (for material), and IfcQuantityWeight
|
||||
(for material).
|
||||
:return: The newly created quantity depending on the IFC class
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some labour to our crew.
|
||||
labour = ifcopenshell.api.resource.add_resource(model,
|
||||
parent_resource=crew, ifc_class="IfcLaborResource")
|
||||
|
||||
# Labour resource is quantified in terms of time.
|
||||
quantity = ifcopenshell.api.resource.add_resource_quantity(model,
|
||||
resource=labour, ifc_class="IfcQuantityTime")
|
||||
|
||||
# Store the time used in hours
|
||||
ifcopenshell.api.resource.edit_resource_quantity(model,
|
||||
physical_quantity=quantity, attributes={"TimeValue": 8.0})
|
||||
"""
|
||||
resource_type = resource.is_a()
|
||||
supported_quantities = ifcopenshell.util.resource.RESOURCES_TO_QUANTITIES[resource_type]
|
||||
if ifc_class not in supported_quantities:
|
||||
raise ValueError(
|
||||
f"Resource type '{resource_type}' does not support quantity type '{ifc_class}'. "
|
||||
f"Supported quantities: {','.join(supported_quantities)}"
|
||||
)
|
||||
|
||||
quantity = file.create_entity(ifc_class, Name="Unnamed")
|
||||
# 3 IfcPhysicalSimpleQuantity Value
|
||||
if ifc_class == "IfcQuantityCount":
|
||||
quantity[3] = 0
|
||||
else:
|
||||
quantity[3] = 0.0
|
||||
old_quantity = resource.BaseQuantity
|
||||
resource.BaseQuantity = quantity
|
||||
if old_quantity:
|
||||
ifcopenshell.util.element.remove_deep2(file, old_quantity)
|
||||
return quantity
|
||||
@@ -0,0 +1,59 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
def add_resource_time(file: ifcopenshell.file, resource: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||
"""Adds the time that a resource is used for
|
||||
|
||||
For labour and equipment resources, the total duration that the resource
|
||||
is used for may be stored. This may either be input manually or
|
||||
calculated parametrically. This is known as the resource time, and may
|
||||
be used to calculate other parameters like resource utilisation.
|
||||
|
||||
:param resource: The IfcConstructionResource to record time for.
|
||||
:return: The newly created IfcResourceTime
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some labour to our crew.
|
||||
labour = ifcopenshell.api.resource.add_resource(model,
|
||||
parent_resource=crew, ifc_class="IfcLaborResource")
|
||||
|
||||
# Labour resource is quantified in terms of time.
|
||||
quantity = ifcopenshell.api.resource.add_resource_quantity(model,
|
||||
resource=labour, ifc_class="IfcQuantityTime")
|
||||
|
||||
# Store the unit time used in hours
|
||||
ifcopenshell.api.resource.edit_resource_quantity(model,
|
||||
physical_quantity=quantity, attributes={"TimeValue": 8.0})
|
||||
|
||||
# Let's imagine we've used the resource for 2 days.
|
||||
time = ifcopenshell.api.resource.add_resource_time(model, resource=labour)
|
||||
ifcopenshell.api.resource.edit_resource_time(model,
|
||||
resource_time=time, attributes={"ScheduleWork": "PT16H"})
|
||||
"""
|
||||
resource_time = file.create_entity("IfcResourceTime")
|
||||
resource.Usage = resource_time
|
||||
return resource_time
|
||||
@@ -0,0 +1,106 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.owner
|
||||
import ifcopenshell.guid
|
||||
|
||||
|
||||
def assign_resource(
|
||||
file: ifcopenshell.file,
|
||||
relating_resource: ifcopenshell.entity_instance,
|
||||
related_object: ifcopenshell.entity_instance,
|
||||
) -> ifcopenshell.entity_instance:
|
||||
"""Assigns a resource to an object
|
||||
|
||||
Two types of objects are typically assigned to resources: products and
|
||||
actors.
|
||||
|
||||
If a product is assigned to a resource, that means that the product
|
||||
represents the resource on site. This may be represented via material
|
||||
handling zones on a construction site, or equipment like cranes and
|
||||
their physical locations.
|
||||
|
||||
If an actor is assigned to a resource, that means that the actor (person
|
||||
or organisation) is the actor consuming the resource (e.g. if the
|
||||
resource is material or equipment) or the actor performing the work
|
||||
(e.g. if the resource is a labour resource).
|
||||
|
||||
:param relating_resource: The IfcResource to assign the object to.
|
||||
:param related_object: The IfcProduct or IfcActor to assign to the
|
||||
object.
|
||||
:return: The newly created IfcRelAssignsToResource
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some a tower crane to our crew.
|
||||
crane = ifcopenshell.api.resource.add_resource(model,
|
||||
parent_resource=crew, ifc_class="IfcConstructionEquipmentResource", name="Tower Crane 01")
|
||||
|
||||
# Our tower crane will be placed via this physical product.
|
||||
product = ifcopenshell.api.root.create_entity(model,
|
||||
ifc_class="IfcBuildingElementProxy", predefined_type="CRANE")
|
||||
|
||||
# Let's place our crane at some X, Y coordinates.
|
||||
matrix = numpy.eye(4)
|
||||
matrix[0][3], matrix[1][3] = 3.0, 4.0
|
||||
ifcopenshell.api.geometry.edit_object_placement(model, product=crane, matrix=matrix)
|
||||
|
||||
# Let's assign our crane to the resource. The crane now represents
|
||||
# the resource.
|
||||
ifcopenshell.api.resource.assign_resource(model, relating_resource=crane, related_object=product)
|
||||
|
||||
# Setup an organisation actor who will operate the crane
|
||||
organisation = ifcopenshell.api.owner.add_organisation(model,
|
||||
identification="UCO", name="Unionised Crane Operators Pty Ltd")
|
||||
role = ifcopenshell.api.owner.add_role(model, assigned_object=organisation, role="CREW")
|
||||
actor = ifcopenshell.api.owner.add_actor(model, actor=organisation)
|
||||
|
||||
# This means that UCO is now our crane operator.
|
||||
ifcopenshell.api.resource.assign_resource(model, relating_resource=crane, related_object=actor)
|
||||
"""
|
||||
if related_object.HasAssignments:
|
||||
for assignment in related_object.HasAssignments:
|
||||
if assignment.is_a("IfclRelAssignsToResource") and assignment.RelatingResource == relating_resource:
|
||||
return assignment
|
||||
|
||||
resource_of = None
|
||||
if relating_resource.ResourceOf:
|
||||
resource_of = relating_resource.ResourceOf[0]
|
||||
|
||||
if resource_of:
|
||||
related_objects = list(resource_of.RelatedObjects)
|
||||
related_objects.append(related_object)
|
||||
resource_of.RelatedObjects = related_objects
|
||||
ifcopenshell.api.owner.update_owner_history(file, element=resource_of)
|
||||
else:
|
||||
resource_of = file.create_entity(
|
||||
"IfcRelAssignsToResource",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(file),
|
||||
"RelatedObjects": [related_object],
|
||||
"RelatingResource": relating_resource,
|
||||
}
|
||||
)
|
||||
return resource_of
|
||||
@@ -0,0 +1,54 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.constraint
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.resource
|
||||
|
||||
|
||||
def calculate_resource_usage(file: ifcopenshell.file, resource: ifcopenshell.entity_instance) -> None:
|
||||
"""Calculates the number of resources required to perform scheduled work on a task.
|
||||
|
||||
:param resource: The IfcConstructionResource to calculate the usage for.
|
||||
:return: None
|
||||
"""
|
||||
|
||||
if ifcopenshell.util.constraint.is_attribute_locked(resource, "Usage.ScheduleUsage"):
|
||||
return
|
||||
if not resource.Usage or not resource.Usage.ScheduleWork:
|
||||
return
|
||||
|
||||
task = ifcopenshell.util.resource.get_task_assignments(resource)
|
||||
if not task or not task.TaskTime:
|
||||
return
|
||||
|
||||
if not task.TaskTime.DurationType or task.TaskTime.DurationType == "WORKTIME":
|
||||
hours_per_day = 8
|
||||
else:
|
||||
hours_per_day = 24
|
||||
|
||||
task_duration = ifcopenshell.util.date.ifc2datetime(task.TaskTime.ScheduleDuration)
|
||||
seconds = task_duration.days * hours_per_day * 60 * 60
|
||||
seconds += task_duration.seconds
|
||||
|
||||
person_hours = ifcopenshell.util.date.ifc2datetime(resource.Usage.ScheduleWork)
|
||||
|
||||
required_resources = person_hours.total_seconds() / seconds
|
||||
resource.Usage.ScheduleUsage = float(required_resources)
|
||||
@@ -0,0 +1,61 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell.api.resource
|
||||
import ifcopenshell.util.constraint
|
||||
import ifcopenshell.util.resource
|
||||
|
||||
|
||||
def calculate_resource_work(file: ifcopenshell.file, resource: ifcopenshell.entity_instance) -> None:
|
||||
"""Calculates the work that a resource is used for
|
||||
|
||||
This is an unofficial parametric calculation that may be done on a
|
||||
resource based on careful analysis of the relationships between the
|
||||
costing, scheduling, and resource domains in IFC.
|
||||
|
||||
A resource may store a productivity rate in a property set called
|
||||
EPset_Productivity. This stores three properties:
|
||||
|
||||
* BaseQuantityConsumed - a duration that the resource is consumed for.
|
||||
* BaseQuantityProducedName - what quantity the resource can produce,
|
||||
such as area or volume.
|
||||
* BaseQuantityProducedValue - what value of that quantity the resource
|
||||
can produce during that duration.
|
||||
|
||||
For example, a labour or equipment resource might produce 100m3 of
|
||||
NetVolume every day (i.e. 8 hours are consumed).
|
||||
|
||||
Then, if a resource is assigned to a construction task, and that
|
||||
construction task is assigned to concrete slabs totalling 200m3, we can
|
||||
calculate that the resource consumes 16 hours of work.
|
||||
|
||||
This calculated work is stored against the resource as scheduled work
|
||||
under the resource time data.
|
||||
|
||||
:param resource: The IfcConstructionResource that you want to calculate
|
||||
the work performed.
|
||||
:return None:
|
||||
"""
|
||||
if ifcopenshell.util.constraint.is_attribute_locked(resource, "Usage.ScheduleWork"):
|
||||
return
|
||||
amount_worked = ifcopenshell.util.resource.get_resource_required_work(resource)
|
||||
if not amount_worked:
|
||||
return
|
||||
if not resource.Usage:
|
||||
ifcopenshell.api.resource.add_resource_time(file, resource=resource)
|
||||
resource.Usage.ScheduleWork = amount_worked
|
||||
@@ -0,0 +1,44 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
from typing import Any
|
||||
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
def edit_resource(file: ifcopenshell.file, resource: ifcopenshell.entity_instance, attributes: dict[str, Any]) -> None:
|
||||
"""Edits the attributes of an IfcResource
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcResource, consult the IFC documentation.
|
||||
|
||||
:param resource: The IfcResource entity you want to edit
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:return: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Change the name of the resource to "Zone A Crew"
|
||||
ifcopenshell.api.resource.edit_resource(model, resource=resource, attributes={"Name": "Foo"})
|
||||
"""
|
||||
for name, value in attributes.items():
|
||||
setattr(resource, name, value)
|
||||
@@ -0,0 +1,55 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
from typing import Any
|
||||
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
def edit_resource_quantity(
|
||||
file: ifcopenshell.file, physical_quantity: ifcopenshell.entity_instance, attributes: dict[str, Any]
|
||||
) -> None:
|
||||
"""Edits the attributes of an IFC quantity
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfC quantity, consult the IFC documentation.
|
||||
|
||||
:param physical_quantity: The IfC quantity entity you want to edit
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:return: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some labour to our crew.
|
||||
labour = ifcopenshell.api.resource.add_resource(model,
|
||||
parent_resource=crew, ifc_class="IfcLaborResource")
|
||||
|
||||
# Labour resource is quantified in terms of time.
|
||||
ifcopenshell.api.resource.add_resource_quantity(model,
|
||||
resource=labour, ifc_class="IfcQuantityTime")
|
||||
|
||||
# Store the time used in hours
|
||||
ifcopenshell.api.resource.edit_resource_quantity(model,
|
||||
physical_quantity=time, attributes={"TimeValue": 8.0})
|
||||
"""
|
||||
for name, value in attributes.items():
|
||||
setattr(physical_quantity, name, value)
|
||||
@@ -0,0 +1,99 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import Any
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.sequence
|
||||
import ifcopenshell.util.constraint
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.resource
|
||||
|
||||
|
||||
def edit_resource_time(
|
||||
file: ifcopenshell.file, resource_time: ifcopenshell.entity_instance, attributes: dict[str, Any]
|
||||
) -> None:
|
||||
"""Edits the attributes of an IfcResourceTime
|
||||
|
||||
For more information about the attributes and data types of an
|
||||
IfcResourceTime, consult the IFC documentation.
|
||||
|
||||
:param resource_time: The IfcResourceTime entity you want to edit
|
||||
:param attributes: a dictionary of attribute names and values.
|
||||
:return: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some labour to our crew.
|
||||
labour = ifcopenshell.api.resource.add_resource(model,
|
||||
parent_resource=crew, ifc_class="IfcLaborResource")
|
||||
|
||||
# Labour resource is quantified in terms of time.
|
||||
ifcopenshell.api.resource.add_resource_quantity(model,
|
||||
resource=labour, ifc_class="IfcQuantityTime")
|
||||
|
||||
# Store the unit time used in hours
|
||||
ifcopenshell.api.resource.edit_resource_quantity(model,
|
||||
physical_quantity=time, attributes={"TimeValue": 8.0})
|
||||
|
||||
# Let's imagine we've used the resource for 2 days.
|
||||
time = ifcopenshell.api.resource.add_resource_time(model, resource=labour)
|
||||
ifcopenshell.api.resource.edit_resource_time(model,
|
||||
resource_time=time, attributes={"ScheduleWork": "P16H"})
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
return usecase.execute(resource_time, attributes)
|
||||
|
||||
|
||||
class Usecase:
|
||||
file: ifcopenshell.file
|
||||
|
||||
def execute(self, resource_time: ifcopenshell.entity_instance, attributes: dict[str, Any]) -> None:
|
||||
resource = self.get_resource(resource_time)
|
||||
|
||||
# If the user specifies both an end date and a duration, the duration takes priority
|
||||
if attributes.get("ScheduleWork", None) and "ScheduleFinish" in attributes.keys():
|
||||
del attributes["ScheduleFinish"]
|
||||
if attributes.get("ActualWork", None) and "ActualFinish" in attributes.keys():
|
||||
del attributes["ActualFinish"]
|
||||
|
||||
for name, value in attributes.items():
|
||||
metrics = ifcopenshell.util.constraint.get_metric_constraints(resource, "Usage." + name)
|
||||
if metrics and ifcopenshell.util.constraint.is_hard_constraint(metrics[0]):
|
||||
continue
|
||||
if value:
|
||||
if "Start" in name or "Finish" in name or name == "StatusTime":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
elif name == "ScheduleWork" or name == "ActualWork" or name == "RemainingTime":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(resource_time, name, value)
|
||||
if name == "ScheduleUsage" and ifcopenshell.util.constraint.get_metric_constraints(
|
||||
resource, "Usage.ScheduleWork"
|
||||
):
|
||||
task = ifcopenshell.util.resource.get_task_assignments(resource)
|
||||
if task:
|
||||
ifcopenshell.api.sequence.calculate_task_duration(self.file, task=task)
|
||||
|
||||
def get_resource(self, resource_time: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||
return next(e for e in self.file.get_inverse(resource_time) if e.is_a("IfcResource"))
|
||||
@@ -0,0 +1,78 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021-2022, Dion Moult <dion@thinkmoult.com>, Yassine Oualid <yassine@sigmadimensions.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.resource
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
def remove_resource(file: ifcopenshell.file, resource: ifcopenshell.entity_instance) -> None:
|
||||
"""Removes a resource and all relationships
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Fire our crew
|
||||
ifcopenshell.api.resource.remove_resource(model, resource=crew)
|
||||
"""
|
||||
settings = {"resource": resource}
|
||||
|
||||
def remove_consider_history(root: ifcopenshell.entity_instance) -> None:
|
||||
history = root.OwnerHistory
|
||||
file.remove(root)
|
||||
if history:
|
||||
ifcopenshell.util.element.remove_deep2(file, history)
|
||||
|
||||
# TODO: review deep purge
|
||||
for inverse in file.get_inverse(settings["resource"]):
|
||||
if inverse.is_a("IfcRelNests"):
|
||||
if inverse.RelatingObject == settings["resource"]:
|
||||
# Remove rel before iteration over objects
|
||||
# to simplify removal of nested resources and avoid crashes.
|
||||
related_objects = inverse.RelatedObjects
|
||||
remove_consider_history(inverse)
|
||||
for related_object in related_objects:
|
||||
ifcopenshell.api.resource.remove_resource(file, resource=related_object)
|
||||
elif inverse.RelatedObjects == (resource,):
|
||||
remove_consider_history(inverse)
|
||||
|
||||
elif inverse.is_a("IfcRelAssignsToControl"):
|
||||
if len(inverse.RelatedObjects) == 1:
|
||||
remove_consider_history(inverse)
|
||||
else:
|
||||
related_objects = list(inverse.RelatedObjects)
|
||||
related_objects.remove(settings["resource"])
|
||||
inverse.RelatedObjects = related_objects
|
||||
elif inverse.is_a("IfcRelAssignsToResource"):
|
||||
if inverse.RelatingResource == settings["resource"]:
|
||||
for related_object in inverse.RelatedObjects:
|
||||
ifcopenshell.api.resource.unassign_resource(
|
||||
file, related_object=related_object, relating_resource=settings["resource"]
|
||||
)
|
||||
elif inverse.RelatedObjects == (resource,):
|
||||
remove_consider_history(inverse)
|
||||
# Usage was added in IFC4.
|
||||
if usage := getattr(settings["resource"], "Usage", None):
|
||||
file.remove(usage)
|
||||
if settings["resource"].BaseQuantity:
|
||||
ifcopenshell.api.resource.remove_resource_quantity(file, resource=settings["resource"])
|
||||
remove_consider_history(resource)
|
||||
@@ -0,0 +1,50 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
def remove_resource_quantity(file: ifcopenshell.file, resource: ifcopenshell.entity_instance) -> None:
|
||||
"""Removes the base quantity of a resource
|
||||
|
||||
:param resource: The IfcConstructionResource to remove the quantity from.
|
||||
:return: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some labour to our crew.
|
||||
labour = ifcopenshell.api.resource.add_resource(model,
|
||||
parent_resource=crew, ifc_class="IfcLaborResource")
|
||||
|
||||
# Labour resource is quantified in terms of time.
|
||||
ifcopenshell.api.resource.add_resource_quantity(model,
|
||||
resource=labour, ifc_class="IfcQuantityTime")
|
||||
|
||||
# Let's say we only want to store the resource but no quantities,
|
||||
# let's clean up our mess and remove the quantity.
|
||||
ifcopenshell.api.resource.remove_resource_quantity(model, resource=labour)
|
||||
"""
|
||||
old_quantity = resource.BaseQuantity
|
||||
resource.BaseQuantity = None
|
||||
if old_quantity:
|
||||
ifcopenshell.util.element.remove_deep2(file, old_quantity)
|
||||
@@ -0,0 +1,72 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.owner
|
||||
import ifcopenshell.util.element
|
||||
|
||||
|
||||
def unassign_resource(
|
||||
file: ifcopenshell.file,
|
||||
relating_resource: ifcopenshell.entity_instance,
|
||||
related_object: ifcopenshell.entity_instance,
|
||||
) -> None:
|
||||
"""Removes the relationship between a resource and object
|
||||
|
||||
:param relating_resource: The IfcResource to assign the object to.
|
||||
:param related_object: The IfcProduct or IfcActor to assign to the
|
||||
object.
|
||||
:return: None
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Add our own crew
|
||||
crew = ifcopenshell.api.resource.add_resource(model, ifc_class="IfcCrewResource")
|
||||
|
||||
# Add some a tower crane to our crew.
|
||||
crane = ifcopenshell.api.resource.add_resource(model,
|
||||
parent_resource=crew, ifc_class="IfcConstructionEquipmentResource", name="Tower Crane 01")
|
||||
|
||||
# Our tower crane will be placed via this physical product.
|
||||
product = ifcopenshell.api.root.create_entity(model,
|
||||
ifc_class="IfcBuildingElementProxy", predefined_type="CRANE")
|
||||
|
||||
# Let's assign our crane to the resource. The crane now represents
|
||||
# the resource.
|
||||
ifcopenshell.api.resource.assign_resource(model,
|
||||
relating_resource=crane, related_object=product)
|
||||
|
||||
# Undo it.
|
||||
ifcopenshell.api.resource.unassign_resource(model,
|
||||
relating_resource=crane, related_object=product)
|
||||
"""
|
||||
for rel in related_object.HasAssignments or []:
|
||||
if not rel.is_a("IfcRelAssignsToResource") or rel.RelatingResource != relating_resource:
|
||||
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(related_object)
|
||||
rel.RelatedObjects = related_objects
|
||||
ifcopenshell.api.owner.update_owner_history(file, element=rel)
|
||||
Reference in New Issue
Block a user