mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-06 20:36:27 +00:00
Skip loading mappings if representation has openings #5405
To avoid errors
This commit is contained in:
@@ -50,7 +50,11 @@ class MaterialCreator:
|
|||||||
self.ifc_importer = ifc_importer
|
self.ifc_importer = ifc_importer
|
||||||
|
|
||||||
def create(
|
def create(
|
||||||
self, element: ifcopenshell.entity_instance, obj: bpy.types.Object, mesh: Union[OBJECT_DATA_TYPE, None]
|
self,
|
||||||
|
element: ifcopenshell.entity_instance,
|
||||||
|
obj: bpy.types.Object,
|
||||||
|
mesh: Union[OBJECT_DATA_TYPE, None],
|
||||||
|
shape_has_openings: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
if ((rep := getattr(element, "Representation", ...) is not ...) and not rep) or (
|
if ((rep := getattr(element, "Representation", ...) is not ...) and not rep) or (
|
||||||
(rep := getattr(element, "RepresentationMaps", ...) is not ...) and not rep
|
(rep := getattr(element, "RepresentationMaps", ...) is not ...) and not rep
|
||||||
@@ -78,7 +82,7 @@ class MaterialCreator:
|
|||||||
# Though 0 value will not occur as we don't use default materials in IfcImporter.
|
# Though 0 value will not occur as we don't use default materials in IfcImporter.
|
||||||
|
|
||||||
self.parsed_meshes.add(self.mesh.name)
|
self.parsed_meshes.add(self.mesh.name)
|
||||||
self.load_texture_maps()
|
self.load_texture_maps(shape_has_openings)
|
||||||
self.assign_material_slots_to_faces()
|
self.assign_material_slots_to_faces()
|
||||||
tool.Geometry.record_object_materials(obj)
|
tool.Geometry.record_object_materials(obj)
|
||||||
del self.mesh["ios_materials"]
|
del self.mesh["ios_materials"]
|
||||||
@@ -104,13 +108,15 @@ class MaterialCreator:
|
|||||||
print(f"WARNING. IfcTextureMap texture coordinates is not supported.")
|
print(f"WARNING. IfcTextureMap texture coordinates is not supported.")
|
||||||
return
|
return
|
||||||
|
|
||||||
def load_texture_maps(self) -> None:
|
def load_texture_maps(self, shape_has_openings: bool) -> None:
|
||||||
for style_or_material_id in self.mesh["ios_materials"]:
|
for style_or_material_id in self.mesh["ios_materials"]:
|
||||||
if not (material := self.styles.get(style_or_material_id)):
|
if not (material := self.styles.get(style_or_material_id)):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
material = self.styles[style_or_material_id]
|
material = self.styles[style_or_material_id]
|
||||||
if coords := self.get_ifc_coordinate(material):
|
if coords := self.get_ifc_coordinate(material):
|
||||||
|
if shape_has_openings and coords.is_a("IfcIndexedTextureMap"):
|
||||||
|
continue
|
||||||
tool.Loader.load_indexed_map(coords, self.mesh)
|
tool.Loader.load_indexed_map(coords, self.mesh)
|
||||||
|
|
||||||
def assign_material_slots_to_faces(self) -> None:
|
def assign_material_slots_to_faces(self) -> None:
|
||||||
@@ -586,7 +592,7 @@ class IfcImporter:
|
|||||||
break
|
break
|
||||||
obj = bpy.data.objects.new(tool.Loader.get_name(element), mesh)
|
obj = bpy.data.objects.new(tool.Loader.get_name(element), mesh)
|
||||||
self.link_element(element, obj)
|
self.link_element(element, obj)
|
||||||
self.material_creator.create(element, obj, mesh)
|
self.material_creator.create(element, obj, mesh, False)
|
||||||
self.type_products[element.GlobalId] = obj
|
self.type_products[element.GlobalId] = obj
|
||||||
|
|
||||||
def create_native_elements(self):
|
def create_native_elements(self):
|
||||||
@@ -850,7 +856,7 @@ class IfcImporter:
|
|||||||
def create_product(
|
def create_product(
|
||||||
self,
|
self,
|
||||||
element: ifcopenshell.entity_instance,
|
element: ifcopenshell.entity_instance,
|
||||||
shape: Optional[Any] = None,
|
shape: Optional[Union[ifcopenshell.geom.ShapeElementType, ifcopenshell.geom.ShapeType]] = None,
|
||||||
mesh: Optional[OBJECT_DATA_TYPE] = None,
|
mesh: Optional[OBJECT_DATA_TYPE] = None,
|
||||||
) -> Union[bpy.types.Object, None]:
|
) -> Union[bpy.types.Object, None]:
|
||||||
if element is None:
|
if element is None:
|
||||||
@@ -886,12 +892,12 @@ class IfcImporter:
|
|||||||
mat = np.array(shape.transformation.matrix).reshape((4, 4), order="F")
|
mat = np.array(shape.transformation.matrix).reshape((4, 4), order="F")
|
||||||
self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, mat))
|
self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, mat))
|
||||||
assert mesh # Type checker.
|
assert mesh # Type checker.
|
||||||
self.material_creator.create(element, obj, mesh)
|
self.material_creator.create(element, obj, mesh, tool.Geometry.does_shape_has_openings(shape))
|
||||||
elif mesh:
|
elif mesh: # When does this occur?
|
||||||
self.set_matrix_world(
|
self.set_matrix_world(
|
||||||
obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, self.get_element_matrix(element))
|
obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, self.get_element_matrix(element))
|
||||||
)
|
)
|
||||||
self.material_creator.create(element, obj, mesh)
|
self.material_creator.create(element, obj, mesh, False)
|
||||||
elif hasattr(element, "ObjectPlacement"):
|
elif hasattr(element, "ObjectPlacement"):
|
||||||
self.set_matrix_world(
|
self.set_matrix_world(
|
||||||
obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, self.get_element_matrix(element))
|
obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, self.get_element_matrix(element))
|
||||||
@@ -1383,9 +1389,9 @@ class IfcImporter:
|
|||||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||||
mesh.update()
|
mesh.update()
|
||||||
|
|
||||||
# TODO: geometry id is not always an int.
|
rep_str: str = geometry.id
|
||||||
rep_id = geometry.id
|
if "openings" not in rep_str:
|
||||||
if rep_id.isdigit():
|
rep_id = rep_str.split("-", 1)[0]
|
||||||
rep = self.file.by_id(int(rep_id))
|
rep = self.file.by_id(int(rep_id))
|
||||||
tool.Loader.load_indexed_colour_map(rep, mesh)
|
tool.Loader.load_indexed_colour_map(rep, mesh)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -646,12 +646,20 @@ class Geometry(bonsai.core.tool.Geometry):
|
|||||||
elif shape:
|
elif shape:
|
||||||
mesh = ifc_importer.create_mesh(element, shape)
|
mesh = ifc_importer.create_mesh(element, shape)
|
||||||
ifc_importer.material_creator.load_existing_materials()
|
ifc_importer.material_creator.load_existing_materials()
|
||||||
ifc_importer.material_creator.create(element, obj, mesh)
|
shape_has_openings = cls.does_shape_has_openings(shape)
|
||||||
|
ifc_importer.material_creator.create(element, obj, mesh, shape_has_openings)
|
||||||
mesh.BIMMeshProperties.has_openings_applied = apply_openings
|
mesh.BIMMeshProperties.has_openings_applied = apply_openings
|
||||||
tool.Loader.load_indexed_colour_map(representation, mesh)
|
if not shape_has_openings:
|
||||||
|
tool.Loader.load_indexed_colour_map(representation, mesh)
|
||||||
|
|
||||||
return mesh
|
return mesh
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def does_shape_has_openings(
|
||||||
|
cls, shape: Union[ifcopenshell.geom.ShapeElementType, ifcopenshell.geom.ShapeType]
|
||||||
|
) -> bool:
|
||||||
|
return "openings" in getattr(shape, "geometry", shape).id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_representation_parameters(cls, data: bpy.types.Mesh) -> None:
|
def import_representation_parameters(cls, data: bpy.types.Mesh) -> None:
|
||||||
props = data.BIMMeshProperties
|
props = data.BIMMeshProperties
|
||||||
|
|||||||
@@ -472,6 +472,16 @@ class Loader(bonsai.core.tool.Loader):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_indexed_colour_map(cls, representation: ifcopenshell.entity_instance, mesh: bpy.types.Mesh) -> None:
|
def load_indexed_colour_map(cls, representation: ifcopenshell.entity_instance, mesh: bpy.types.Mesh) -> None:
|
||||||
|
"""Ensure indexed colour map is loaded for representation if it's available.
|
||||||
|
|
||||||
|
Method doesn't support elements with openings, see #5405.
|
||||||
|
|
||||||
|
:param representation: IfcShapeRepresentation of any type. Representation may not have an indexed colour map,
|
||||||
|
method will automatically check if it does and will skip it otherwise.
|
||||||
|
|
||||||
|
:raises AssertionError: If mesh doesn't match the representation exactly, which usually occurs
|
||||||
|
if element geometry is altered by openings.
|
||||||
|
"""
|
||||||
if representation.RepresentationType != "Tessellation":
|
if representation.RepresentationType != "Tessellation":
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user