First Commit

This commit is contained in:
2026-05-31 10:17:09 +07:00
commit 17a9c69379
4547 changed files with 1170384 additions and 0 deletions
@@ -0,0 +1,34 @@
# 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/>.
"""Processes and costs may be controlled by other entities which indicate
constraints that determine how they can change
This is an advanced feature mostly used in 4D/5D
"""
from .. import wrap_usecases
from .assign_control import assign_control
from .unassign_control import unassign_control
wrap_usecases(__path__, __name__)
__all__ = [
"assign_control",
"unassign_control",
]
@@ -0,0 +1,109 @@
# 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 Union
import ifcopenshell
import ifcopenshell.api.owner
import ifcopenshell.guid
def assign_control(
file: ifcopenshell.file,
relating_control: ifcopenshell.entity_instance,
related_objects: list[ifcopenshell.entity_instance],
) -> Union[ifcopenshell.entity_instance, None]:
"""Assigns a planning control or constraint to a list of objects.
IFC can describe concepts that control other objects. For example, a
planning calendar controls the availability of working days for
construction planning. As another example, a cost item might constrain
or limit the ability to procure and build a product.
This usecase lets you assign controls following the rules of the IFC
specification. This is an advanced topic and assumes knowledge of the
IFC concepts to determine what is allowed to control what. In the
future, this API will likely be deprecated in favour of multiple usecase
specific APIs.
:param relating_control: The IfcControl entity that is creating the
control or constraint
:param related_objects: The list of IfcObjectDefinition that is being controlled
:return: The newly created IfcRelAssignsToControl. If relationship already
existed before and wasn't changed then returns None.
Example:
.. code:: python
# One common usecase is to assign a calendar to a task
calendar = ifcopenshell.api.sequence.add_work_calendar(model)
schedule = ifcopenshell.api.sequence.add_work_schedule(model)
task = ifcopenshell.api.sequence.add_task(model,
work_schedule=schedule)
# All subtasks will inherit this calendar, so assigning a single
# calendar to the root task effectively defines a "default" calendar
ifcopenshell.api.control.assign_control(model,
relating_control=calendar, related_objects=[task])
# Another common example might be relating a cost item and a product
wall = ifcopenshell.api.root.create_entity(model, ifc_class="IfcWall")
schedule = ifcopenshell.api.cost.add_cost_schedule(model)
cost_item = ifcopenshell.api.cost.add_cost_item(model,
cost_schedule=schedule)
ifcopenshell.api.control.assign_control(model,
relating_control=cost_item, related_objects=[wall])
"""
# Filter out already assigned objects.
related_objects_set = set(related_objects)
objects_to_assign: set[ifcopenshell.entity_instance] = set()
control_assignments = set(relating_control.Controls)
if control_assignments:
for obj in related_objects_set:
existing_assignment = next((a for a in obj.HasAssignments if a in control_assignments), None)
# Skip objects already assigned to this control.
if existing_assignment:
continue
objects_to_assign.add(obj)
else:
objects_to_assign = related_objects_set
if not objects_to_assign:
return None
controls: Union[ifcopenshell.entity_instance, None]
controls = next(iter(relating_control.Controls), None)
if controls:
related_objects_new: list[ifcopenshell.entity_instance] = list(controls.RelatedObjects)
related_objects_new.extend(objects_to_assign)
controls.RelatedObjects = list(related_objects_new)
ifcopenshell.api.owner.update_owner_history(file, element=controls)
else:
controls = file.create_entity(
"IfcRelAssignsToControl",
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(file),
"RelatedObjects": list(objects_to_assign),
"RelatingControl": relating_control,
},
)
return controls
@@ -0,0 +1,65 @@
# 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_control(
file: ifcopenshell.file,
relating_control: ifcopenshell.entity_instance,
related_objects: list[ifcopenshell.entity_instance],
) -> None:
"""Unassigns a planning control or constraint to an object
:param relating_control: The IfcControl entity that is creating the
control or constraint
:param related_objects: The list IfcObjectDefinitions that is being controlled
:return: None
Example:
.. code:: python
# Let's relate a cost item and a product
wall = ifcopenshell.api.root.create_entity(model, ifc_class="IfcWall")
schedule = ifcopenshell.api.cost.add_cost_schedule(model)
cost_item = ifcopenshell.api.cost.add_cost_item(model,
cost_schedule=schedule)
ifcopenshell.api.control.assign_control(model,
relating_control=cost_item, related_objects=[wall])
# And now let's change our mind
ifcopenshell.api.control.unassign_control(model,
relating_control=cost_item, related_objects=[wall])
"""
related_objects_set = set(related_objects)
control_assignments = set(relating_control.Controls)
rels = set(rel for obj in related_objects_set for rel in obj.HasAssignments if rel in control_assignments)
for rel in rels:
related_objects_new = set(rel.RelatedObjects) - related_objects_set
if related_objects_new:
rel.RelatedObjects = list(related_objects_new)
ifcopenshell.api.owner.update_owner_history(file, element=rel)
else:
history = rel.OwnerHistory
file.remove(rel)
if history:
ifcopenshell.util.element.remove_deep2(file, history)