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

3D空间中两条直线共线检测的JavaScript实现方案问询

检测3D空间中两条直线是否共线的JavaScript实现

核心逻辑

两条3D直线共线需要同时满足两个条件:

  1. 两条直线的方向向量互相平行
  2. 其中一条直线上的任意一点(比如起点)落在另一条直线上

纯JavaScript实现(无依赖)

function areLinesCollinear(line1Start, line1End, line2Start, line2End) {
    // 处理浮点数精度误差的极小值
    const EPSILON = 1e-8;

    // 计算两条直线的方向向量
    const dir1 = [
        line1End[0] - line1Start[0],
        line1End[1] - line1Start[1],
        line1End[2] - line1Start[2]
    ];
    const dir2 = [
        line2End[0] - line2Start[0],
        line2End[1] - line2Start[1],
        line2End[2] - line2Start[2]
    ];

    // 叉乘判断方向向量是否平行
    const crossDirX = dir1[1] * dir2[2] - dir1[2] * dir2[1];
    const crossDirY = dir1[2] * dir2[0] - dir1[0] * dir2[2];
    const crossDirZ = dir1[0] * dir2[1] - dir1[1] * dir2[0];
    if (Math.abs(crossDirX) > EPSILON || Math.abs(crossDirY) > EPSILON || Math.abs(crossDirZ) > EPSILON) {
        return false;
    }

    // 计算第二条直线起点到第一条直线起点的向量
    const pointVec = [
        line2Start[0] - line1Start[0],
        line2Start[1] - line1Start[1],
        line2Start[2] - line1Start[2]
    ];

    // 判断该向量是否与第一条直线方向向量平行(即点在直线上)
    const crossPointX = pointVec[1] * dir1[2] - pointVec[2] * dir1[1];
    const crossPointY = pointVec[2] * dir1[0] - pointVec[0] * dir1[2];
    const crossPointZ = pointVec[0] * dir1[1] - pointVec[1] * dir1[0];
    return Math.abs(crossPointX) < EPSILON && Math.abs(crossPointY) < EPSILON && Math.abs(crossPointZ) < EPSILON;
}

// 测试示例
const line1Start = [0, 0, 0];
const line1End = [10, 0, 0];
const line2Start = [12, 0, 0];
const line2End = [15, 0, 0];
console.log(areLinesCollinear(line1Start, line1End, line2Start, line2End)); // 输出true

Three.js修正实现

如果之前用Three.js只判断了方向向量平行,会漏掉点是否在直线上的判断,以下是修正后的版本:

import * as THREE from 'three';

function areLinesCollinearThreeJS(line1Start, line1End, line2Start, line2End) {
    const EPSILON = 1e-8;
    const dir1 = new THREE.Vector3().subVectors(line1End, line1Start);
    const dir2 = new THREE.Vector3().subVectors(line2End, line2Start);

    // 先判断方向向量是否平行
    if (!dir1.isParallelTo(dir2, EPSILON)) {
        return false;
    }

    // 再判断第二条直线起点是否在第一条直线上
    const pointVec = new THREE.Vector3().subVectors(line2Start, line1Start);
    return pointVec.isParallelTo(dir1, EPSILON);
}

// 测试示例
const line1Start = new THREE.Vector3(0, 0, 0);
const line1End = new THREE.Vector3(10, 0, 0);
const line2Start = new THREE.Vector3(12, 0, 0);
const line2End = new THREE.Vector3(15, 0, 0);
console.log(areLinesCollinearThreeJS(line1Start, line1End, line2Start, line2End)); // 输出true

注意事项

  • 必须处理浮点数精度问题:由于计算误差,不能直接判断叉乘结果等于0,要和极小值EPSILON比较
  • 若直线是单点(起点和终点重合),需要额外判断两条直线的点是否重合

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 22:48:33