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

如何在ThreeJS中检测一条THREE.Line是否处于另一条THREE.Line的起止点之间

如何检测一条THREE.Line是否完全处于另一条THREE.Line的线段范围内

你的现有代码是用来检测两条线段是否相交的,所以线条交叉时会返回true,但这不符合你需要的「line1完全处于line2的起止点构成的线段内」的需求——简单说,你要的是判断line1是line2的子线段,而非仅仅相交。

实现思路

要实现这个判断,必须满足两个核心条件:

  1. line1和line2共线(否则不可能存在包含关系);
  2. line1的两个端点都落在line2的线段范围内。

我们可以利用Three.js内置的Vector3方法简化计算,避免手动编写复杂的线性代数公式:

type Point = THREE.Vector3;

function isLineContained(line1Start: Point, line1End: Point, line2Start: Point, line2End: Point): boolean {
    // 1. 判断两条线段是否共线
    const line2Dir = line2End.clone().sub(line2Start);
    // 计算line1起点到line2起点的向量与line2方向向量的叉乘
    const crossStart = line2Dir.clone().cross(line1Start.clone().sub(line2Start));
    // 计算line1终点到line2起点的向量与line2方向向量的叉乘
    const crossEnd = line2Dir.clone().cross(line1End.clone().sub(line2Start));
    
    // 叉乘结果非零则不共线,直接返回false
    // 使用isZero()处理浮点精度误差,而非直接判断===0
    if (!crossStart.isZero() || !crossEnd.isZero()) {
        return false;
    }

    // 2. 判断line1的两个端点是否都在line2的线段上
    const line2LengthSq = line2Dir.lengthSq();
    // 计算点积,得到端点在line2方向上的投影长度(相对于line2起点)
    const dotStart = line1Start.clone().sub(line2Start).dot(line2Dir);
    const dotEnd = line1End.clone().sub(line2Start).dot(line2Dir);

    // 投影长度需在0到line2的长度平方之间(对应线段的起止范围)
    const isStartInRange = dotStart >= 0 && dotStart <= line2LengthSq;
    const isEndInRange = dotEnd >= 0 && dotEnd <= line2LengthSq;

    return isStartInRange && isEndInRange;
}

// 测试示例
const line1Start = new THREE.Vector3(0, 0, 0);
const line1End = new THREE.Vector3(10, 0, 0);

// 测试1:line1部分超出line2范围,返回false
const line2Start = new THREE.Vector3(5, 0, 0);
const line2End = new THREE.Vector3(15, 0, 0);
console.log(isLineContained(line1Start, line1End, line2Start, line2End)); // false

// 测试2:line1完全在line2范围内,返回true
const line3Start = new THREE.Vector3(6, 0, 0);
const line3End = new THREE.Vector3(12, 0, 0);
console.log(isLineContained(line3Start, line3End, line2Start, line2End)); // true

关键细节说明

  • 共线判断:叉乘的几何意义是判断两个向量是否垂直,若叉乘结果为零向量,则说明两个向量共线。使用Three.js的isZero()方法可以自动处理浮点运算的精度误差,避免因微小数值偏差导致误判。
  • 点在线段上的判断:通过点积计算端点在目标线段方向上的投影长度,若投影长度在0到目标线段的长度平方之间,则说明该点落在目标线段的范围内(使用长度平方而非长度可以避免开方运算,提升性能)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:37:43