geometry.remove_representation_item - add element argument

Use explicit element argument instead of props.representation_obj as representation_obj may not be there (e.g. removing rep items without item mode) or some other object might be in item mode and then booleans won't be unmarked.

Found the issue because of the failing test 🥳
This commit is contained in:
Andrej730
2025-04-02 18:24:56 +05:00
parent 156cca5932
commit 0315542237
4 changed files with 28 additions and 14 deletions
@@ -2509,11 +2509,12 @@ class RemoveRepresentationItem(bpy.types.Operator, tool.Ifc.Operator):
return True
def _execute(self, context):
obj = tool.Geometry.get_active_or_representation_obj()
assert (obj := tool.Geometry.get_active_or_representation_obj())
assert (element := tool.Ifc.get_entity(obj))
ifc_file = tool.Ifc.get()
representation_item = ifc_file.by_id(self.representation_item_id)
tool.Geometry.remove_representation_item(representation_item)
tool.Geometry.remove_representation_item(representation_item, element)
tool.Geometry.reload_representation(obj)
# reload items ui
+16 -8
View File
@@ -202,6 +202,7 @@ class Geometry(bonsai.core.tool.Geometry):
@classmethod
def delete_ifc_item(cls, obj: bpy.types.Object) -> None:
"""Delete IfcRepresentationItem's Object."""
props = tool.Geometry.get_geometry_props()
if len(props.item_objs) == 1:
return
@@ -212,7 +213,9 @@ class Geometry(bonsai.core.tool.Geometry):
mesh = obj.data
assert isinstance(mesh, bpy.types.Mesh)
item = tool.Ifc.get().by_id(tool.Geometry.get_mesh_props(mesh).ifc_definition_id)
cls.remove_representation_item(item)
rep_obj = props.representation_obj
assert (rep_obj := props.representation_obj) and (rep_element := tool.Ifc.get_entity(rep_obj))
cls.remove_representation_item(item, rep_element)
cls.reload_representation(props.representation_obj)
bpy.data.objects.remove(obj)
@@ -1344,12 +1347,19 @@ class Geometry(bonsai.core.tool.Geometry):
)
@classmethod
def remove_representation_item(cls, representation_item: ifcopenshell.entity_instance) -> None:
def remove_representation_item(
cls, representation_item: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance
) -> None:
"""Remove IfcRepresentationItem.
:param representation_item: item to remove.
:param element: item's element. Is used to unmark manual booleans.
"""
# NOTE: we assume it's not the last representation item
# otherwise we probably would need to remove representation too
# NOTE: a lot of shared code with `geometry.remove_representation`
ifc_file = tool.Ifc.get()
shape_aspects = []
shape_aspects: list[ifcopenshell.entity_instance] = []
consider_inverses = []
styled_item, colour, texture, layer = None, None, None, None
@@ -1366,7 +1376,7 @@ class Geometry(bonsai.core.tool.Geometry):
[consider_inverses.append(texture := t) for t in getattr(representation_item, "HasTextures", [])]
representation = None
boolean_results_to_remove = set()
boolean_results_to_remove: set[ifcopenshell.entity_instance] = set()
for inverse in ifc_file.get_inverse(representation_item):
if inverse.is_a("IfcShapeRepresentation"):
if inverse.OfShapeAspect:
@@ -1409,11 +1419,9 @@ class Geometry(bonsai.core.tool.Geometry):
also_consider = list(consider_inverses)
ifcopenshell.util.element.remove_deep2(ifc_file, representation_item, also_consider=also_consider)
props = tool.Geometry.get_geometry_props()
rep_element = tool.Ifc.get_entity(props.representation_obj)
tool.Model.unmark_manual_booleans(rep_element, [b.id() for b in boolean_results_to_remove])
tool.Model.unmark_manual_booleans(element, [b.id() for b in boolean_results_to_remove])
for boolean_result in boolean_results_to_remove:
cls.remove_representation_item(boolean_result)
cls.remove_representation_item(boolean_result, element)
@classmethod
def create_shape_aspect(
+6 -2
View File
@@ -687,8 +687,12 @@ class Model(bonsai.core.tool.Model):
@classmethod
def unmark_manual_booleans(cls, element: ifcopenshell.entity_instance, boolean_ids: list[int]) -> None:
# NOTE: we use use boolean_ids instead of boolean entities
# so it will be possible to unmark manual booleans after they already was deleted
"""Remove boolean ids from ``element``'s 'BBIM_Boolean' pset.
:param boolean_ids: List of boolean ids to remove.
Ids are used instead of entities to make it possible to unmark already removed booleans.
Provided ids may not be marked as manual booleans previously.
"""
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
if not pset:
return
+3 -2
View File
@@ -20,6 +20,7 @@ import bpy
import math
import numpy as np
import ifcopenshell
import ifcopenshell.api.geometry
import ifcopenshell.api.type
import bonsai.core.tool
import bonsai.tool as tool
@@ -606,13 +607,13 @@ class TestRemoveRepresentationItem(NewFile):
items = [ifc.createIfcExtrudedAreaSolid(), ifc.createIfcExtrudedAreaSolid()]
representation = ifc.createIfcShapeRepresentation(Items=items, ContextOfItems=context)
tool.Ifc.run("geometry.assign_representation", product=element, representation=representation)
ifcopenshell.api.geometry.assign_representation(ifc, product=element, representation=representation)
product_shape = element.Representation
shape_aspect = subject.create_shape_aspect(product_shape, representation, items[:1], None)
shape_aspect_id = shape_aspect.id()
subject.remove_representation_item(items[0])
subject.remove_representation_item(items[0], element)
assert tool.Ifc.get_entity_by_id(shape_aspect_id) is None
assert set(representation.Items) == {items[1]}