diff --git a/src/bonsai/bonsai/bim/import_ifc.py b/src/bonsai/bonsai/bim/import_ifc.py index 6dd8d2e940..c5eae6c4d9 100644 --- a/src/bonsai/bonsai/bim/import_ifc.py +++ b/src/bonsai/bonsai/bim/import_ifc.py @@ -827,28 +827,12 @@ class IfcImporter: def create_pointcloud( self, product: ifcopenshell.entity_instance, representation: ifcopenshell.entity_instance ) -> Union[ifcopenshell.entity_instance, None]: - placement_matrix = self.get_element_matrix(product) - vertex_list = [] - for item in representation.Items: - if item.is_a("IfcCartesianPointList3D"): - vertex_list.extend( - mathutils.Vector(list(coordinates)) * self.unit_scale for coordinates in item.CoordList - ) - elif item.is_a("IfcCartesianPointList2D"): - vertex_list.extend( - mathutils.Vector(list(coordinates)).to_3d() * self.unit_scale for coordinates in item.CoordList - ) - elif item.is_a("IfcCartesianPoint"): - vertex_list.append(mathutils.Vector(list(item.Coordinates)) * self.unit_scale) - - if len(vertex_list) == 0: - return None - - mesh_name = tool.Geometry.get_representation_name(representation) - mesh = bpy.data.meshes.new(mesh_name) - mesh.from_pydata(vertex_list, [], []) + mesh = tool.Loader.create_point_cloud_mesh(representation) + if mesh is None: + return tool.Ifc.link(representation, mesh) + placement_matrix = self.get_element_matrix(product) obj = bpy.data.objects.new(tool.Loader.get_name(product), mesh) self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, placement_matrix)) self.link_element(product, obj) diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index 910b921550..59bcdc0173 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -585,6 +585,16 @@ class Geometry(bonsai.core.tool.Geometry): settings.set("keep-bounding-boxes", True) context = representation.ContextOfItems + ifc_importer = bonsai.bim.import_ifc.IfcImporter(ifc_import_settings) + ifc_importer.file = tool.Ifc.get() + + # create_shape doesn't support point cloud representations. + if representation.RepresentationType in ("PointCloud", "Point"): + mesh = tool.Loader.create_point_cloud_mesh(representation) + if mesh is None: + raise Exception(f"Failed to process point cloud representation: {representation}.") + return mesh + if element.is_a("IfcTypeProduct"): # You may only specify a single representation when creating shapes for types try: @@ -606,9 +616,6 @@ class Geometry(bonsai.core.tool.Geometry): settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS) shape = ifcopenshell.geom.create_shape(settings, element, representation) - ifc_importer = bonsai.bim.import_ifc.IfcImporter(ifc_import_settings) - ifc_importer.file = tool.Ifc.get() - if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING": mesh = ifc_importer.create_camera(element, shape) if element.is_a("IfcAnnotation") and ifc_importer.is_curve_annotation(element): diff --git a/src/bonsai/bonsai/tool/loader.py b/src/bonsai/bonsai/tool/loader.py index 10fba187fb..8afbbae24b 100644 --- a/src/bonsai/bonsai/tool/loader.py +++ b/src/bonsai/bonsai/tool/loader.py @@ -651,6 +651,26 @@ class Loader(bonsai.core.tool.Loader): except: pass + @classmethod + def create_point_cloud_mesh(cls, representation: ifcopenshell.entity_instance) -> Union[bpy.types.Mesh, None]: + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + vertex_list = [] + for item in representation.Items: + if item.is_a("IfcCartesianPointList3D"): + vertex_list.extend(Vector(list(coordinates)) * unit_scale for coordinates in item.CoordList) + elif item.is_a("IfcCartesianPointList2D"): + vertex_list.extend(Vector(list(coordinates)).to_3d() * unit_scale for coordinates in item.CoordList) + elif item.is_a("IfcCartesianPoint"): + vertex_list.append(Vector(list(item.Coordinates)) * unit_scale) + + if len(vertex_list) == 0: + return None + + mesh_name = tool.Geometry.get_representation_name(representation) + mesh = bpy.data.meshes.new(mesh_name) + mesh.from_pydata(vertex_list, [], []) + return mesh + @classmethod def get_offset_point(cls, ifc_file: ifcopenshell.file) -> Union[npt.NDArray[np.float64], None]: elements_checked = 0