From abe6dbdfc95f8d69fcf524f24c9ccedb1fa03d75 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 8 Apr 2024 14:45:47 +0500 Subject: [PATCH] layer.unassign_layer - support batching #4474 --- .../blenderbim/bim/module/layer/operator.py | 5 ++- .../ifcopenshell/api/layer/unassign_layer.py | 34 +++++++++++----- .../test/api/layer/test_unassign_layer.py | 39 +++++++++++++++++++ 3 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 src/ifcopenshell-python/test/api/layer/test_unassign_layer.py diff --git a/src/blenderbim/blenderbim/bim/module/layer/operator.py b/src/blenderbim/blenderbim/bim/module/layer/operator.py index ccdf666d60..70d1213586 100644 --- a/src/blenderbim/blenderbim/bim/module/layer/operator.py +++ b/src/blenderbim/blenderbim/bim/module/layer/operator.py @@ -176,7 +176,10 @@ class UnassignPresentationLayer(bpy.types.Operator): ifcopenshell.api.run( "layer.unassign_layer", self.file, - **{"item": self.file.by_id(item.BIMMeshProperties.ifc_definition_id), "layer": self.file.by_id(self.layer)} + **{ + "items": [self.file.by_id(item.BIMMeshProperties.ifc_definition_id)], + "layer": self.file.by_id(self.layer), + } ) return {"FINISHED"} diff --git a/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py b/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py index 4cb941d35e..657db6ac9e 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py @@ -16,16 +16,23 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: - def __init__(self, file, item=None, layer=None): - """Unassigns an item from a layer + def __init__( + self, file: ifcopenshell.file, items: list[ifcopenshell.entity_instance], layer: ifcopenshell.entity_instance + ): + """Unassigns representation items from a layer If the representation item isn't assigned to the layer, nothing will happen. + If after unassignment layer won't have any assigned items it will be + removed to keep IFC valid. - :param item: An IfcRepresentationItem element to unassign - :type item: ifcopenshell.entity_instance.entity_instance + :param items: A list IfcRepresentationItem elements to unassign + :type items: list[ifcopenshell.entity_instance.entity_instance] :param layer: The IfcPresentationLayerAssignment to unassign from :type layer: ifcopenshell.entity_instance.entity_instance :return: None @@ -57,15 +64,24 @@ class Usecase: ifcopenshell.api.run("layer.assign_layer", model, items=[representation.Items[0]], layer=layer) # Let's undo it! - ifcopenshell.api.run("layer.unassign_layer", model, item=representation.Items[0], layer=layer) + ifcopenshell.api.run("layer.unassign_layer", model, items=[representation.Items[0]], layer=layer) """ self.file = file self.settings = { - "item": item, + "items": items, "layer": layer, } def execute(self): - assigned_items = set(self.settings["layer"].AssignedItems) or set() - assigned_items.remove(self.settings["item"]) - self.settings["layer"].AssignedItems = list(assigned_items) + layer = self.settings["layer"] + assigned_items = set(layer.AssignedItems) or set() + items = set(self.settings["items"]) + if not items.issubset(assigned_items): + return + assigned_items = list(assigned_items - items) + + # keep IFC valid in case if there are no items left + if assigned_items: + layer.AssignedItems = assigned_items + else: + self.file.remove(layer) diff --git a/src/ifcopenshell-python/test/api/layer/test_unassign_layer.py b/src/ifcopenshell-python/test/api/layer/test_unassign_layer.py new file mode 100644 index 0000000000..7a29896500 --- /dev/null +++ b/src/ifcopenshell-python/test/api/layer/test_unassign_layer.py @@ -0,0 +1,39 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2022 Dion Moult +# +# 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 . + +import test.bootstrap +import ifcopenshell.api + + +class TestUnassignLayer(test.bootstrap.IFC4): + def test_unassign_layer_from_items(self): + items = [self.file.createIfcExtrudedAreaSolid() for i in range(3)] + layer = self.file.createIfcPresentationLayerAssignment() + + ifcopenshell.api.run("layer.assign_layer", self.file, items=items, layer=layer) + ifcopenshell.api.run("layer.unassign_layer", self.file, items=items[2:], layer=layer) + assert len(layer.AssignedItems) == 2 + assert set(layer.AssignedItems) == set(items[:2]) + + def test_remove_layer_if_all_items_are_unassigned(self): + items = [self.file.createIfcExtrudedAreaSolid() for i in range(3)] + layer = self.file.createIfcPresentationLayerAssignment() + + ifcopenshell.api.run("layer.assign_layer", self.file, items=items, layer=layer) + ifcopenshell.api.run("layer.unassign_layer", self.file, items=items, layer=layer) + assert not self.file.by_type("IfcPresentationLayerAssignment")