nodejs判断二维&三维空间两条线段是否相交并求出交点

安装math.js,JavaScript数学库

math.js官方文档
math.js是一个广泛应用于JavaScript 和 Node.js的数学库,特点是灵活表达式解析器,支持符号计算,内置大量函数与常量,并提供集成解决方案来处理不同的数据类型,如数字,大数字,复数,分数,单位和矩阵。
安装方法:

npm install mathjs

三维空间线段交点

math.js里自带了一个方法,可以计算线与线的交点(结果不是很准确),线与三维平面的交点
math.intersect(endPoint1Line1, endPoint2Line1, endPoint1Line2, endPoint2Line2)
math.intersect(endPoint1, endPoint2, planeCoefficients)
注:平面方程需要类似于 a1x + b1y + c1z = d

const math = require('mathjs')
math.intersect([0, 0], [10, 10], [10, 0], [0, 10])              // 二维线段 Returns [5, 5]
math.intersect([0, 0, 0], [10, 10, 0], [10, 0, 0], [0, 10, 0])  // 三维线段 Returns [5, 5, 0]
math.intersect([1, 0, 1],  [4, -2, 2], [1, 1, 1, 6])            // 线与平面 Returns [7, -4, 3]

用nodejs代码自己实现:

const math = require('mathjs')
//主函数:判断两线段是否相交,并求出焦点
function find3dCrossPoint (point1, point2, point3, point4) {

  // 空间直线方程 参数形式
  const deltax_s1 = point2[0] - point1[0]
  const deltay_s1 = point2[1] - point1[1]
  const deltaz_s1 = point2[2] - point1[2]

  const deltax_s2 = point4[0] - point3[0]
  const deltay_s2 = point4[1] - point3[1]
  const deltaz_s2 = point4[2] - point3[2]

  // 解开方程组
  const x0 = [deltax_s1, -deltax_s2]
  const b0 = point3[0] - point1[0]
  const x1 = [deltay_s1, -deltay_s2]
  const b1 = point3[1] - point1[1]
  const x2 = [deltaz_s1, -deltaz_s2]
  const b2 = point3[2] - point1[2]

  const tempDic = [
    { 'thex': [x0, x1], 'theb': [b0, b1], 'theIsCross': 2 },
    { 'thex': [x0, x2], 'theb': [b0, b2], 'theIsCross': 1 },
    { 'thex': [x1, x2], 'theb': [b1, b2], 'theIsCross': 0 }
  ]

  // 系数矩阵
  let x = tempDic[0]['thex']

  // 常数项
  let b = math.transpose(tempDic[0]['theb'])
  let isExitX = false
  let theIsCrossNum = 2
  for (let i = 0; i < 3; i++) {
    x = tempDic[i]['thex']
    b = math.transpose(tempDic[i]['theb'])
    theIsCrossNum = 2 - i
    if (math.det(x) != 0) {
      isExitX = true
      break
    }
  }

  if (!isExitX) {
    return false
  } else {
    const theSolve = math.lusolve(x, b)
    const t1 = theSolve[0]
    const t2 = theSolve[1]

    // 要求0<=t1,t2<=1,否则还是不相交
    if (t1 > 0 && t2 < 1) {
      const theIsCross = [
        point1[2] + deltaz_s1 * t1 == point3[2] + deltaz_s2 * t2,
        point1[1] + deltay_s1 * t1 == point3[1] + deltay_s2 * t2,
        point1[0] + deltax_s1 * t1 == point3[0] + deltax_s2 * t2
      ]

      const isCross = theIsCross[theIsCrossNum]

      if (isCross) {
        const crossPointX = point1[0] + deltax_s1 * t1
        const crossPointY = point1[1] + deltay_s1 * t1
        const crossPointZ = point1[2] + deltaz_s1 * t1
        const crossPoint = math.flatten([crossPointX, crossPointY, crossPointZ])

        // 交点在两条线段上
        if (isPointOnLine(crossPoint, [point1, point2]) && isPointOnLine(crossPoint, [point3, point4])) {
          return crossPoint
        } else {
          return false
        }
      }
    } else {
      return false
    }
  }
}

function isPointOnLine (point, line) {
  //已知点在线上
  const p1 = line[0]
  const p2 = line[1]

  const xmax = math.max(p1[0], p2[0])
  const xmin = math.min(p1[0], p2[0])

  const ymax = math.max(p1[1], p2[1])
  const ymin = math.min(p1[1], p2[1])

  const zmax = math.max(p1[2], p2[2])
  const zmin = math.min(p1[2], p2[2])

  if (point[0] <= xmax && point[0] >= xmin && point[1] <= ymax && point[1] >= ymin && point[2] <= zmax && point[2] >= zmin) {
    return true
  } else {
    return false
  }

}

测试:

const result = find3dCrossPoint([0, 0, 0], [1, 1, 1], [1, 0, 0], [0, 1, 1])
console.log(result) //交点为:[ 0.5, 0.5, 0.5 ]

参考

math.js简单用法
python实现三维空间线段的交点

你可能感兴趣的:(算法,javascript,矩阵,node.js,math.js)