geometry.unassign_representation to remove shape aspects

previously it was leaving unused shape aspects unconnected to any other elements, now it will purge them
This commit is contained in:
Andrej730
2024-09-13 16:50:41 +05:00
parent aa289fd796
commit 8061e22480
2 changed files with 39 additions and 3 deletions
@@ -50,13 +50,16 @@ class Usecase:
return return
representations.remove(representation) representations.remove(representation)
if not representations: if not representations:
self.file.remove(product.Representation) product_def = product.Representation
# TODO: should somehow find matching shape aspect and remove it
# even before the last representation is removed.
self.process_shape_aspects(product_def)
self.file.remove(product_def)
else: else:
product.Representation.Representations = representations product.Representation.Representations = representations
def unassign_type_representation(self) -> None: def unassign_type_representation(self) -> None:
matching_representation_map = None matching_representation_map = None
representation_maps = self.settings["product"].RepresentationMaps or []
for representation_map in self.settings["product"].RepresentationMaps or []: for representation_map in self.settings["product"].RepresentationMaps or []:
if representation_map.MappedRepresentation == self.settings["representation"]: if representation_map.MappedRepresentation == self.settings["representation"]:
@@ -68,8 +71,26 @@ class Usecase:
self.settings["product"].RepresentationMaps = [ self.settings["product"].RepresentationMaps = [
rm for rm in self.settings["product"].RepresentationMaps if rm != matching_representation_map rm for rm in self.settings["product"].RepresentationMaps if rm != matching_representation_map
] or None ] or None
self.process_shape_aspects(matching_representation_map)
self.remove_representation_map_only(matching_representation_map) self.remove_representation_map_only(matching_representation_map)
def process_shape_aspects(self, product_representation: ifcopenshell.entity_instance) -> None:
# Technically IfcShapeAspect doesn't become invalid when product representation is removed,
# but shape aspect makes sense only in context of some other representation.
if self.file.schema == "IFC2X3" and product_representation.is_a("IfcRepresentationMap"):
shape_aspects = [
a
for a in self.file.by_type("IfcShapeAspect")
if a.PartOfProductDefinitionShape == product_representation
]
else:
shape_aspects = product_representation.HasShapeAspects
for shape_aspect in shape_aspects:
representations = shape_aspect.ShapeRepresentations
self.file.remove(shape_aspect)
for rep in representations:
ifcopenshell.api.geometry.remove_representation(self.file, rep)
def remove_representation_map_only(self, representation_map: ifcopenshell.entity_instance) -> None: def remove_representation_map_only(self, representation_map: ifcopenshell.entity_instance) -> None:
representation_map.MappedRepresentation = self.file.createIfcShapeRepresentation() representation_map.MappedRepresentation = self.file.createIfcShapeRepresentation()
ifcopenshell.util.element.remove_deep2(self.file, representation_map) ifcopenshell.util.element.remove_deep2(self.file, representation_map)
@@ -25,26 +25,41 @@ class TestUnassignRepresentation(test.bootstrap.IFC4):
def test_unassigning_a_product_representation(self): def test_unassigning_a_product_representation(self):
representation = self.file.createIfcShapeRepresentation() representation = self.file.createIfcShapeRepresentation()
representation2 = self.file.createIfcShapeRepresentation() representation2 = self.file.createIfcShapeRepresentation()
item = self.file.create_entity("IfcExtrudedAreaSolid")
representation2.Items = (item,)
wall = self.file.createIfcWall( wall = self.file.createIfcWall(
Representation=self.file.createIfcProductDefinitionShape(Representations=[representation, representation2]) Representation=self.file.createIfcProductDefinitionShape(Representations=[representation, representation2])
) )
shape_aspect = self.file.create_entity("IfcShapeAspect")
shape_aspect.ShapeRepresentations = (self.file.createIfcShapeRepresentation(Items=(item,)),)
shape_aspect.PartOfProductDefinitionShape = wall.Representation
ifcopenshell.api.geometry.unassign_representation(self.file, product=wall, representation=representation) ifcopenshell.api.geometry.unassign_representation(self.file, product=wall, representation=representation)
assert representation not in wall.Representation.Representations assert representation not in wall.Representation.Representations
ifcopenshell.api.geometry.unassign_representation(self.file, product=wall, representation=representation2) ifcopenshell.api.geometry.unassign_representation(self.file, product=wall, representation=representation2)
assert not wall.Representation assert not wall.Representation
assert len(self.file.by_type("IfcShapeRepresentation")) == 2 assert len(self.file.by_type("IfcShapeRepresentation")) == 2
assert len(self.file.by_type("IfcProductDefinitionShape")) == 0 assert len(self.file.by_type("IfcProductDefinitionShape")) == 0
assert len(self.file.by_type("IfcShapeAspect")) == 0
def test_unassigning_a_type_product_representation(self): def test_unassigning_a_type_product_representation(self):
representation = self.file.createIfcShapeRepresentation() item = self.file.create_entity("IfcExtrudedAreaSolid")
representation = self.file.createIfcShapeRepresentation(Items=(item,))
origin = self.file.createIfcAxis2Placement3D() origin = self.file.createIfcAxis2Placement3D()
repmap = self.file.createIfcRepresentationMap(MappedRepresentation=representation, MappingOrigin=origin) repmap = self.file.createIfcRepresentationMap(MappedRepresentation=representation, MappingOrigin=origin)
walltype = self.file.createIfcWallType(RepresentationMaps=[repmap]) walltype = self.file.createIfcWallType(RepresentationMaps=[repmap])
shape_aspect = self.file.create_entity("IfcShapeAspect")
shape_aspect.ShapeRepresentations = (self.file.createIfcShapeRepresentation(Items=(item,)),)
shape_aspect.PartOfProductDefinitionShape = repmap
ifcopenshell.api.geometry.unassign_representation(self.file, product=walltype, representation=representation) ifcopenshell.api.geometry.unassign_representation(self.file, product=walltype, representation=representation)
assert not walltype.RepresentationMaps assert not walltype.RepresentationMaps
assert len(self.file.by_type("IfcAxis2Placement3D")) == 0 assert len(self.file.by_type("IfcAxis2Placement3D")) == 0
assert len(self.file.by_type("IfcRepresentationMap")) == 0 assert len(self.file.by_type("IfcRepresentationMap")) == 0
assert len(self.file.by_type("IfcShapeRepresentation")) == 1 assert len(self.file.by_type("IfcShapeRepresentation")) == 1
assert len(self.file.by_type("IfcShapeAspect")) == 0
def test_unassigning_a_type_product_representation_used_by_instances(self): def test_unassigning_a_type_product_representation_used_by_instances(self):
representation = self.file.createIfcShapeRepresentation() representation = self.file.createIfcShapeRepresentation()