Fix a variety of IFC validation errors in entity creation and asset appending

This commit is contained in:
Dion Moult
2022-10-14 18:19:26 +11:00
parent 10bde73c1a
commit a34c0cb35c
9 changed files with 217 additions and 1395 deletions
@@ -79,4 +79,6 @@ class Usecase:
RelatedElement=self.settings["related_element"],
RelatingConnectionType=self.settings["relating_connection"],
RelatedConnectionType=self.settings["related_connection"],
RelatingPriorities=[],
RelatedPriorities=[],
)
@@ -66,14 +66,7 @@ class Usecase:
for e in self.file.traverse(element.HasRepresentation[0])
if e.is_a("IfcGeometricRepresentationContext")
]
for added_context in added_contexts:
equivalent_existing_context = self.get_equivalent_existing_context(added_context)
if not equivalent_existing_context:
equivalent_existing_context = self.create_equivalent_context(added_context)
for inverse in self.file.get_inverse(added_context):
ifcopenshell.util.element.replace_attribute(inverse, added_context, equivalent_existing_context)
for added_context in added_contexts:
ifcopenshell.util.element.remove_deep(self.file, added_context)
self.reuse_existing_contexts(added_contexts)
return element
def append_cost_schedule(self):
@@ -101,14 +94,7 @@ class Usecase:
self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext")
element = self.add_element(self.settings["element"])
added_contexts = [e for e in self.file.traverse(element) if e.is_a("IfcGeometricRepresentationContext")]
for added_context in added_contexts:
equivalent_existing_context = self.get_equivalent_existing_context(added_context)
if not equivalent_existing_context:
equivalent_existing_context = self.create_equivalent_context(added_context)
for inverse in self.file.get_inverse(added_context):
ifcopenshell.util.element.replace_attribute(inverse, added_context, equivalent_existing_context)
for added_context in added_contexts:
ifcopenshell.util.element.remove_deep(self.file, added_context)
self.reuse_existing_contexts(added_contexts)
return element
def append_product(self):
@@ -125,14 +111,7 @@ class Usecase:
self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext")
element = self.add_element(self.settings["element"])
added_contexts = [e for e in self.file.traverse(element) if e.is_a("IfcGeometricRepresentationContext")]
for added_context in added_contexts:
equivalent_existing_context = self.get_equivalent_existing_context(added_context)
if not equivalent_existing_context:
equivalent_existing_context = self.create_equivalent_context(added_context)
for inverse in self.file.get_inverse(added_context):
ifcopenshell.util.element.replace_attribute(inverse, added_context, equivalent_existing_context)
for added_context in added_contexts:
ifcopenshell.util.element.remove_deep2(self.file, added_context)
self.reuse_existing_contexts(added_contexts)
element_type = ifcopenshell.util.element.get_type(self.settings["element"])
if element_type:
@@ -159,6 +138,7 @@ class Usecase:
new = self.file.add(element)
self.added_elements[element.id()] = new
for subelement in self.settings["library"].traverse(element):
self.added_elements[subelement.id()] = self.file.add(subelement)
self.check_inverses(subelement)
return new
@@ -206,6 +186,16 @@ class Usecase:
return True
return False
def reuse_existing_contexts(self, added_contexts):
for added_context in added_contexts:
equivalent_existing_context = self.get_equivalent_existing_context(added_context)
if not equivalent_existing_context:
equivalent_existing_context = self.create_equivalent_context(added_context)
for inverse in self.file.get_inverse(added_context):
ifcopenshell.util.element.replace_attribute(inverse, added_context, equivalent_existing_context)
for added_context in added_contexts:
ifcopenshell.util.element.remove_deep2(self.file, added_context)
def get_equivalent_existing_context(self, added_context):
for context in self.existing_contexts:
if context.is_a() != added_context.is_a():
@@ -50,14 +50,46 @@ class Usecase:
element.ObjectType = self.settings["predefined_type"]
elif hasattr(element, "ElementType"):
element.ElementType = self.settings["predefined_type"]
elif hasattr(element, "ProcessType"):
element.ProcessType = self.settings["predefined_type"]
elif hasattr(element, "ObjectType"):
element.ObjectType = self.settings["predefined_type"]
if self.file.schema == "IFC2X3":
self.handle_2x3_defaults(element)
elif self.file.schema == "IFC4":
self.handle_4_defaults(element)
return element
def handle_2x3_defaults(self, element):
if element.is_a("IfcElement") or element.is_a("IfcElementType"):
if not element.PredefinedType:
element.PredefinedType = "NOTDEFINED"
if element.is_a("IfcSpatialStructureElement"):
element.CompositionType = "ELEMENT"
elif element.is_a("IfcRoof"):
element.ShapeType = "NOTDEFINED"
elif element.is_a("IfcFurnitureType"):
element.AssemblyPlace = "NOTDEFINED"
elif element.is_a("IfcDoorStyle") or element.is_a("IfcWindowStyle"):
element.OperationType = "NOTDEFINED"
element.ConstructionType = "NOTDEFINED"
element.ParameterTakesPrecedence = False
element.Sizeable = False
def handle_4_defaults(self, element):
if element.is_a("IfcElement") or element.is_a("IfcElementType"):
if not element.PredefinedType:
element.PredefinedType = "NOTDEFINED"
if element.is_a("IfcDoorStyle") or element.is_a("IfcWindowStyle"):
element.OperationType = "NOTDEFINED"
element.ConstructionType = "NOTDEFINED"
element.ParameterTakesPrecedence = False
element.Sizeable = False
elif element.is_a("IfcDoorType"):
element.OperationType = "NOTDEFINED"
elif element.is_a("IfcWindowType"):
element.PartitioningType = "NOTDEFINED"
elif element.is_a("IfcFurnitureType"):
element.AssemblyPlace = "NOTDEFINED"