mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-17 10:59:17 +00:00
Fix bug where removing a representation from a typed instance didn't remove all data users.
This commit is contained in:
@@ -96,3 +96,27 @@ def switch_representation(
|
||||
|
||||
if enable_dynamic_voids and geometry.is_body_representation(representation):
|
||||
geometry.create_dynamic_voids(obj)
|
||||
|
||||
|
||||
def remove_representation(ifc, geometry, obj=None, representation=None):
|
||||
element = ifc.get_entity(obj)
|
||||
if geometry.is_mapped_representation(representation) or geometry.is_type_product(element):
|
||||
type = geometry.get_element_type(element)
|
||||
representation = geometry.resolve_mapped_representation(representation)
|
||||
data = geometry.get_representation_data(representation)
|
||||
if data and geometry.has_data_users(data):
|
||||
for element in geometry.get_elements_of_type(type):
|
||||
obj = ifc.get_object(element)
|
||||
if obj:
|
||||
obj = geometry.replace_object_with_empty(obj)
|
||||
obj = ifc.get_object(type)
|
||||
if obj:
|
||||
obj = geometry.replace_object_with_empty(obj)
|
||||
ifc.run("geometry.unassign_representation", product=type, representation=representation)
|
||||
ifc.run("geometry.remove_representation", representation=representation)
|
||||
else:
|
||||
data = geometry.get_representation_data(representation)
|
||||
if data and geometry.has_data_users(data):
|
||||
geometry.replace_object_with_empty(obj)
|
||||
ifc.run("geometry.unassign_representation", product=element, representation=representation)
|
||||
ifc.run("geometry.remove_representation", representation=representation)
|
||||
|
||||
@@ -78,6 +78,8 @@ class Geometry:
|
||||
def does_object_have_mesh_with_faces(cls, obj): pass
|
||||
def duplicate_object_data(cls, obj): pass
|
||||
def get_cartesian_point_coordinate_offset(cls, obj): pass
|
||||
def get_element_type(cls, element): pass
|
||||
def get_elements_of_type(cls, type): pass
|
||||
def get_ifc_representation_class(cls, element, representation): pass
|
||||
def get_object_data(cls, obj): pass
|
||||
def get_object_materials_without_styles(cls, obj): pass
|
||||
@@ -85,10 +87,14 @@ class Geometry:
|
||||
def get_representation_data(cls, representation): pass
|
||||
def get_representation_name(cls, representation): pass
|
||||
def get_total_representation_items(cls, obj): pass
|
||||
def has_data_users(cls, data): pass
|
||||
def import_representation(cls, obj, representation, enable_dynamic_voids=False): pass
|
||||
def is_body_representation(cls, representation): pass
|
||||
def is_mapped_representation(cls, representation): pass
|
||||
def is_type_product(cls, element): pass
|
||||
def link(cls, element, obj): pass
|
||||
def rename_object(cls, obj, name): pass
|
||||
def replace_object_with_empty(cls, obj): pass
|
||||
def resolve_mapped_representation(cls, representation): pass
|
||||
def should_force_faceted_brep(cls): pass
|
||||
def should_force_triangulation(cls): pass
|
||||
|
||||
@@ -255,3 +255,56 @@ class TestSwitchRepresentation:
|
||||
enable_dynamic_voids=False,
|
||||
is_global=False,
|
||||
)
|
||||
|
||||
|
||||
class TestRemoveRepresentation:
|
||||
def test_removing_an_actively_used_mapped_representation_by_remapping_usages_to_an_empty(self, ifc, geometry):
|
||||
ifc.get_entity("obj").should_be_called().will_return("element")
|
||||
geometry.is_mapped_representation("mapped_rep").should_be_called().will_return(False)
|
||||
geometry.is_type_product("element").should_be_called().will_return(True)
|
||||
geometry.get_element_type("element").should_be_called().will_return("type")
|
||||
geometry.resolve_mapped_representation("mapped_rep").should_be_called().will_return("representation")
|
||||
geometry.get_representation_data("representation").should_be_called().will_return("data")
|
||||
geometry.has_data_users("data").should_be_called().will_return(True)
|
||||
geometry.get_elements_of_type("type").should_be_called().will_return(["element"])
|
||||
ifc.get_object("element").should_be_called().will_return("obj")
|
||||
geometry.replace_object_with_empty("obj").should_be_called()
|
||||
ifc.get_object("type").should_be_called().will_return("type_obj")
|
||||
geometry.replace_object_with_empty("type_obj").should_be_called()
|
||||
ifc.run("geometry.unassign_representation", product="type", representation="representation").should_be_called()
|
||||
ifc.run("geometry.remove_representation", representation="representation").should_be_called()
|
||||
subject.remove_representation(ifc, geometry, obj="obj", representation="mapped_rep")
|
||||
|
||||
def test_removing_an_unused_mapped_representation(self, ifc, geometry):
|
||||
ifc.get_entity("obj").should_be_called().will_return("element")
|
||||
geometry.is_mapped_representation("mapped_rep").should_be_called().will_return(True)
|
||||
geometry.get_element_type("element").should_be_called().will_return("type")
|
||||
geometry.resolve_mapped_representation("mapped_rep").should_be_called().will_return("representation")
|
||||
geometry.get_representation_data("representation").should_be_called().will_return(None)
|
||||
ifc.run("geometry.unassign_representation", product="type", representation="representation").should_be_called()
|
||||
ifc.run("geometry.remove_representation", representation="representation").should_be_called()
|
||||
subject.remove_representation(ifc, geometry, obj="obj", representation="mapped_rep")
|
||||
|
||||
def test_removing_an_actively_used_representation(self, ifc, geometry):
|
||||
ifc.get_entity("obj").should_be_called().will_return("element")
|
||||
geometry.is_mapped_representation("representation").should_be_called().will_return(False)
|
||||
geometry.is_type_product("element").should_be_called().will_return(False)
|
||||
geometry.get_representation_data("representation").should_be_called().will_return("data")
|
||||
geometry.has_data_users("data").should_be_called().will_return(True)
|
||||
geometry.replace_object_with_empty("obj").should_be_called()
|
||||
ifc.run(
|
||||
"geometry.unassign_representation", product="element", representation="representation"
|
||||
).should_be_called()
|
||||
ifc.run("geometry.remove_representation", representation="representation").should_be_called()
|
||||
subject.remove_representation(ifc, geometry, obj="obj", representation="representation")
|
||||
|
||||
def test_removing_an_unused_representation(self, ifc, geometry):
|
||||
ifc.get_entity("obj").should_be_called().will_return("element")
|
||||
geometry.is_mapped_representation("representation").should_be_called().will_return(False)
|
||||
geometry.is_type_product("element").should_be_called().will_return(False)
|
||||
geometry.get_representation_data("representation").should_be_called().will_return(None)
|
||||
ifc.run(
|
||||
"geometry.unassign_representation", product="element", representation="representation"
|
||||
).should_be_called()
|
||||
ifc.run("geometry.remove_representation", representation="representation").should_be_called()
|
||||
subject.remove_representation(ifc, geometry, obj="obj", representation="representation")
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import numpy
|
||||
import pytest
|
||||
import test.bootstrap
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.placement
|
||||
|
||||
|
||||
class TestUnassignRepresentation(test.bootstrap.IFC4):
|
||||
def test_unassigning_a_product_representation(self):
|
||||
representation = self.file.createIfcShapeRepresentation()
|
||||
representation2 = self.file.createIfcShapeRepresentation()
|
||||
wall = self.file.createIfcWall(
|
||||
Representation=self.file.createIfcProductDefinitionShape(Representations=[representation, representation2])
|
||||
)
|
||||
ifcopenshell.api.run("geometry.unassign_representation", self.file, product=wall, representation=representation)
|
||||
assert representation not in wall.Representation.Representations
|
||||
ifcopenshell.api.run(
|
||||
"geometry.unassign_representation", self.file, product=wall, representation=representation2
|
||||
)
|
||||
assert not wall.Representation
|
||||
assert len(self.file.by_type("IfcShapeRepresentation")) == 2
|
||||
assert len(self.file.by_type("IfcProductDefinitionShape")) == 0
|
||||
|
||||
def test_unassigning_a_type_product_representation(self):
|
||||
representation = self.file.createIfcShapeRepresentation()
|
||||
origin = self.file.createIfcAxis2Placement3D()
|
||||
repmap = self.file.createIfcRepresentationMap(MappedRepresentation=representation, MappingOrigin=origin)
|
||||
walltype = self.file.createIfcWallType(RepresentationMaps=[repmap])
|
||||
ifcopenshell.api.run(
|
||||
"geometry.unassign_representation", self.file, product=walltype, representation=representation
|
||||
)
|
||||
assert not walltype.RepresentationMaps
|
||||
assert len(self.file.by_type("IfcAxis2Placement3D")) == 0
|
||||
assert len(self.file.by_type("IfcRepresentationMap")) == 0
|
||||
assert len(self.file.by_type("IfcShapeRepresentation")) == 1
|
||||
|
||||
def test_unassigning_a_type_product_representation_used_by_instances(self):
|
||||
representation = self.file.createIfcShapeRepresentation()
|
||||
origin = self.file.createIfcAxis2Placement3D()
|
||||
repmap = self.file.createIfcRepresentationMap(MappedRepresentation=representation, MappingOrigin=origin)
|
||||
walltype = self.file.createIfcWallType(RepresentationMaps=[repmap])
|
||||
mapped_item = self.file.createIfcMappedItem(MappingSource=repmap)
|
||||
rep = self.file.createIfcShapeRepresentation(Items=[mapped_item])
|
||||
prodrep = self.file.createIfcProductDefinitionShape(Representations=[rep])
|
||||
wall = self.file.createIfcWall(Representation=prodrep)
|
||||
ifcopenshell.api.run(
|
||||
"geometry.unassign_representation", self.file, product=walltype, representation=representation
|
||||
)
|
||||
assert not walltype.RepresentationMaps
|
||||
assert len(self.file.by_type("IfcAxis2Placement3D")) == 0
|
||||
assert len(self.file.by_type("IfcRepresentationMap")) == 0
|
||||
assert len(self.file.by_type("IfcShapeRepresentation")) == 1
|
||||
assert not wall.Representation
|
||||
assert len(self.file.by_type("IfcProductDefinitionShape")) == 0
|
||||
Reference in New Issue
Block a user