【问题标题】:To find coordinates of nearest point on a line segment from a point从点查找线段上最近点的坐标
【发布时间】:2016-11-03 12:51:20
【问题描述】:

我需要计算从点 P 到线段 AB 的垂线的英尺。我需要 C 点的坐标,其中 PC 从 P 点垂直绘制到 AB 线。

我在 SO here 上找到的答案很少,但矢量乘积过程不适用于我。 这是我尝试过的:

function nearestPointSegment(a, b, c) {
   var t = nearestPointGreatCircle(a,b,c);
   return t;
}

function nearestPointGreatCircle(a, b, c) {
  var a_cartesian = normalize(Cesium.Cartesian3.fromDegrees(a.x,a.y))
  var b_cartesian = normalize(Cesium.Cartesian3.fromDegrees(b.x,b.y))
  var c_cartesian = normalize(Cesium.Cartesian3.fromDegrees(c.x,c.y))
  var G = vectorProduct(a_cartesian, b_cartesian);
  var F = vectorProduct(c_cartesian, G);
  var t = vectorProduct(G, F);
  t = multiplyByScalar(normalize(t), R);
  return fromCartesianToDegrees(t);
}

function vectorProduct(a, b) {
    var result = new Object();
    result.x = a.y * b.z - a.z * b.y;
    result.y = a.z * b.x - a.x * b.z;
    result.z = a.x * b.y - a.y * b.x;
    return result;
}

function normalize(t) {
    var length = Math.sqrt((t.x * t.x) + (t.y * t.y) + (t.z * t.z));
    var result = new Object();
    result.x = t.x/length;
    result.y = t.y/length;
    result.z = t.z/length;
    return result;
}

function multiplyByScalar(normalize, k) {
    var result = new Object();
    result.x = normalize.x * k;
    result.y = normalize.y * k;
    result.z = normalize.z * k;
    return result;
}

function fromCartesianToDegrees(pos) {
  var carto  = Cesium.Ellipsoid.WGS84.cartesianToCartographic(pos);     
  var lon = Cesium.Math.toDegrees(carto.longitude); 
  var lat = Cesium.Math.toDegrees(carto.latitude); 
  return [lon,lat];
}

我缺少什么?

【问题讨论】:

    标签: javascript cesium


    【解决方案1】:

    这是一种方法:

    // edge cases
    if (a.x === b.x) {
      // AB is vertical
      c.x = a.x;
      c.y = p.y;
    }
    else if (a.y === b.y) {
      // AB is horizontal
      c.x = p.x;
      c.y = a.y;
    }
    else {
      // linear function of AB
      var m1 = (b.y - a.y) / (b.x - a.x);
      var t1 = a.y - m1 * a.x;
      // linear function of PC
      var m2 = -1 / m1; // perpendicular
      var t2 = p.y - m2 * p.x;
      // c.x * m1 + t1 === c.x * m2 + t2
      c.x = (t2 - t1) / (m1 - m2);
      c.y = m1 * c.x + t1;
    }
    

    编辑:

    这是一种更好的基于矢量的方法:

    function foot(A, B, P) {
      const AB = {
        x: B.x - A.x,
        y: B.y - A.y
      };
      const k = ((P.x - A.x) * AB.x + (P.y - A.y) * AB.y) / (AB.x * AB.x + AB.y * AB.y);
      return {
        x: A.x + k * AB.x,
        y: A.y + k * AB.y
      };
    }
    
    const A = { x: 1, y: 1 };
    const B = { x: 4, y: 5 };
    const P = { x: 4.5, y: 3 };
    const C = foot(A, B, P);
    console.log(C);
    
    // perpendicular?
    const AB = {
      x: B.x - A.x,
      y: B.y - A.y
    };
    const PC = {
      x: C.x - P.x,
      y: C.y - P.y
    };
    console.log((AB.x * PC.x + AB.y * PC.y).toFixed(3));

    编辑:理论

    我从从 A 到 B 的向量 A➞B 开始。通过将此向量乘以标量 k 并将其添加到点 A,我可以到达 AB 线上的任何点 C。

    I) C = A + k × A➞B

    接下来我需要建立90°角,即A➞B和P➞C的点积为零。

    II) A➞B·P➞C = 0

    现在求解 k。

    【讨论】:

    • 嘿@Chris,你的解决方案效果很好,你能告诉我你用的是哪个公式/理论吗?
    • @UgniusMalūkas 我已经添加了理论:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    相关资源
    最近更新 更多