Roundtripping geometry now works for one to many styled item relationships

This commit is contained in:
Dion Moult
2020-11-26 21:31:42 +11:00
parent e346d5e3c6
commit 15ea15d9ab
4 changed files with 51 additions and 28 deletions
@@ -269,6 +269,7 @@ if bpy is not None:
prop.BIMObjectProperties,
prop.BIMMaterialProperties,
prop.SweptSolid,
prop.ItemSlotMap,
prop.BIMMeshProperties,
prop.BIMCameraProperties,
prop.BIMTextProperties,
@@ -1323,6 +1323,7 @@ class IfcExporter:
self.template_file = "{}template.ifc".format(ifc_export_settings.schema_dir)
self.ifc_export_settings = ifc_export_settings
self.ifc_parser = ifc_parser
self.roundtrip_id_map = {}
def export(self, selected_objects):
self.schema_version = self.ifc_export_settings.schema
@@ -2002,27 +2003,41 @@ class IfcExporter:
def create_styled_items(self):
for styled_item in self.ifc_parser.styled_items:
product = self.ifc_parser.products[
self.ifc_parser.get_product_index_from_raw_name(styled_item["related_product_name"])
]
material_slots = {}
if product["ifc"].Representation:
# This is a simplification, which works since we are currently in a controlled environment where the
# BlenderBIM Add-on controls how data is structured during export. When we implement full IFC
# round-tripping, this simplification can no longer apply.
for representation in product["ifc"].Representation.Representations:
# At the moment, until we implement full support for round-tripping contexts, we assume that styled
# items only apply to the body context. This is therefore an incomplete implementation and may break
# in edge cases.
if representation.RepresentationIdentifier != "Body":
continue
for i, item in enumerate(self.get_geometric_representation_items(representation)):
if i >= len(product["raw"].material_slots):
i = 0
material_slots[product["raw"].material_slots[i].name] = item
for styled_item_name, representation_item in material_slots.items():
if styled_item_name == styled_item["attributes"]["Name"]:
styled_item["ifc"] = self.create_styled_item(styled_item, representation_item)
self.process_styled_item(styled_item)
def process_styled_item(self, styled_item):
product = self.ifc_parser.products[
self.ifc_parser.get_product_index_from_raw_name(styled_item["related_product_name"])
]
if not product["ifc"].Representation:
return
material_slots = []
# This is a simplification, which works since we are currently in a controlled environment where the
# BlenderBIM Add-on controls how data is structured during export. When we implement full IFC
# round-tripping, this simplification can no longer apply.
for representation in product["ifc"].Representation.Representations:
# At the moment, until we implement full support for round-tripping contexts, we assume that styled
# items only apply to the body context. This is therefore an incomplete implementation and may break
# in edge cases.
if representation.RepresentationIdentifier != "Body":
continue
if product["raw"].data.BIMMeshProperties.ifc_definition_id:
# For native roundtripping, each slot could be a one to many relationship to items
for item in self.get_geometric_representation_items(representation):
original_id = self.roundtrip_id_map[item.id()]
i = product["raw"].data.BIMMeshProperties.ifc_item_ids.get(str(original_id)).slot_index
material_slots.append((product["raw"].material_slots[i].name, item))
else:
# For Blender, each slot represents a geometric representation item
for i, item in enumerate(self.get_geometric_representation_items(representation)):
if i >= len(product["raw"].material_slots):
i = 0
material_slots.append((product["raw"].material_slots[i].name, item))
for styled_item_name, representation_item in material_slots:
if styled_item_name == styled_item["attributes"]["Name"]:
styled_item["ifc"] = self.create_styled_item(styled_item, representation_item)
def get_geometric_representation_items(self, representation):
results = []
@@ -2389,6 +2404,8 @@ class IfcExporter:
added_element = migrator.migrate(element, self.file)
if added_element.is_a("IfcGeometricRepresentationContext"):
substitutions["contexts"].append(added_element)
elif added_element.is_a("IfcGeometricRepresentationItem"):
self.roundtrip_id_map[added_element.id()] = element.id()
for element in substitutions["contexts"]:
new_element = self.ifc_rep_context[representation["context"]][representation["subcontext"]][
@@ -38,13 +38,11 @@ class MaterialCreator:
def __init__(self, ifc_import_settings, ifc_importer):
self.mesh = None
self.materials = {}
self.current_object_styles = []
self.parsed_meshes = []
self.ifc_import_settings = ifc_import_settings
self.ifc_importer = ifc_importer
def create(self, element, obj, mesh):
self.current_object_styles = []
self.obj = obj
self.mesh = mesh
if (hasattr(element, "Representation") and not element.Representation) or (
@@ -84,10 +82,14 @@ class MaterialCreator:
if not item.StyledByItem:
return
item_id = self.mesh.BIMMeshProperties.ifc_item_ids.add()
item_id.name = str(item.id())
styled_item = item.StyledByItem[0]
style_name = self.get_style_name(styled_item)
if style_name in self.current_object_styles:
if self.mesh.materials.get(style_name):
item_id.slot_index = self.mesh.materials.find(style_name)
return True
style = bpy.data.materials.get(style_name)
@@ -97,8 +99,7 @@ class MaterialCreator:
self.parse_styled_item(styled_item, style)
self.assign_style_to_mesh(style)
item_id = self.mesh.BIMMeshProperties.ifc_item_ids.add()
item_id.name = str(item.id())
item_id.slot_index = len(self.mesh.materials) - 1
return True
def assign_material_slots_to_faces(self, obj):
@@ -327,7 +328,6 @@ class MaterialCreator:
if not self.mesh:
return
self.mesh.materials.append(material)
self.current_object_styles.append(material.name)
class IfcImporter:
+6 -1
View File
@@ -1716,6 +1716,11 @@ class RepresentationItem(PropertyGroup):
vgroup: StringProperty(name="Vertex Group")
class ItemSlotMap(PropertyGroup):
name: StringProperty(name="Item Element ID")
slot_index: IntProperty(name="Material Slot Index")
class BIMMeshProperties(PropertyGroup):
is_native: BoolProperty(name="Is Native", default=False)
is_swept_solid: BoolProperty(name="Is Swept Solid")
@@ -1727,4 +1732,4 @@ class BIMMeshProperties(PropertyGroup):
ifc_parameters: CollectionProperty(name="IFC Parameters", type=IfcParameter)
active_representation_item_index: IntProperty(name="Active Representation Item Index")
presentation_layer_index: IntProperty(name="Presentation Layer Index", default=-1)
ifc_item_ids: CollectionProperty(name="IFC Definition ID", type=StrProperty)
ifc_item_ids: CollectionProperty(name="IFC Definition ID", type=ItemSlotMap)