3D空间中两条直线共线检测的JavaScript实现方案问询
检测3D空间中两条直线是否共线的JavaScript实现
核心逻辑
两条3D直线共线需要同时满足两个条件:
- 两条直线的方向向量互相平行
- 其中一条直线上的任意一点(比如起点)落在另一条直线上
纯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
相关产品推荐
相关产品推荐

