如何获取Open3D采样点云中各点所属的网格三角面索引?
获取Open3D Poisson Disk采样点对应的网格三角面索引
Open3D的sample_points_poisson_disk函数本身不会返回采样点所属的原网格三角面索引,需要通过额外逻辑实现,以下是两种可行方案:
方案一:射线投射法(精准匹配)
通过向网格内部发射射线,利用Open3D的射线投射功能获取点所属的三角面索引,精度更高。
代码实现
import open3d as o3d import numpy as np # 初始化三角网格 o3d_mesh = o3d.geometry.TriangleMesh() o3d_mesh.vertices = o3d.utility.Vector3dVector(vert_data) o3d_mesh.triangles = o3d.utility.Vector3iVector(face_data) o3d_mesh.compute_vertex_normals() # 计算网格法向量 # 执行Poisson Disk采样 pcd = o3d_mesh.sample_points_poisson_disk(number_of_points=500, init_factor=5) points = np.asarray(pcd.points) pcd.estimate_normals() # 估算点云法向量用于射线方向 normals = np.asarray(pcd.normals) face_indices = [] for i, point in enumerate(points): # 构造射线:起点为采样点,方向为点云法向量的反方向(确保射向网格内部) ray = o3d.core.Tensor([point, -normals[i]], dtype=o3d.core.Dtype.Float32) ray_cast_result = o3d_mesh.ray_cast(ray) if ray_cast_result.hit: # 获取命中的第一个三角面索引 face_idx = ray_cast_result.primitive_ids[0].item() face_indices.append(face_idx) else: # 处理极端情况(如采样点在网格外) face_indices.append(-1) # face_indices即为每个采样点对应的原网格三角面索引
方案二:KDTree重心匹配法(快速近似)
通过计算每个三角面的重心,构建KDTree后匹配采样点的最近重心,速度更快但属于近似方案,适合对精度要求不高或点数量大的场景。
代码实现
import open3d as o3d import numpy as np # 初始化三角网格 o3d_mesh = o3d.geometry.TriangleMesh() o3d_mesh.vertices = o3d.utility.Vector3dVector(vert_data) o3d_mesh.triangles = o3d.utility.Vector3iVector(face_data) # 计算所有三角面的重心 triangles = np.asarray(o3d_mesh.triangles) vertices = np.asarray(o3d_mesh.vertices) tri_centers = np.mean(vertices[triangles], axis=1) # 构建重心点集的KDTree kdtree = o3d.geometry.KDTreeFlann(o3d.utility.Vector3dVector(tri_centers)) # 执行Poisson Disk采样 pcd = o3d_mesh.sample_points_poisson_disk(number_of_points=500, init_factor=5) points = np.asarray(pcd.points) face_indices = [] for point in points: # 搜索最近的三角面重心 [_, idx, _] = kdtree.search_knn_vector_3d(point, 1) face_indices.append(idx[0]) # face_indices即为采样点对应的近似三角面索引
方案对比
- 射线投射法:精准度高,能准确找到包含采样点的三角面,但计算速度较慢,适合点数量较少的场景。
- KDTree重心匹配法:速度快,实现简单,但当网格三角面尺寸差异较大时,可能出现匹配错误。
内容的提问来源于stack exchange,提问作者ssuraj
相关产品推荐
相关产品推荐

