You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Open3D中查找与体素相交且距体素中心最近的三角形

解决Open3D中查找体素中心最近三角形的问题

你的核心问题是误用了基于顶点的KD树——KDTreeFlann(mesh)默认用网格的顶点构建索引,所以返回的是最近顶点的ID,而非三角形ID。以下是两种可行的解决方案:

方案一:直接使用compute_closest_point_on_mesh(推荐)

Open3D的TriangleMesh内置了compute_closest_point_on_mesh方法,直接返回查询点到网格表面最近点的距离,以及该点所在的三角形索引,完全匹配你的需求。修改后的代码如下:

import open3d as o3d
import numpy as np

vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]])
triangles = np.array([[0, 1, 2]])
mesh = o3d.geometry.TriangleMesh()
mesh.vertices = o3d.utility.Vector3dVector(vertices)
mesh.triangles = o3d.utility.Vector3iVector(triangles)

# 体素中心示例
voxel_centers = np.array([[0.1, 0.1, 0.1], [0.5, 0.5, 0.5], [0.9, 0.9, 0.9]])

closest_triangles = []
for center in voxel_centers:
    # 直接获取最近点所在的三角形ID
    _, triangle_id = mesh.compute_closest_point_on_mesh(center)
    closest_triangles.append(triangle_id)

closest_triangles = np.array(closest_triangles)
print("Closest triangles")
print(closest_triangles)

运行后输出为[0 0 0],符合你只有一个三角形的实际情况。

方案二:基于顶点KD树关联三角形索引(不推荐,仅作原理说明)

如果坚持要用KDTree,需要先建立顶点到所属三角形的映射,再对查询到的最近顶点,筛选其所属三角形并计算距离,最终选最近的那个。步骤如下:

import open3d as o3d
import numpy as np
from collections import defaultdict

vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]])
triangles = np.array([[0, 1, 2]])
mesh = o3d.geometry.TriangleMesh()
mesh.vertices = o3d.utility.Vector3dVector(vertices)
mesh.triangles = o3d.utility.Vector3iVector(triangles)

# 构建顶点到三角形的映射字典
vertex_to_triangles = defaultdict(list)
for tri_idx, tri in enumerate(mesh.triangles):
    for v_idx in tri:
        vertex_to_triangles[v_idx].append(tri_idx)

voxel_centers = np.array([[0.1, 0.1, 0.1], [0.5, 0.5, 0.5], [0.9, 0.9, 0.9]])

kdtree = o3d.geometry.KDTreeFlann(mesh)
closest_triangles = []
for center in voxel_centers:
    _, vertex_ids, _ = kdtree.search_knn_vector_3d(center, 1)
    v_idx = vertex_ids[0]
    # 获取该顶点所属的所有三角形
    candidate_tris = vertex_to_triangles[v_idx]
    # 计算每个候选三角形到查询点的距离(用三角形重心距离)
    min_dist = float('inf')
    best_tri = -1
    for tri_idx in candidate_tris:
        tri_verts = np.asarray(mesh.vertices)[np.asarray(mesh.triangles)[tri_idx]]
        centroid = np.mean(tri_verts, axis=0)
        dist = np.linalg.norm(centroid - center)
        if dist < min_dist:
            min_dist = dist
            best_tri = tri_idx
    closest_triangles.append(best_tri)

closest_triangles = np.array(closest_triangles)
print("Closest triangles")
print(closest_triangles)

这种方法效率较低、逻辑复杂,仅在特殊场景下使用。

额外:筛选与体素相交的三角形

你的需求是“找到与给定体素相交且距离体素中心最近的三角形”,可以在获取最近三角形后,验证其是否与体素相交:

def triangle_intersects_voxel(tri_verts, voxel_aabb):
    # 获取三角形的AABB
    tri_aabb = o3d.geometry.AxisAlignedBoundingBox.create_from_points(o3d.utility.Vector3dVector(tri_verts))
    # 判断两个AABB是否相交
    return tri_aabb.intersects(voxel_aabb)

# 假设体素边长为0.2,创建体素的AABB
voxel_size = 0.2
valid_triangles = []
for idx, center in enumerate(voxel_centers):
    voxel_min = center - voxel_size/2
    voxel_max = center + voxel_size/2
    voxel_aabb = o3d.geometry.AxisAlignedBoundingBox(voxel_min, voxel_max)
    # 获取最近三角形的顶点
    tri_idx = closest_triangles[idx]
    tri_verts = np.asarray(mesh.vertices)[np.asarray(mesh.triangles)[tri_idx]]
    if triangle_intersects_voxel(tri_verts, voxel_aabb):
        valid_triangles.append(tri_idx)
    else:
        # 若最近三角形不相交,可扩大搜索范围找其他相交三角形
        pass

内容的提问来源于stack exchange,提问作者roymustang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:05:19