Generate functions for all API usecases for better static code features. See #2693.

This commit is contained in:
Dion Moult
2024-05-06 14:35:39 +10:00
parent 10f894e2ea
commit d11ec67129
330 changed files with 13283 additions and 13751 deletions
@@ -15,3 +15,16 @@
#
# 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_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
@@ -19,93 +19,89 @@
import ifcopenshell.api
class Usecase:
def __init__(
self,
def add_resource(
file,
parent_resource=None,
ifc_class="IfcCrewResource",
name=None,
predefined_type="NOTDEFINED",
) -> None:
"""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.
:type parent_resource: ifcopenshell.entity_instance
:param ifc_class: The class of resource chosen from
IfcConstructionEquipmentResource, IfcConstructionMaterialResource,
IfcConstructionProductResource, IfcCrewResource, IfcLaborResource,
or IfcSubContractResource.
:type ifc_class: str,optional
:param name: The name of the resource
:type name: str,optional
:param predefined_type: Consult the IFC documentation for the valid
predefined types for each type of resource class.
:type predefined_type: str,optional
:return: The newly created resource depending on the nominated IFC
class.
:rtype: ifcopenshell.entity_instance
Example:
.. code:: python
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add some labour to our crew.
ifcopenshell.api.run("resource.add_resource", model, parent_resource=crew, ifc_class="IfcLaborResource")
"""
settings = {
"parent_resource": parent_resource,
"ifc_class": ifc_class,
"name": name,
"predefined_type": predefined_type,
}
resource = ifcopenshell.api.run(
"root.create_entity",
file,
parent_resource=None,
ifc_class="IfcCrewResource",
name=None,
predefined_type="NOTDEFINED",
):
"""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.
:type parent_resource: ifcopenshell.entity_instance
:param ifc_class: The class of resource chosen from
IfcConstructionEquipmentResource, IfcConstructionMaterialResource,
IfcConstructionProductResource, IfcCrewResource, IfcLaborResource,
or IfcSubContractResource.
:type ifc_class: str,optional
:param name: The name of the resource
:type name: str,optional
:param predefined_type: Consult the IFC documentation for the valid
predefined types for each type of resource class.
:type predefined_type: str,optional
:return: The newly created resource depending on the nominated IFC
class.
:rtype: ifcopenshell.entity_instance
Example:
.. code:: python
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add some labour to our crew.
ifcopenshell.api.run("resource.add_resource", model, parent_resource=crew, ifc_class="IfcLaborResource")
"""
self.file = file
self.settings = {
"parent_resource": parent_resource,
"ifc_class": ifc_class,
"name": name,
"predefined_type": predefined_type,
}
def execute(self):
resource = ifcopenshell.api.run(
"root.create_entity",
self.file,
ifc_class=self.settings["ifc_class"],
predefined_type=self.settings["predefined_type"],
name=self.settings["name"] or "Unnamed",
ifc_class=settings["ifc_class"],
predefined_type=settings["predefined_type"],
name=settings["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 settings["parent_resource"]:
ifcopenshell.api.run(
"nest.assign_object",
file,
related_objects=[resource],
relating_object=settings["parent_resource"],
)
# 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 self.settings["parent_resource"]:
ifcopenshell.api.run(
"nest.assign_object",
self.file,
related_objects=[resource],
relating_object=self.settings["parent_resource"],
)
else:
context = self.file.by_type("IfcContext")[0]
ifcopenshell.api.run(
"project.assign_declaration",
self.file,
definitions=[resource],
relating_context=context,
)
return resource
else:
context = file.by_type("IfcContext")[0]
ifcopenshell.api.run(
"project.assign_declaration",
file,
definitions=[resource],
relating_context=context,
)
return resource
@@ -19,58 +19,55 @@
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, resource=None, ifc_class="IfcQuantityCount"):
"""Adds a quantity to a resource
def add_resource_quantity(file, resource=None, ifc_class="IfcQuantityCount") -> None:
"""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.
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.
This base quantity is then used in other calculations.
:param resource: The IfcConstructionResource to add a quantity to.
:type resource: ifcopenshell.entity_instance
: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).
:type ifc_class: str,optional
:return: The newly created quantity depending on the IFC class
:rtype: ifcopenshell.entity_instance
:param resource: The IfcConstructionResource to add a quantity to.
:type resource: ifcopenshell.entity_instance
: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).
:type ifc_class: str,optional
:return: The newly created quantity depending on the IFC class
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# 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")
# 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")
# Labour resource is quantified in terms of time.
quantity = ifcopenshell.api.run("resource.add_resource_quantity", model,
resource=labour, ifc_class="IfcQuantityTime")
# Store the time used in hours
ifcopenshell.api.run("resource.edit_resource_quantity", model,
physical_quantity=quantity, attributes={"TimeValue": 8.0})
"""
self.file = file
self.settings = {"resource": resource, "ifc_class": ifc_class}
# Store the time used in hours
ifcopenshell.api.run("resource.edit_resource_quantity", model,
physical_quantity=quantity, attributes={"TimeValue": 8.0})
"""
settings = {"resource": resource, "ifc_class": ifc_class}
def execute(self):
quantity = self.file.create_entity(self.settings["ifc_class"], Name="Unnamed")
quantity[3] = 0.0
old_quantity = self.settings["resource"].BaseQuantity
self.settings["resource"].BaseQuantity = quantity
if old_quantity:
ifcopenshell.util.element.remove_deep(self.file, old_quantity)
return quantity
quantity = file.create_entity(settings["ifc_class"], Name="Unnamed")
quantity[3] = 0.0
old_quantity = settings["resource"].BaseQuantity
settings["resource"].BaseQuantity = quantity
if old_quantity:
ifcopenshell.util.element.remove_deep(file, old_quantity)
return quantity
@@ -19,50 +19,47 @@
import ifcopenshell.util.date
class Usecase:
def __init__(self, file, resource=None):
"""Adds the time that a resource is used for
def add_resource_time(file, resource=None) -> None:
"""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.
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.
:type resource: ifcopenshell.entity_instance
:return: The newly created IfcResourceTime
:rtype: ifcopenshell.entity_instance
:param resource: The IfcConstructionResource to record time for.
:type resource: ifcopenshell.entity_instance
:return: The newly created IfcResourceTime
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# 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")
# 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")
# 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})
# 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 2 days.
time = ifcopenshell.api.run("resource.add_resource_time", model, resource=labour)
ifcopenshell.api.run("resource.edit_resource_time", model,
resource_time=time, attributes={"ScheduleWork": "PT16H"})
"""
self.file = file
self.settings = {
"resource": resource,
}
# Let's imagine we've used the resource for 2 days.
time = ifcopenshell.api.run("resource.add_resource_time", model, resource=labour)
ifcopenshell.api.run("resource.edit_resource_time", model,
resource_time=time, attributes={"ScheduleWork": "PT16H"})
"""
settings = {
"resource": resource,
}
def execute(self):
resource_time = self.file.create_entity("IfcResourceTime")
self.settings["resource"].Usage = resource_time
return resource_time
resource_time = file.create_entity("IfcResourceTime")
settings["resource"].Usage = resource_time
return resource_time
@@ -20,101 +20,93 @@ import ifcopenshell
import ifcopenshell.api
class Usecase:
def __init__(self, file, relating_resource=None, related_object=None):
"""Assigns a resource to an object
def assign_resource(file, relating_resource=None, related_object=None) -> None:
"""Assigns a resource to an object
Two types of objects are typically assigned to resources: products and
actors.
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 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).
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.
:type relating_resource: ifcopenshell.entity_instance
:param related_object: The IfcProduct or IfcActor to assign to the
object.
:type related_object: ifcopenshell.entity_instance
:return: The newly created IfcRelAssignsToResource
:rtype: ifcopenshell.entity_instance
:param relating_resource: The IfcResource to assign the object to.
:type relating_resource: ifcopenshell.entity_instance
:param related_object: The IfcProduct or IfcActor to assign to the
object.
:type related_object: ifcopenshell.entity_instance
:return: The newly created IfcRelAssignsToResource
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add some a tower crane to our crew.
crane = ifcopenshell.api.run("resource.add_resource", model,
parent_resource=crew, ifc_class="IfcConstructionEquipmentResource", name="Tower Crane 01")
# Add some a tower crane to our crew.
crane = ifcopenshell.api.run("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.run("root.create_entity", model,
ifc_class="IfcBuildingElementProxy", predefined_type="CRANE")
# Our tower crane will be placed via this physical product.
product = ifcopenshell.api.run("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.run("geometry.edit_object_placement", model, product=crane, matrix=matrix)
# 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.run("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.run("resource.assign_resource", model, relating_resource=crane, related_object=product)
# Let's assign our crane to the resource. The crane now represents
# the resource.
ifcopenshell.api.run("resource.assign_resource", model, relating_resource=crane, related_object=product)
# Setup an organisation actor who will operate the crane
organisation = ifcopenshell.api.run("owner.add_organisation", model,
identification="UCO", name="Unionised Crane Operators Pty Ltd")
role = ifcopenshell.api.run("owner.add_role", model, assigned_object=organisation, role="CREW")
actor = ifcopenshell.api.run("owner.add_actor", model, actor=organisation)
# Setup an organisation actor who will operate the crane
organisation = ifcopenshell.api.run("owner.add_organisation", model,
identification="UCO", name="Unionised Crane Operators Pty Ltd")
role = ifcopenshell.api.run("owner.add_role", model, assigned_object=organisation, role="CREW")
actor = ifcopenshell.api.run("owner.add_actor", model, actor=organisation)
# This means that UCO is now our crane operator.
ifcopenshell.api.run("resource.assign_resource", model, relating_resource=crane, related_object=actor)
"""
self.file = file
self.settings = {
"relating_resource": relating_resource,
"related_object": related_object,
}
# This means that UCO is now our crane operator.
ifcopenshell.api.run("resource.assign_resource", model, relating_resource=crane, related_object=actor)
"""
settings = {
"relating_resource": relating_resource,
"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("IfclRelAssignsToResource")
and assignment.RelatingResource
== self.settings["relating_resource"]
):
return
if settings["related_object"].HasAssignments:
for assignment in settings["related_object"].HasAssignments:
if (
assignment.is_a("IfclRelAssignsToResource")
and assignment.RelatingResource == settings["relating_resource"]
):
return
resource_of = None
if self.settings["relating_resource"].ResourceOf:
resource_of = self.settings["relating_resource"].ResourceOf[0]
resource_of = None
if settings["relating_resource"].ResourceOf:
resource_of = settings["relating_resource"].ResourceOf[0]
if resource_of:
related_objects = list(resource_of.RelatedObjects)
related_objects.append(self.settings["related_object"])
resource_of.RelatedObjects = related_objects
ifcopenshell.api.run(
"owner.update_owner_history", self.file, **{"element": resource_of}
)
else:
resource_of = self.file.create_entity(
"IfcRelAssignsToResource",
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.run(
"owner.create_owner_history", self.file
),
"RelatedObjects": [self.settings["related_object"]],
"RelatingResource": self.settings["relating_resource"],
}
)
return resource_of
if resource_of:
related_objects = list(resource_of.RelatedObjects)
related_objects.append(settings["related_object"])
resource_of.RelatedObjects = related_objects
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": resource_of})
else:
resource_of = file.create_entity(
"IfcRelAssignsToResource",
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
"RelatedObjects": [settings["related_object"]],
"RelatingResource": settings["relating_resource"],
}
)
return resource_of
@@ -23,42 +23,29 @@ import ifcopenshell.util.element
import ifcopenshell.util.resource
class Usecase:
def __init__(self, file, resource=None):
"""Calculates the number of resources required to perform scheduled work on a task.
"""
self.file = file
self.settings = {"resource": resource}
def calculate_resource_usage(file, resource=None) -> None:
"""Calculates the number of resources required to perform scheduled work on a task."""
settings = {"resource": resource}
def execute(self):
if ifcopenshell.util.constraint.is_attribute_locked(self.settings["resource"], "Usage.ScheduleUsage"):
return
if (
not self.settings["resource"].Usage
or not self.settings["resource"].Usage.ScheduleWork
):
return
if ifcopenshell.util.constraint.is_attribute_locked(settings["resource"], "Usage.ScheduleUsage"):
return
if not settings["resource"].Usage or not settings["resource"].Usage.ScheduleWork:
return
task = ifcopenshell.util.resource.get_task_assignments(
self.settings["resource"]
)
if not task or not task.TaskTime:
return
task = ifcopenshell.util.resource.get_task_assignments(settings["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
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
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(
self.settings["resource"].Usage.ScheduleWork
)
person_hours = ifcopenshell.util.date.ifc2datetime(settings["resource"].Usage.ScheduleWork)
required_resources = person_hours.total_seconds() / seconds
self.settings["resource"].Usage.ScheduleUsage = float(required_resources)
required_resources = person_hours.total_seconds() / seconds
settings["resource"].Usage.ScheduleUsage = float(required_resources)
@@ -23,52 +23,49 @@ import ifcopenshell.util.element
import ifcopenshell.util.resource
class Usecase:
def __init__(self, file, resource=None):
"""Calculates the work that a resource is used for
def calculate_resource_work(file, resource=None) -> 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.
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:
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.
* 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).
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.
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.
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.
:type resource: ifcopenshell.entity_instance
:return None:
:rtype: None:
"""
self.file = file
self.settings = {"resource": resource}
:param resource: The IfcConstructionResource that you want to calculate
the work performed.
:type resource: ifcopenshell.entity_instance
:return None:
:rtype: None:
"""
settings = {"resource": resource}
def execute(self):
if ifcopenshell.util.constraint.is_attribute_locked(self.settings["resource"], "Usage.ScheduleWork"):
return
amount_worked = ifcopenshell.util.resource.get_resource_required_work(self.settings["resource"])
if not amount_worked:
return
if not self.settings["resource"].Usage:
ifcopenshell.api.run(
"resource.add_resource_time",
self.file,
resource=self.settings["resource"],
)
self.settings["resource"].Usage.ScheduleWork = amount_worked
if ifcopenshell.util.constraint.is_attribute_locked(settings["resource"], "Usage.ScheduleWork"):
return
amount_worked = ifcopenshell.util.resource.get_resource_required_work(settings["resource"])
if not amount_worked:
return
if not settings["resource"].Usage:
ifcopenshell.api.run(
"resource.add_resource_time",
file,
resource=settings["resource"],
)
settings["resource"].Usage.ScheduleWork = amount_worked
@@ -17,33 +17,30 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, resource=None, attributes=None):
"""Edits the attributes of an IfcResource
def edit_resource(file, resource=None, attributes=None) -> None:
"""Edits the attributes of an IfcResource
For more information about the attributes and data types of an
IfcResource, consult the IFC documentation.
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
:type resource: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
:param resource: The IfcResource entity you want to edit
:type resource: 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
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Change the name of the resource to "Zone A Crew"
ifcopenshell.api.run("resource.edit_resource", model, resource=resource, attributes={"Name": "Foo"})
"""
self.file = file
self.settings = {"resource": resource, "attributes": attributes or {}}
# Change the name of the resource to "Zone A Crew"
ifcopenshell.api.run("resource.edit_resource", model, resource=resource, attributes={"Name": "Foo"})
"""
settings = {"resource": resource, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["resource"], name, value)
for name, value in settings["attributes"].items():
setattr(settings["resource"], name, value)
@@ -17,45 +17,42 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, physical_quantity=None, attributes=None):
"""Edits the attributes of an IFC quantity
def edit_resource_quantity(file, physical_quantity=None, attributes=None) -> 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.
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
:type physical_quantity: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
:param physical_quantity: The IfC quantity entity you want to edit
:type physical_quantity: 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
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# 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")
# 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.
ifcopenshell.api.run("resource.add_resource_quantity", model,
resource=labour, ifc_class="IfcQuantityTime")
# Labour resource is quantified in terms of time.
ifcopenshell.api.run("resource.add_resource_quantity", model,
resource=labour, ifc_class="IfcQuantityTime")
# Store the time used in hours
ifcopenshell.api.run("resource.edit_resource_quantity", model,
physical_quantity=time, attributes={"TimeValue": 8.0})
"""
self.file = file
self.settings = {
"physical_quantity": physical_quantity,
"attributes": attributes or {},
}
# Store the time used in hours
ifcopenshell.api.run("resource.edit_resource_quantity", model,
physical_quantity=time, attributes={"TimeValue": 8.0})
"""
settings = {
"physical_quantity": physical_quantity,
"attributes": attributes or {},
}
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["physical_quantity"], name, value)
for name, value in settings["attributes"].items():
setattr(settings["physical_quantity"], name, value)
@@ -20,47 +20,50 @@ import datetime
import ifcopenshell
def edit_resource_time(file, resource_time=None, attributes=None) -> 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
:type resource_time: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
: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.
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=time, attributes={"TimeValue": 8.0})
# Let's imagine we've used the resource for 2 days.
time = ifcopenshell.api.run("resource.add_resource_time", model, resource=labour)
ifcopenshell.api.run("resource.edit_resource_time", model,
resource_time=time, attributes={"ScheduleWork": "P16H"})
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {"resource_time": resource_time, "attributes": attributes or {}}
return usecase.execute()
class Usecase:
def __init__(self, file, resource_time=None, attributes=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
:type resource_time: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
: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.
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=time, attributes={"TimeValue": 8.0})
# Let's imagine we've used the resource for 2 days.
time = ifcopenshell.api.run("resource.add_resource_time", model, resource=labour)
ifcopenshell.api.run("resource.edit_resource_time", model,
resource_time=time, attributes={"ScheduleWork": "P16H"})
"""
self.file = file
self.settings = {"resource_time": resource_time, "attributes": attributes or {}}
def execute(self):
self.resource = self.get_resource()
@@ -70,43 +73,25 @@ class Usecase:
and "ScheduleFinish" in self.settings["attributes"].keys()
):
del self.settings["attributes"]["ScheduleFinish"]
if (
self.settings["attributes"].get("ActualWork", None)
and "ActualFinish" in self.settings["attributes"].keys()
):
if self.settings["attributes"].get("ActualWork", None) and "ActualFinish" in self.settings["attributes"].keys():
del self.settings["attributes"]["ActualFinish"]
for name, value in self.settings["attributes"].items():
metrics = ifcopenshell.util.constraint.get_metric_constraints(
self.resource, "Usage." + name
)
metrics = ifcopenshell.util.constraint.get_metric_constraints(self.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"
):
elif name == "ScheduleWork" or name == "ActualWork" or name == "RemainingTime":
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
setattr(self.settings["resource_time"], name, value)
if (
name == "ScheduleUsage"
and ifcopenshell.util.constraint.get_metric_constraints(
self.resource, "Usage.ScheduleWork"
)
if name == "ScheduleUsage" and ifcopenshell.util.constraint.get_metric_constraints(
self.resource, "Usage.ScheduleWork"
):
task = ifcopenshell.util.resource.get_task_assignments(self.resource)
if task:
ifcopenshell.api.run(
"sequence.calculate_task_duration", self.file, task=task
)
ifcopenshell.api.run("sequence.calculate_task_duration", self.file, task=task)
def get_resource(self):
return [
e
for e in self.file.get_inverse(self.settings["resource_time"])
if e.is_a("IfcResource")
][0]
return [e for e in self.file.get_inverse(self.settings["resource_time"]) if e.is_a("IfcResource")][0]
@@ -21,71 +21,68 @@ import ifcopenshell.api
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, resource=None):
"""Removes a resource and all relationships
def remove_resource(file, resource=None) -> None:
"""Removes a resource and all relationships
Example:
Example:
.. code:: python
.. code:: python
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Fire our crew
ifcopenshell.api.run("resource.remove_resource", model, resource=crew)
"""
self.file = file
self.settings = {"resource": resource}
# Fire our crew
ifcopenshell.api.run("resource.remove_resource", model, resource=crew)
"""
settings = {"resource": resource}
def execute(self):
# TODO: review deep purge
for inverse in self.file.get_inverse(self.settings["resource"]):
if inverse.is_a("IfcRelNests"):
if inverse.RelatingObject == self.settings["resource"]:
for related_object in inverse.RelatedObjects:
ifcopenshell.api.run(
"resource.remove_resource",
self.file,
resource=related_object,
)
history = inverse.OwnerHistory
self.file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(self.file, history)
elif inverse.is_a("IfcRelAssignsToControl"):
if 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["resource"])
inverse.RelatedObjects = related_objects
elif inverse.is_a("IfcRelAssignsToResource"):
if inverse.RelatingResource == self.settings["resource"]:
for related_object in inverse.RelatedObjects:
ifcopenshell.api.run(
"resource.unassign_resource",
self.file,
related_object=related_object,
resource=self.settings["resource"],
)
elif inverse.RelatedObjects == tuple(self.settings["resource"]):
history = inverse.OwnerHistory
self.file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(self.file, history)
if self.settings["resource"].Usage:
self.file.remove(self.settings["resource"].Usage)
if self.settings["resource"].BaseQuantity:
ifcopenshell.api.run(
"resource.remove_resource_quantity",
self.file,
resource=self.settings["resource"],
)
history = self.settings["resource"].OwnerHistory
self.file.remove(self.settings["resource"])
if history:
ifcopenshell.util.element.remove_deep2(self.file, history)
# TODO: review deep purge
for inverse in file.get_inverse(settings["resource"]):
if inverse.is_a("IfcRelNests"):
if inverse.RelatingObject == settings["resource"]:
for related_object in inverse.RelatedObjects:
ifcopenshell.api.run(
"resource.remove_resource",
file,
resource=related_object,
)
history = inverse.OwnerHistory
file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(file, history)
elif inverse.is_a("IfcRelAssignsToControl"):
if 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["resource"])
inverse.RelatedObjects = related_objects
elif inverse.is_a("IfcRelAssignsToResource"):
if inverse.RelatingResource == settings["resource"]:
for related_object in inverse.RelatedObjects:
ifcopenshell.api.run(
"resource.unassign_resource",
file,
related_object=related_object,
resource=settings["resource"],
)
elif inverse.RelatedObjects == tuple(settings["resource"]):
history = inverse.OwnerHistory
file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(file, history)
if settings["resource"].Usage:
file.remove(settings["resource"].Usage)
if settings["resource"].BaseQuantity:
ifcopenshell.api.run(
"resource.remove_resource_quantity",
file,
resource=settings["resource"],
)
history = settings["resource"].OwnerHistory
file.remove(settings["resource"])
if history:
ifcopenshell.util.element.remove_deep2(file, history)
@@ -19,34 +19,31 @@
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, resource=None):
"""Removes the base quantity of a resource
def remove_resource_quantity(file, resource=None) -> None:
"""Removes the base quantity of a resource
Example:
Example:
.. code:: python
.. code:: python
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# 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")
# 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.
ifcopenshell.api.run("resource.add_resource_quantity", model,
resource=labour, ifc_class="IfcQuantityTime")
# Labour resource is quantified in terms of time.
ifcopenshell.api.run("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.run("resource.remove_resource_quantity", model, resource=labour)
"""
self.file = file
self.settings = {"resource": resource}
# 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.run("resource.remove_resource_quantity", model, resource=labour)
"""
settings = {"resource": resource}
def execute(self):
old_quantity = self.settings["resource"].BaseQuantity
self.settings["resource"].BaseQuantity = None
if old_quantity:
ifcopenshell.util.element.remove_deep(self.file, old_quantity)
old_quantity = settings["resource"].BaseQuantity
settings["resource"].BaseQuantity = None
if old_quantity:
ifcopenshell.util.element.remove_deep(file, old_quantity)
@@ -21,65 +21,57 @@ import ifcopenshell.api
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, relating_resource=None, related_object=None):
"""Removes the relationship between a resource and object
def unassign_resource(file, relating_resource=None, related_object=None) -> None:
"""Removes the relationship between a resource and object
:param relating_resource: The IfcResource to assign the object to.
:type relating_resource: ifcopenshell.entity_instance
:param related_object: The IfcProduct or IfcActor to assign to the
object.
:type related_object: ifcopenshell.entity_instance
:return: The newly created IfcRelAssignsToResource
:rtype: ifcopenshell.entity_instance
:param relating_resource: The IfcResource to assign the object to.
:type relating_resource: ifcopenshell.entity_instance
:param related_object: The IfcProduct or IfcActor to assign to the
object.
:type related_object: ifcopenshell.entity_instance
:return: The newly created IfcRelAssignsToResource
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add some a tower crane to our crew.
crane = ifcopenshell.api.run("resource.add_resource", model,
parent_resource=crew, ifc_class="IfcConstructionEquipmentResource", name="Tower Crane 01")
# Add some a tower crane to our crew.
crane = ifcopenshell.api.run("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.run("root.create_entity", model,
ifc_class="IfcBuildingElementProxy", predefined_type="CRANE")
# Our tower crane will be placed via this physical product.
product = ifcopenshell.api.run("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.run("resource.assign_resource", model,
relating_resource=crane, related_object=product)
# Let's assign our crane to the resource. The crane now represents
# the resource.
ifcopenshell.api.run("resource.assign_resource", model,
relating_resource=crane, related_object=product)
# Undo it.
ifcopenshell.api.run("resource.unassign_resource", model,
relating_resource=crane, related_object=product)
"""
self.file = file
self.settings = {
"relating_resource": relating_resource,
"related_object": related_object,
}
# Undo it.
ifcopenshell.api.run("resource.unassign_resource", model,
relating_resource=crane, related_object=product)
"""
settings = {
"relating_resource": relating_resource,
"related_object": related_object,
}
def execute(self):
for rel in self.settings["related_object"].HasAssignments or []:
if (
not rel.is_a("IfcRelAssignsToResource")
or rel.RelatingResource != self.settings["relating_resource"]
):
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("IfcRelAssignsToResource") or rel.RelatingResource != settings["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(settings["related_object"])
rel.RelatedObjects = related_objects
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": rel})
return rel