diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 5115a415fa..6312ce7f50 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -494,7 +494,7 @@ class IfcImporter: rep = representation while True: - if rep.Items and rep.Items[0].is_a("IfcMappedItem"): + if len(rep.Items) == 1 and rep.Items[0].is_a("IfcMappedItem"): rep_matrix = ifcopenshell.util.placement.get_mappeditem_transformation(rep.Items[0]) if not np.allclose(rep_matrix, np.eye(4)): matrix = rep_matrix @ matrix @@ -547,7 +547,7 @@ class IfcImporter: return True def is_native_swept_disk_solid(self, element, representation): - items = representation.Items or [] # Be forgiving of invalid IFCs because Revit :( + items = [i["item"] for i in ifcopenshell.util.representation.resolve_items(representation)] if len(items) == 1 and items[0].is_a("IfcSweptDiskSolid"): if tool.Blender.Modifier.is_railing(element): return False @@ -563,6 +563,7 @@ class IfcImporter: return False def is_native_faceted_brep(self, representation): + # TODO handle mapped items for i in representation.Items: if i.is_a() != "IfcFacetedBrep": return False @@ -1316,12 +1317,17 @@ class IfcImporter: curve.resolution_u = 2 polyline = curve.splines.new("POLY") - for item in native_data["representation"].Items: + for item_data in ifcopenshell.util.representation.resolve_items(native_data["representation"]): + item = item_data["item"] + matrix = item_data["matrix"] + matrix[0][3] *= self.unit_scale + matrix[1][3] *= self.unit_scale + matrix[2][3] *= self.unit_scale # TODO: support inner radius, start param, and end param geometry = self.create_generic_shape(item.Directrix) e = geometry.edges v = geometry.verts - vertices = [[v[i], v[i + 1], v[i + 2], 1] for i in range(0, len(v), 3)] + vertices = [list(matrix @ [v[i], v[i + 1], v[i + 2], 1]) for i in range(0, len(v), 3)] edges = [[e[i], e[i + 1]] for i in range(0, len(e), 2)] v2 = None for edge in edges: diff --git a/src/ifcopenshell-python/ifcopenshell/util/representation.py b/src/ifcopenshell-python/ifcopenshell/util/representation.py index 2d5d252e72..68842d3ef3 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/representation.py +++ b/src/ifcopenshell-python/ifcopenshell/util/representation.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import numpy as np import ifcopenshell @@ -67,6 +68,21 @@ def get_representation(element, context, subcontext=None, target_view=None): def resolve_representation(representation): - if representation.Items and representation.Items[0].is_a("IfcMappedItem"): + if len(representation.Items) == 1 and representation.Items[0].is_a("IfcMappedItem"): return resolve_representation(representation.Items[0].MappingSource.MappedRepresentation) return representation + + +def resolve_items(representation, matrix=None): + if matrix is None: + matrix = np.eye(4) + results = [] + for item in representation.Items or []: # Be forgiving of invalid IFCs because Revit :( + if item.is_a("IfcMappedItem"): + rep_matrix = ifcopenshell.util.placement.get_mappeditem_transformation(item) + if not np.allclose(rep_matrix, np.eye(4)): + rep_matrix = rep_matrix @ matrix.copy() + results.extend(resolve_items(item.MappingSource.MappedRepresentation, rep_matrix)) + else: + results.append({"matrix": matrix.copy(), "item": item}) + return results