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

如何判断三维空间中直线是否与立方体相交(不含顶点触碰)

三维直线与立方体相交判断实现方案

1. 先将立方体转换为轴对齐边界框(AABB)

从给定的8个立方体顶点中,提取三个坐标轴方向的极值,得到简化的边界框:

  • 遍历所有顶点的x坐标,计算最小值x_min和最大值x_max
  • 同理得到y_min/y_max、z_min/z_max
    转换为AABB后,无需处理复杂的顶点-面关系,大幅简化计算逻辑。

2. 用Slab方法(轴分离定理)判断相交性

Slab方法是高效判断直线与AABB相交的经典算法,核心是将直线投影到三个坐标轴,检查投影区间与AABB的投影区间是否重叠。

具体步骤

设直线端点为P0(x0,y0,z0)、P1(x1,y1,z1),方向向量D = (dx, dy, dz) = P1 - P0,参数t的取值范围t∈[0,1]对应线段部分,超出范围对应直线延长线:

  • 初始化t_min = 0,t_max = 1
  • 依次处理x、y、z三个轴:
    1. 若方向向量分量d ≈ 0(浮点精度用1e-8判断):
      • 若P0的对应坐标不在[min, max]区间内,直线平行于该轴且在AABB外,直接返回不相交
    2. 否则:
      • 计算t1 = (min - P0对应坐标) / d,t2 = (max - P0对应坐标) / d
      • 确保t1 ≤ t2,否则交换两者
      • 更新t_min = max(t_min, t1),t_max = min(t_max, t2)
      • 若t_min > t_max,说明该轴投影无重叠,返回不相交
  • 处理完三轴后,若t_min ≤ t_max,需进一步排除仅触碰顶点的情况:
    • 计算t_min和t_max对应的交点P_min = P0 + t_min*D、P_max = P0 + t_max*D
    • 判断两个交点是否均为立方体顶点(用1e-8阈值判断坐标相等):
      • 若两个交点都是顶点,且t_min/t_max对应线段端点(即t∈{0,1}),或两个交点重合为单个顶点,返回不相交
      • 否则返回相交

3. 浮点精度处理要点

所有坐标比较、相等判断必须引入极小epsilon值(如1e-8),避免因浮点计算误差导致的误判。

示例伪代码

def line_intersects_cube(cube_vertices, p0, p1):
    # 计算AABB边界
    x_coords = [v[0] for v in cube_vertices]
    y_coords = [v[1] for v in cube_vertices]
    z_coords = [v[2] for v in cube_vertices]
    x_min, x_max = min(x_coords), max(x_coords)
    y_min, y_max = min(y_coords), max(y_coords)
    z_min, z_max = min(z_coords), max(z_coords)
    
    dx = p1[0] - p0[0]
    dy = p1[1] - p0[1]
    dz = p1[2] - p0[2]
    epsilon = 1e-8
    
    t_min = 0.0
    t_max = 1.0
    
    # 处理x轴
    if abs(dx) < epsilon:
        if p0[0] < x_min - epsilon or p0[0] > x_max + epsilon:
            return False
    else:
        t1 = (x_min - p0[0]) / dx
        t2 = (x_max - p0[0]) / dx
        if t1 > t2:
            t1, t2 = t2, t1
        t_min = max(t_min, t1)
        t_max = min(t_max, t2)
        if t_min > t_max + epsilon:
            return False
    
    # 处理y轴
    if abs(dy) < epsilon:
        if p0[1] < y_min - epsilon or p0[1] > y_max + epsilon:
            return False
    else:
        t1 = (y_min - p0[1]) / dy
        t2 = (y_max - p0[1]) / dy
        if t1 > t2:
            t1, t2 = t2, t1
        t_min = max(t_min, t1)
        t_max = min(t_max, t2)
        if t_min > t_max + epsilon:
            return False
    
    # 处理z轴
    if abs(dz) < epsilon:
        if p0[2] < z_min - epsilon or p0[2] > z_max + epsilon:
            return False
    else:
        t1 = (z_min - p0[2]) / dz
        t2 = (z_max - p0[2]) / dz
        if t1 > t2:
            t1, t2 = t2, t1
        t_min = max(t_min, t1)
        t_max = min(t_max, t2)
        if t_min > t_max + epsilon:
            return False
    
    # 判断点是否为立方体顶点
    def is_vertex(point):
        for v in cube_vertices:
            if (abs(point[0]-v[0]) < epsilon and
                abs(point[1]-v[1]) < epsilon and
                abs(point[2]-v[2]) < epsilon):
                return True
        return False
    
    p_min = (p0[0] + t_min*dx, p0[1] + t_min*dy, p0[2] + t_min*dz)
    p_max = (p0[0] + t_max*dx, p0[1] + t_max*dy, p0[2] + t_max*dz)
    
    min_is_vtx = is_vertex(p_min)
    max_is_vtx = is_vertex(p_max)
    
    # 排除仅触碰顶点的情况
    if min_is_vtx and max_is_vtx:
        # 两个交点为同一顶点,或线段连接两个顶点
        if abs(t_min - t_max) < epsilon or \
           ((t_min < epsilon or abs(t_min-1) < epsilon) and 
            (t_max < epsilon or abs(t_max-1) < epsilon)):
            return False
    
    # 排除线段端点仅触碰单个顶点的情况
    if (t_min < epsilon and min_is_vtx) and (t_max > 1 - epsilon and max_is_vtx):
        return False
    
    return True

特殊情况处理

如果立方体不是轴对齐的,需要先对直线和立方体做相同的旋转变换,将立方体转换为轴对齐状态后,再使用上述方法判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:15:44