mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
document.assign_document - support batching #4474
This commit is contained in:
@@ -17,11 +17,19 @@
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
from typing import Union
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, product=None, document=None):
|
||||
"""Assigns a document to a product
|
||||
def __init__(
|
||||
self,
|
||||
file: ifcopenshell.file,
|
||||
products: list[ifcopenshell.entity_instance],
|
||||
document: ifcopenshell.entity_instance,
|
||||
):
|
||||
"""Assigns a document to a list of products
|
||||
|
||||
An object may be assigned to zero, one, or multiple documents. Almost
|
||||
any object or property may be assigned to a document, though typically
|
||||
@@ -32,14 +40,16 @@ class Usecase:
|
||||
consistent with other external relationships (such as classification
|
||||
systems or libraries).
|
||||
|
||||
:param product: The object to associate the document to. This could be
|
||||
:param product: The list of objects to associate the document to. This could be
|
||||
almost any sensible object in IFC.
|
||||
:type product: ifcopenshell.entity_instance.entity_instance
|
||||
:type product: list[ifcopenshell.entity_instance.entity_instance]
|
||||
:param document: The IfcDocumentReference to associate to, or
|
||||
alternatively an IfcDocumentInformation, though this is not
|
||||
recommended.
|
||||
:type document: ifcopenshell.entity_instance.entity_instance
|
||||
:return: The IfcRelAssociatesDocument relationship
|
||||
or `None` if `products` was an empty list or all products were
|
||||
already assigned to the `document`.
|
||||
:rtype: ifcopenshell.entity_instance.entity_instance
|
||||
|
||||
Example:
|
||||
@@ -54,42 +64,51 @@ class Usecase:
|
||||
reference = ifcopenshell.api.run("document.add_reference", model, information=document)
|
||||
|
||||
# Let's imagine storey represents an IfcBuildingStorey for the ground floor
|
||||
ifcopenshell.api.run("document.assign_document", model, product=storey, document=reference)
|
||||
ifcopenshell.api.run("document.assign_document", model, products=[storey], document=reference)
|
||||
"""
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"product": product,
|
||||
"products": products,
|
||||
"document": document,
|
||||
}
|
||||
|
||||
def execute(self):
|
||||
rel = self.get_document_rel()
|
||||
related_objects = set(rel.RelatedObjects) if rel.RelatedObjects else set()
|
||||
related_objects.add(self.settings["product"])
|
||||
rel.RelatedObjects = list(related_objects)
|
||||
def execute(self) -> Union[ifcopenshell.entity_instance, None]:
|
||||
# TODO: do we need to support non-ifcroot elements like we do in classification.add_reference?
|
||||
# NOTE: reuses code from `library.assign_reference`
|
||||
|
||||
referenced_elements = ifcopenshell.util.element.get_referenced_elements(self.settings["document"])
|
||||
products: set[ifcopenshell.entity_instance] = set(self.settings["products"])
|
||||
products = products - referenced_elements
|
||||
|
||||
if not products:
|
||||
return
|
||||
|
||||
def get_document_rel(self):
|
||||
if self.file.schema == "IFC2X3":
|
||||
for rel in self.file.by_type("IfcRelAssociatesDocument"):
|
||||
if rel.RelatingDocument == self.settings["document"]:
|
||||
return rel
|
||||
rel = next(
|
||||
(
|
||||
r
|
||||
for r in self.file.by_type("IfcRelAssociatesDocument")
|
||||
if r.RelatingDocument == self.settings["document"]
|
||||
),
|
||||
None,
|
||||
)
|
||||
else:
|
||||
if (
|
||||
hasattr(self.settings["document"], "DocumentRefForObjects")
|
||||
and self.settings["document"].DocumentRefForObjects
|
||||
):
|
||||
return self.settings["document"].DocumentRefForObjects[0]
|
||||
elif (
|
||||
hasattr(self.settings["document"], "DocumentInfoForObjects")
|
||||
and self.settings["document"].DocumentInfoForObjects
|
||||
):
|
||||
return self.settings["document"].DocumentInfoForObjects[0]
|
||||
ifc_class = self.settings["document"].is_a()
|
||||
if ifc_class == "IfcDocumentReference":
|
||||
rel = next(iter(self.settings["document"].DocumentRefForObjects), None)
|
||||
elif ifc_class == "IfcDocumentInformation":
|
||||
rel = next(iter(self.settings["document"].DocumentInfoForObjects), None)
|
||||
|
||||
return self.file.create_entity(
|
||||
"IfcRelAssociatesDocument",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
"RelatingDocument": self.settings["document"],
|
||||
}
|
||||
)
|
||||
if not rel:
|
||||
return self.file.create_entity(
|
||||
"IfcRelAssociatesDocument",
|
||||
GlobalId=ifcopenshell.guid.new(),
|
||||
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", self.file),
|
||||
RelatedObjects=list(products),
|
||||
RelatingDocument=self.settings["document"],
|
||||
)
|
||||
|
||||
related_objects = set(rel.RelatedObjects) | products
|
||||
rel.RelatedObjects = list(related_objects)
|
||||
ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel)
|
||||
return rel
|
||||
|
||||
@@ -45,7 +45,7 @@ class Usecase:
|
||||
reference = ifcopenshell.api.run("document.add_reference", model, information=document)
|
||||
|
||||
# Let's imagine storey represents an IfcBuildingStorey for the ground floor
|
||||
ifcopenshell.api.run("document.assign_document", model, product=storey, document=reference)
|
||||
ifcopenshell.api.run("document.assign_document", model, products=[storey], document=reference)
|
||||
|
||||
# Now let's change our mind and remove the association
|
||||
ifcopenshell.api.run("document.unassign_document", model, product=storey, document=reference)
|
||||
|
||||
Reference in New Issue
Block a user