From f1138d1aac9ce8be974a3ffb08e66e2f04c78781 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 23 Mar 2025 21:55:57 +1100 Subject: [PATCH] Fix regression in point cloud loading in refactoring the new item mode. --- src/bonsai/bonsai/bim/import_ifc.py | 7 ++--- src/bonsai/bonsai/tool/loader.py | 15 +++++---- src/bonsai/test/tool/test_loader.py | 48 +++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/bonsai/bonsai/bim/import_ifc.py b/src/bonsai/bonsai/bim/import_ifc.py index 30c51e6310..d1c158dc8e 100644 --- a/src/bonsai/bonsai/bim/import_ifc.py +++ b/src/bonsai/bonsai/bim/import_ifc.py @@ -761,12 +761,9 @@ class IfcImporter: def create_pointclouds(self, products: set[ifcopenshell.entity_instance]) -> set[ifcopenshell.entity_instance]: result = set() for product in products: - representation = self.get_pointcloud_representation(product) - if representation is not None: - pointcloud = self.create_pointcloud(product, representation) - if pointcloud is not None: + if representation := self.get_pointcloud_representation(product): + if pointcloud := self.create_pointcloud(product, representation): result.add(pointcloud) - return result def create_pointcloud( diff --git a/src/bonsai/bonsai/tool/loader.py b/src/bonsai/bonsai/tool/loader.py index 91cfbc4629..0e8dee0305 100644 --- a/src/bonsai/bonsai/tool/loader.py +++ b/src/bonsai/bonsai/tool/loader.py @@ -766,16 +766,15 @@ class Loader(bonsai.core.tool.Loader): coords = None if item.is_a("IfcCartesianPointList3D"): # PointCloud.c coords = np.array(item.CoordList) - vertex_list.extend(Vector(list(coordinates)) * unit_scale for coordinates in item.CoordList) # Is it ever used? In IFC4+ PointCloud is requiring 3D list, before IFC4 there were no coord lists at all. elif item.is_a("IfcCartesianPointList2D"): - vertex_list.extend(Vector(list(coordinates)).to_3d() * unit_scale for coordinates in item.CoordList) - elif item.is_a("IfcPoint"): # Point - if item.is_a("IfcCartesianPoint"): - vertex_list.append(Vector(list(item.Coordinates)) * unit_scale) - else: - # TODO: implement non cartesian point vertices. - continue + coords = np.array(item.CoordList) + coords = np.column_stack((coords, np.zeros(coords.shape[0]))) + elif item.is_a("IfcCartesianPoint"): # Point + coord = np.array(item.Coordinates) + if len(coord) == 2: + coord = np.append(coord, (0.0,)) + coords = np.array((coord,)) else: assert False assert coords is not None diff --git a/src/bonsai/test/tool/test_loader.py b/src/bonsai/test/tool/test_loader.py index 30ef9e22b9..094fa8648f 100644 --- a/src/bonsai/test/tool/test_loader.py +++ b/src/bonsai/test/tool/test_loader.py @@ -549,3 +549,51 @@ class TestSetupActiveBsddClassification(NewFile): def test_set_load_and_set_active_bsdd_ifc4x3(self): self.run_test("IFC4X3") + + +class TestCreatePointCloudMesh(NewFile): + def test_cartesian_point_list_3d(self): + bpy.ops.bim.create_project() + ifc_file = tool.Ifc.get() + coords = ((1., 2., 3.), (4., 5., 6.)) + item = ifc_file.createIfcCartesianPointList3D(coords) + rep = ifc_file.createIfcShapeRepresentation(Items=[item]) + mesh = subject.create_point_cloud_mesh(rep) + assert len(mesh.vertices) == 2 + verts = np.array([v.co for v in mesh.vertices]) + assert np.allclose(verts, np.array([np.array(c) for c in coords])) + + def test_cartesian_point_list_2d(self): + bpy.ops.bim.create_project() + ifc_file = tool.Ifc.get() + coords = ((1., 2.), (4., 5.)) + coords3d = ((1., 2., 0.), (4., 5., 0.)) + item = ifc_file.createIfcCartesianPointList2D(coords) + rep = ifc_file.createIfcShapeRepresentation(Items=[item]) + mesh = subject.create_point_cloud_mesh(rep) + assert len(mesh.vertices) == 2 + verts = np.array([v.co for v in mesh.vertices]) + assert np.allclose(verts, np.array([np.array(c) for c in coords3d])) + + def test_point_3d(self): + bpy.ops.bim.create_project() + ifc_file = tool.Ifc.get() + coords = ((1., 2., 0.),) + item = ifc_file.createIfcCartesianPoint(Coordinates=coords[0]) + rep = ifc_file.createIfcShapeRepresentation(Items=[item]) + mesh = subject.create_point_cloud_mesh(rep) + assert len(mesh.vertices) == 1 + verts = np.array([v.co for v in mesh.vertices]) + assert np.allclose(verts, np.array([np.array(c) for c in coords])) + + def test_point_2d(self): + bpy.ops.bim.create_project() + ifc_file = tool.Ifc.get() + coords = ((1., 2.),) + coords3d = ((1., 2., 0.),) + item = ifc_file.createIfcCartesianPoint(Coordinates=coords[0]) + rep = ifc_file.createIfcShapeRepresentation(Items=[item]) + mesh = subject.create_point_cloud_mesh(rep) + assert len(mesh.vertices) == 1 + verts = np.array([v.co for v in mesh.vertices]) + assert np.allclose(verts, np.array([np.array(c) for c in coords3d]))