mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-03 13:28:19 +00:00
root.reassign_class to handle switching occurrence class <-> type class #5260
Kind of experimental. The idea is that it will reassign class e.g. from IfcWindow to IfcWindowType (or vice versa) and will keep the IFC representations and property sets. Example - https://imgur.com/a/X7MHR0s
This commit is contained in:
@@ -77,6 +77,7 @@ class DisableReassignClass(bpy.types.Operator):
|
|||||||
class ReassignClass(bpy.types.Operator):
|
class ReassignClass(bpy.types.Operator):
|
||||||
bl_idname = "bim.reassign_class"
|
bl_idname = "bim.reassign_class"
|
||||||
bl_label = "Reassign IFC Class"
|
bl_label = "Reassign IFC Class"
|
||||||
|
bl_description = "Reassign IFC class for selected objects"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
obj: bpy.props.StringProperty()
|
obj: bpy.props.StringProperty()
|
||||||
|
|
||||||
@@ -89,71 +90,71 @@ class ReassignClass(bpy.types.Operator):
|
|||||||
else:
|
else:
|
||||||
objects = set(context.selected_objects + [context.active_object])
|
objects = set(context.selected_objects + [context.active_object])
|
||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
predefined_type = context.scene.BIMRootProperties.ifc_predefined_type
|
root_props = context.scene.BIMRootProperties
|
||||||
|
ifc_product: str = root_props.ifc_product
|
||||||
|
ifc_class: str = root_props.ifc_class
|
||||||
|
type_ifc_class = next(iter(ifcopenshell.util.type.get_applicable_types(ifc_class)), None)
|
||||||
|
|
||||||
|
predefined_type = root_props.ifc_predefined_type
|
||||||
if predefined_type == "USERDEFINED":
|
if predefined_type == "USERDEFINED":
|
||||||
predefined_type = context.scene.BIMRootProperties.ifc_userdefined_type
|
predefined_type = root_props.ifc_userdefined_type
|
||||||
|
|
||||||
# NOTE: root.reassign_class
|
# NOTE: root.reassign_class
|
||||||
# automatically will reassign class for other occurrences of the type
|
# automatically will reassign class for other occurrences of the type
|
||||||
# so we need to run it only for the types or non-typed elements
|
# so we need to run it only for the types or non-typed elements
|
||||||
elements_to_reassign = set()
|
elements_to_reassign: dict[ifcopenshell.entity_instance, str] = dict()
|
||||||
# need to update blender object name
|
# need to update blender object name
|
||||||
# for all elements that were changed in the process
|
# for all elements that were changed in the process
|
||||||
elements_to_update = set()
|
elements_to_update: set[ifcopenshell.entity_instance] = set()
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
obj.BIMObjectProperties.is_reassigning_class = False
|
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
if element.is_a("IfcTypeObject"):
|
if not element:
|
||||||
elements_to_reassign.add(element)
|
|
||||||
elements_to_update.update(ifcopenshell.util.element.get_types(element))
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# check if element is typed
|
same_ifc_product = element.is_a(ifc_product)
|
||||||
element_type = ifcopenshell.util.element.get_type(element)
|
|
||||||
if element_type:
|
if not same_ifc_product:
|
||||||
elements_to_reassign.add(element_type)
|
if not (element.is_a("IfcElement") and ifc_product == "IfcElementType") and not (
|
||||||
|
element.is_a("IfcElementType") and ifc_product == "IfcElement"
|
||||||
|
):
|
||||||
|
self.report(
|
||||||
|
{"ERROR"}, f"Not supported class reassignment for object '{obj.name}' -> {ifc_product}."
|
||||||
|
)
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
obj.BIMObjectProperties.is_reassigning_class = False
|
||||||
|
if element.is_a("IfcTypeObject"):
|
||||||
|
elements_to_reassign[element] = ifc_class
|
||||||
|
elements_to_update.update(ifcopenshell.util.element.get_types(element))
|
||||||
|
continue
|
||||||
|
elif same_ifc_product and (element_type := ifcopenshell.util.element.get_type(element)):
|
||||||
|
assert type_ifc_class
|
||||||
|
elements_to_reassign[element_type] = type_ifc_class
|
||||||
elements_to_update.update(ifcopenshell.util.element.get_types(element_type))
|
elements_to_update.update(ifcopenshell.util.element.get_types(element_type))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# non-typed element
|
# non-typed element
|
||||||
elements_to_reassign.add(element)
|
elements_to_reassign[element] = ifc_class
|
||||||
|
|
||||||
# store elements to objects to update later as elements will get invalid
|
# store elements to objects to update later as elements will get invalid
|
||||||
# after class reassignment
|
# after class reassignment
|
||||||
elements_to_update = elements_to_update | elements_to_reassign
|
elements_to_update = elements_to_update | set(elements_to_reassign)
|
||||||
objects_to_update = set(o for e in elements_to_update if (o := tool.Ifc.get_object(e)))
|
objects_to_update = set(o for e in elements_to_update if (o := tool.Ifc.get_object(e)))
|
||||||
|
|
||||||
base_class = context.scene.BIMRootProperties.ifc_class
|
|
||||||
if context.scene.BIMRootProperties.ifc_product == "IfcElementType":
|
|
||||||
type_class = base_class
|
|
||||||
occurrence_classes = ifcopenshell.util.type.get_applicable_entities(type_class)
|
|
||||||
occurrence_class = None if len(occurrence_classes) == 0 else occurrence_classes[0]
|
|
||||||
else:
|
|
||||||
occurrence_class = base_class
|
|
||||||
type_classes = ifcopenshell.util.type.get_applicable_types(occurrence_class)
|
|
||||||
type_class = None if len(type_classes) == 0 else type_classes[0]
|
|
||||||
|
|
||||||
reassigned_elements = set()
|
reassigned_elements = set()
|
||||||
for element in elements_to_reassign:
|
for element, ifc_class_ in elements_to_reassign.items():
|
||||||
ifc_class = type_class if element.is_a("IfcTypeObject") else occurrence_class
|
|
||||||
if ifc_class is None:
|
|
||||||
self.report(
|
|
||||||
{"ERROR"},
|
|
||||||
f"Couldn't find valid class for reassigning element of class {element.is_a()} based on class {base_class}",
|
|
||||||
)
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
element = ifcopenshell.api.run(
|
element = ifcopenshell.api.run(
|
||||||
"root.reassign_class",
|
"root.reassign_class",
|
||||||
self.file,
|
self.file,
|
||||||
product=element,
|
product=element,
|
||||||
ifc_class=ifc_class,
|
ifc_class=ifc_class_,
|
||||||
predefined_type=predefined_type,
|
predefined_type=predefined_type,
|
||||||
)
|
)
|
||||||
reassigned_elements.add(element)
|
reassigned_elements.add(element)
|
||||||
|
|
||||||
for obj in objects_to_update:
|
for obj in objects_to_update:
|
||||||
obj.name = tool.Loader.get_name(tool.Ifc.get_entity(obj))
|
obj.name = tool.Loader.get_name(tool.Ifc.get_entity(obj))
|
||||||
|
tool.Collector.assign(obj)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -83,8 +83,7 @@ class BIM_PT_class(Panel):
|
|||||||
def draw_class_dropdowns(self, context, ifc_predefined_types, is_reassigning_class=False):
|
def draw_class_dropdowns(self, context, ifc_predefined_types, is_reassigning_class=False):
|
||||||
props = context.scene.BIMRootProperties
|
props = context.scene.BIMRootProperties
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
if not is_reassigning_class:
|
prop_with_search(layout, props, "ifc_product")
|
||||||
prop_with_search(layout, props, "ifc_product")
|
|
||||||
prop_with_search(layout, props, "ifc_class")
|
prop_with_search(layout, props, "ifc_class")
|
||||||
if ifc_predefined_types:
|
if ifc_predefined_types:
|
||||||
prop_with_search(layout, props, "ifc_predefined_type")
|
prop_with_search(layout, props, "ifc_predefined_type")
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ class TestSetObjectName(NewFile):
|
|||||||
|
|
||||||
|
|
||||||
class TestReassignClass(NewFile):
|
class TestReassignClass(NewFile):
|
||||||
def test_run(self):
|
def test_reassigning_multiple_occurrences_of_the_same_type(self):
|
||||||
bpy.context.scene.BIMProjectProperties.template_file = "IFC4 Demo Template.ifc"
|
bpy.context.scene.BIMProjectProperties.template_file = "IFC4 Demo Template.ifc"
|
||||||
bpy.ops.bim.create_project()
|
bpy.ops.bim.create_project()
|
||||||
ifc_file = tool.Ifc.get()
|
ifc_file = tool.Ifc.get()
|
||||||
|
|||||||
@@ -17,10 +17,16 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api.aggregate
|
||||||
|
import ifcopenshell.api.geometry
|
||||||
|
import ifcopenshell.api.spatial
|
||||||
|
import ifcopenshell.api.type
|
||||||
|
import ifcopenshell.guid
|
||||||
|
import ifcopenshell.util.representation
|
||||||
import ifcopenshell.util.type
|
import ifcopenshell.util.type
|
||||||
import ifcopenshell.util.schema
|
import ifcopenshell.util.schema
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
from typing import Optional
|
from typing import Optional, Union, Literal
|
||||||
|
|
||||||
|
|
||||||
def reassign_class(
|
def reassign_class(
|
||||||
@@ -46,15 +52,14 @@ def reassign_class(
|
|||||||
cannot be unambiguously derived, so you are required to manually check
|
cannot be unambiguously derived, so you are required to manually check
|
||||||
this.
|
this.
|
||||||
|
|
||||||
|
Reassigning type class to occurrence (and vice versa) is supported.
|
||||||
|
|
||||||
:param product: The IfcProduct that you want to change the class of.
|
:param product: The IfcProduct that you want to change the class of.
|
||||||
:type product: ifcopenshell.entity_instance
|
:type product: ifcopenshell.entity_instance
|
||||||
:param ifc_class: The new IFC class you want to change it to.
|
:param ifc_class: The new IFC class you want to change it to.
|
||||||
:type ifc_class: str,optional
|
|
||||||
:param predefined_type: In case you want to change the predefined type
|
:param predefined_type: In case you want to change the predefined type
|
||||||
too. User defined types are also allowed, just type what you want.
|
too. User defined types are also allowed, just type what you want.
|
||||||
:type predefined_type: str,optional
|
|
||||||
:return: The newly modified product.
|
:return: The newly modified product.
|
||||||
:rtype: ifcopenshell.entity_instance
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -80,38 +85,141 @@ def reassign_class(
|
|||||||
|
|
||||||
|
|
||||||
class Usecase:
|
class Usecase:
|
||||||
def execute(self):
|
file: ifcopenshell.file
|
||||||
element = self.reassign_class(self.settings["product"], self.settings["ifc_class"])
|
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
ifc_class: str = self.settings["ifc_class"]
|
||||||
|
product: ifcopenshell.entity_instance = self.settings["product"]
|
||||||
|
predefined_type: Union[str, None] = self.settings["predefined_type"]
|
||||||
|
|
||||||
|
was_type_product_before = product.is_a("IfcTypeProduct")
|
||||||
|
schema = ifcopenshell.schema_by_name(self.file.schema)
|
||||||
|
is_type_product_after = schema.declaration_by_name(ifc_class)._is("IfcTypeProduct")
|
||||||
|
|
||||||
|
if was_type_product_before == is_type_product_after:
|
||||||
|
return self.simple_reassignment(product, ifc_class, predefined_type)
|
||||||
|
|
||||||
|
switch_type = "occurrence_to_type" if is_type_product_after else "type_to_occurrence"
|
||||||
|
|
||||||
|
return self.switch_between_class_types(
|
||||||
|
product,
|
||||||
|
switch_type,
|
||||||
|
ifc_class,
|
||||||
|
predefined_type,
|
||||||
|
)
|
||||||
|
|
||||||
|
def switch_between_class_types(
|
||||||
|
self,
|
||||||
|
element: ifcopenshell.entity_instance,
|
||||||
|
switch_type: Literal["occurrence_to_type", "type_to_occurrence"],
|
||||||
|
ifc_class: str,
|
||||||
|
predefined_type: Union[str, None],
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
|
|
||||||
|
psets_to_reassign: list[ifcopenshell.entity_instance] = []
|
||||||
|
|
||||||
|
representations = list(ifcopenshell.util.representation.get_representations_iter(element))
|
||||||
|
for rep in representations:
|
||||||
|
if switch_type == "type_to_occurrence":
|
||||||
|
rep = ifcopenshell.util.representation.resolve_representation(rep)
|
||||||
|
ifcopenshell.api.geometry.unassign_representation(self.file, product=element, representation=rep)
|
||||||
|
|
||||||
|
if switch_type == "type_to_occurrence":
|
||||||
|
occurrences = ifcopenshell.util.element.get_types(element)
|
||||||
|
psets_to_reassign = element.HasPropertySets or []
|
||||||
|
|
||||||
|
element = self.reassign_class(element, ifc_class, predefined_type)
|
||||||
|
ifcopenshell.api.type.unassign_type(self.file, occurrences)
|
||||||
|
|
||||||
|
for pset in psets_to_reassign:
|
||||||
|
rel = self.file.create_entity(
|
||||||
|
"IfcRelDefinesByProperties",
|
||||||
|
GlobalId=ifcopenshell.guid.new(),
|
||||||
|
RelatedObjects=[element],
|
||||||
|
RelatingPropertyDefinition=pset,
|
||||||
|
)
|
||||||
|
else: # occurrence_to_type
|
||||||
|
element_type = ifcopenshell.util.element.get_type(element)
|
||||||
|
# Handle element type.
|
||||||
|
if element_type:
|
||||||
|
ifcopenshell.api.type.unassign_type(self.file, [element])
|
||||||
|
|
||||||
|
# Handle containers and aggregates.
|
||||||
|
if ifcopenshell.util.element.get_container(element):
|
||||||
|
ifcopenshell.api.spatial.unassign_container(self.file, [element])
|
||||||
|
elif ifcopenshell.util.element.get_aggregate(element):
|
||||||
|
ifcopenshell.api.aggregate.unassign_object(self.file, [element])
|
||||||
|
|
||||||
|
for rel in element.IsDefinedBy:
|
||||||
|
pset: ifcopenshell.entity_instance = rel.RelatingPropertyDefinition
|
||||||
|
objs = list(rel.RelatedObjects)
|
||||||
|
objs.remove(element)
|
||||||
|
if objs:
|
||||||
|
rel.RelatedObjects = objs
|
||||||
|
else:
|
||||||
|
history = getattr(rel, "OwnerHistory", None)
|
||||||
|
self.file.remove(rel)
|
||||||
|
if history:
|
||||||
|
ifcopenshell.util.element.remove_deep2(self.file, history)
|
||||||
|
psets_to_reassign.append(pset)
|
||||||
|
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
for pset_name in psets:
|
||||||
|
pset = self.file.by_id(psets[pset_name]["id"])
|
||||||
|
|
||||||
|
element = self.reassign_class(element, ifc_class, predefined_type)
|
||||||
|
|
||||||
|
# Reassign psets.
|
||||||
|
if psets_to_reassign:
|
||||||
|
element.HasPropertySets = psets_to_reassign
|
||||||
|
|
||||||
|
# Reassign representations.
|
||||||
|
for rep in representations:
|
||||||
|
ifcopenshell.api.geometry.assign_representation(self.file, product=element, representation=rep)
|
||||||
|
|
||||||
|
# Keep IFC valid.
|
||||||
|
if switch_type == "type_to_occurrence" and representations:
|
||||||
|
ifcopenshell.api.geometry.edit_object_placement(self.file, product=element)
|
||||||
|
|
||||||
|
return element
|
||||||
|
|
||||||
|
def simple_reassignment(
|
||||||
|
self,
|
||||||
|
element: ifcopenshell.entity_instance,
|
||||||
|
ifc_class: str,
|
||||||
|
predefined_type: Union[str, None],
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
|
element = self.reassign_class(element, ifc_class, predefined_type)
|
||||||
if element.is_a("IfcTypeProduct"):
|
if element.is_a("IfcTypeProduct"):
|
||||||
for occurrence in ifcopenshell.util.element.get_types(element) or []:
|
for occurrence in ifcopenshell.util.element.get_types(element):
|
||||||
ifc_class = ifcopenshell.util.type.get_applicable_entities(self.settings["ifc_class"])[0]
|
ifc_class_ = ifcopenshell.util.type.get_applicable_entities(ifc_class)[0]
|
||||||
self.reassign_class(occurrence, ifc_class)
|
self.reassign_class(occurrence, ifc_class_, predefined_type)
|
||||||
else:
|
else:
|
||||||
element_type = ifcopenshell.util.element.get_type(element)
|
element_type = ifcopenshell.util.element.get_type(element)
|
||||||
if element_type:
|
if element_type:
|
||||||
ifc_class = ifcopenshell.util.type.get_applicable_types(self.settings["ifc_class"])
|
ifc_class_ = next(iter(ifcopenshell.util.type.get_applicable_types(ifc_class)))
|
||||||
if ifc_class and len(ifc_class) == 1:
|
element_type = self.reassign_class(element_type, ifc_class_, predefined_type)
|
||||||
element_type = self.reassign_class(element_type, ifc_class[0])
|
|
||||||
ifc_class = element.is_a()
|
ifc_class = element.is_a()
|
||||||
for occurrence in ifcopenshell.util.element.get_types(element_type) or []:
|
for occurrence in ifcopenshell.util.element.get_types(element_type):
|
||||||
if occurrence == element:
|
if occurrence == element:
|
||||||
continue
|
continue
|
||||||
self.reassign_class(occurrence, ifc_class)
|
self.reassign_class(occurrence, ifc_class, predefined_type)
|
||||||
return element
|
return element
|
||||||
|
|
||||||
def reassign_class(self, element, ifc_class):
|
def reassign_class(
|
||||||
|
self, element: ifcopenshell.entity_instance, ifc_class: str, predefined_type: Union[str, None]
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
element = ifcopenshell.util.schema.reassign_class(self.file, element, ifc_class)
|
element = ifcopenshell.util.schema.reassign_class(self.file, element, ifc_class)
|
||||||
if self.settings["predefined_type"] and hasattr(element, "PredefinedType"):
|
if predefined_type and hasattr(element, "PredefinedType"):
|
||||||
try:
|
try:
|
||||||
element.PredefinedType = self.settings["predefined_type"]
|
element.PredefinedType = predefined_type
|
||||||
except:
|
except:
|
||||||
# PredefinedType wasn't in the respective enum, assume it's actually USERDEFINED
|
# PredefinedType wasn't in the respective enum, assume it's actually USERDEFINED
|
||||||
# and set .ElementType / .ObjectType to the provided predefined type
|
# and set .ElementType / .ObjectType to the provided predefined type
|
||||||
element.PredefinedType = "USERDEFINED"
|
element.PredefinedType = "USERDEFINED"
|
||||||
if element.is_a("IfcTypeProduct"):
|
if element.is_a("IfcTypeProduct"):
|
||||||
element.ElementType = self.settings["predefined_type"]
|
element.ElementType = predefined_type
|
||||||
else:
|
else:
|
||||||
element.ObjectType = self.settings["predefined_type"]
|
element.ObjectType = predefined_type
|
||||||
|
|
||||||
return element
|
return element
|
||||||
|
|||||||
@@ -16,9 +16,14 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import ifcopenshell.api.aggregate
|
||||||
|
import ifcopenshell.api.geometry
|
||||||
|
import ifcopenshell.api.spatial
|
||||||
|
import ifcopenshell.util.representation
|
||||||
import test.bootstrap
|
import test.bootstrap
|
||||||
import ifcopenshell.api.type
|
import ifcopenshell.api.pset
|
||||||
import ifcopenshell.api.root
|
import ifcopenshell.api.root
|
||||||
|
import ifcopenshell.api.type
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
@@ -95,6 +100,102 @@ class TestReassignClass(test.bootstrap.IFC4):
|
|||||||
assert len(self.file.by_type("IfcWall")) == 0
|
assert len(self.file.by_type("IfcWall")) == 0
|
||||||
assert len(self.file.by_type("IfcWallType")) == 0
|
assert len(self.file.by_type("IfcWallType")) == 0
|
||||||
|
|
||||||
|
# Switching between occurrence / type classes.
|
||||||
|
def test_unassign_type_from_occurrences_if_switching_from_type_class_to_occurrence_class(self):
|
||||||
|
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
element1 = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
ifcopenshell.api.type.assign_type(self.file, related_objects=[element1], relating_type=element_type)
|
||||||
|
element2 = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
ifcopenshell.api.type.assign_type(self.file, related_objects=[element2], relating_type=element_type)
|
||||||
|
|
||||||
|
element_type = ifcopenshell.api.root.reassign_class(self.file, product=element_type, ifc_class="IfcSlab")
|
||||||
|
|
||||||
|
# Type is unassigned.
|
||||||
|
assert ifcopenshell.util.element.get_type(element1) is None
|
||||||
|
assert ifcopenshell.util.element.get_type(element2) is None
|
||||||
|
assert len(self.file.by_type("IfcRelDefinesByType")) == 0
|
||||||
|
|
||||||
|
assert len(self.file.by_type("IfcWall")) == 2
|
||||||
|
assert len(self.file.by_type("IfcSlab")) == 1
|
||||||
|
|
||||||
|
def test_unassign_type_from_element_if_switching_from_occurrence_class_to_type_class(self):
|
||||||
|
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
ifcopenshell.api.type.assign_type(self.file, related_objects=[element], relating_type=element_type)
|
||||||
|
|
||||||
|
element = ifcopenshell.api.root.reassign_class(self.file, product=element, ifc_class="IfcSlabType")
|
||||||
|
|
||||||
|
# Type is unassigned.
|
||||||
|
assert ifcopenshell.util.element.get_types(element_type) == []
|
||||||
|
assert len(self.file.by_type("IfcRelDefinesByType")) == 0
|
||||||
|
|
||||||
|
assert len(self.file.by_type("IfcWallType")) == 1
|
||||||
|
assert len(self.file.by_type("IfcSlabType")) == 1
|
||||||
|
|
||||||
|
def test_unassigning_container_switching_from_occurrence_class_to_type_class(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
container = self.file.create_entity("IfcBuilding")
|
||||||
|
ifcopenshell.api.spatial.assign_container(self.file, products=[element], relating_structure=container)
|
||||||
|
element = ifcopenshell.api.root.reassign_class(self.file, product=element, ifc_class="IfcSlabType")
|
||||||
|
|
||||||
|
assert len(self.file.by_type("IfcRelContainedInSpatialStructure")) == 0
|
||||||
|
assert len(self.file.by_type("IfcWall")) == 0
|
||||||
|
assert len(self.file.by_type("IfcSlabType")) == 1
|
||||||
|
|
||||||
|
def test_unassigning_aggregate_switching_from_occurrence_class_to_type_class(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
aggregate = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcSlab")
|
||||||
|
ifcopenshell.api.aggregate.assign_object(self.file, products=[element], relating_object=aggregate)
|
||||||
|
element = ifcopenshell.api.root.reassign_class(self.file, product=element, ifc_class="IfcSlabType")
|
||||||
|
|
||||||
|
assert len(self.file.by_type("IfcRelAggregates")) == 0
|
||||||
|
assert len(self.file.by_type("IfcWall")) == 0
|
||||||
|
assert len(self.file.by_type("IfcSlabType")) == 1
|
||||||
|
|
||||||
|
def test_keeping_psets_switching_from_occurrence_class_to_type_class(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
pset = ifcopenshell.api.pset.add_pset(self.file, element, name="TestPset")
|
||||||
|
element = ifcopenshell.api.root.reassign_class(self.file, product=element, ifc_class="IfcSlabType")
|
||||||
|
|
||||||
|
assert ifcopenshell.util.element.get_pset(element, name="TestPset")["id"] == pset.id()
|
||||||
|
assert len(self.file.by_type("IfcRelDefinesByProperties")) == 0
|
||||||
|
assert len(self.file.by_type("IfcWall")) == 0
|
||||||
|
assert len(self.file.by_type("IfcSlabType")) == 1
|
||||||
|
|
||||||
|
def test_keeping_psets_switching_from_type_class_to_occurrence_class(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
pset = ifcopenshell.api.pset.add_pset(self.file, element, name="TestPset")
|
||||||
|
element = ifcopenshell.api.root.reassign_class(self.file, product=element, ifc_class="IfcSlab")
|
||||||
|
|
||||||
|
assert ifcopenshell.util.element.get_pset(element, name="TestPset")["id"] == pset.id()
|
||||||
|
assert len(self.file.by_type("IfcRelDefinesByProperties")) == 1
|
||||||
|
assert len(self.file.by_type("IfcWallType")) == 0
|
||||||
|
assert len(self.file.by_type("IfcSlab")) == 1
|
||||||
|
|
||||||
|
def test_keeping_representations_switching_from_occurrence_class_to_type_class(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
context = self.file.create_entity("IfcGeometricRepresentationContext")
|
||||||
|
representation = self.file.create_entity("IfcShapeRepresentation", ContextOfItems=context)
|
||||||
|
ifcopenshell.api.geometry.assign_representation(self.file, element, representation)
|
||||||
|
element = ifcopenshell.api.root.reassign_class(self.file, product=element, ifc_class="IfcSlabType")
|
||||||
|
|
||||||
|
assert ifcopenshell.util.representation.get_representation(element, context=context) == representation
|
||||||
|
assert len(self.file.by_type("IfcWall")) == 0
|
||||||
|
assert len(self.file.by_type("IfcSlabType")) == 1
|
||||||
|
|
||||||
|
def test_keeping_representations_switching_from_type_class_to_occurrence_class(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
context = self.file.create_entity("IfcGeometricRepresentationContext")
|
||||||
|
representation = self.file.create_entity("IfcShapeRepresentation", ContextOfItems=context)
|
||||||
|
representation.Items = [self.file.create_entity("IfcExtrudedAreaSolid")]
|
||||||
|
ifcopenshell.api.geometry.assign_representation(self.file, element, representation)
|
||||||
|
element = ifcopenshell.api.root.reassign_class(self.file, product=element, ifc_class="IfcSlab")
|
||||||
|
|
||||||
|
assert len(self.file.by_type("IfcRepresentationMap")) == 0
|
||||||
|
assert ifcopenshell.util.representation.get_representation(element, context=context) == representation
|
||||||
|
assert len(self.file.by_type("IfcWallType")) == 0
|
||||||
|
assert len(self.file.by_type("IfcSlab")) == 1
|
||||||
|
|
||||||
|
|
||||||
class TestReassignClassIFC2X3(test.bootstrap.IFC2X3, TestReassignClass):
|
class TestReassignClassIFC2X3(test.bootstrap.IFC2X3, TestReassignClass):
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user