【问题标题】:find a point on a line closest to a third point javascript在最接近第三个点javascript的线上找到一个点
【发布时间】:2016-10-26 07:36:23
【问题描述】:

我试图在最接近线外第三点的线上找到一个点。这些点是纬度/经度。

简单的图形显示了我想要实现的目标。我将它用于 javascript,但任何语言或公式仍然可以使用。我知道这是基本几何,但我仍然无法在 google 上找到公式:S 大声笑...留在学校!

var a = '48,-90';
var b = '49,-92';
var c = '48.25,-91.8';
var d = 'calculated point on line';

【问题讨论】:

标签: javascript math geometry


【解决方案1】:

RCrowe@Find a point in a polyline which is closest to a latlng

/* desc Static function. Find point on lines nearest test point
   test point pXy with properties .x and .y
   lines defined by array aXys with nodes having properties .x and .y 
   return is object with .x and .y properties and property i indicating nearest segment in aXys 
   and property fFrom the fractional distance of the returned point from aXy[i-1]
   and property fTo the fractional distance of the returned point from aXy[i]   */


function getClosestPointOnLines(pXy, aXys) {

    var minDist;
    var fTo;
    var fFrom;
    var x;
    var y;
    var i;
    var dist;

    if (aXys.length > 1) {

        for (var n = 1 ; n < aXys.length ; n++) {

            if (aXys[n].x != aXys[n - 1].x) {
                var a = (aXys[n].y - aXys[n - 1].y) / (aXys[n].x - aXys[n - 1].x);
                var b = aXys[n].y - a * aXys[n].x;
                dist = Math.abs(a * pXy.x + b - pXy.y) / Math.sqrt(a * a + 1);
            }
            else
                dist = Math.abs(pXy.x - aXys[n].x)

            // length^2 of line segment 
            var rl2 = Math.pow(aXys[n].y - aXys[n - 1].y, 2) + Math.pow(aXys[n].x - aXys[n - 1].x, 2);

            // distance^2 of pt to end line segment
            var ln2 = Math.pow(aXys[n].y - pXy.y, 2) + Math.pow(aXys[n].x - pXy.x, 2);

            // distance^2 of pt to begin line segment
            var lnm12 = Math.pow(aXys[n - 1].y - pXy.y, 2) + Math.pow(aXys[n - 1].x - pXy.x, 2);

            // minimum distance^2 of pt to infinite line
            var dist2 = Math.pow(dist, 2);

            // calculated length^2 of line segment
            var calcrl2 = ln2 - dist2 + lnm12 - dist2;

            // redefine minimum distance to line segment (not infinite line) if necessary
            if (calcrl2 > rl2)
                dist = Math.sqrt(Math.min(ln2, lnm12));

            if ((minDist == null) || (minDist > dist)) {
                if (calcrl2 > rl2) {
                    if (lnm12 < ln2) {
                        fTo = 0;//nearer to previous point
                        fFrom = 1;
                    }
                    else {
                        fFrom = 0;//nearer to current point
                        fTo = 1;
                    }
                }
                else {
                    // perpendicular from point intersects line segment
                    fTo = ((Math.sqrt(lnm12 - dist2)) / Math.sqrt(rl2));
                    fFrom = ((Math.sqrt(ln2 - dist2)) / Math.sqrt(rl2));
                }
                minDist = dist;
                i = n;
            }
        }

        var dx = aXys[i - 1].x - aXys[i].x;
        var dy = aXys[i - 1].y - aXys[i].y;

        x = aXys[i - 1].x - (dx * fTo);
        y = aXys[i - 1].y - (dy * fTo);

    }

    return { 'x': x, 'y': y, 'i': i, 'fTo': fTo, 'fFrom': fFrom };
}

【讨论】:

    【解决方案2】:

    令 A,B,C 为 double[],使得 A = a 的 {x,y},B = b 的 {x,y},C = c 的 {x,y}。 如果ab线是y = mx + z,那么

    m = (A[1]-B[1])/(A[0]-B[0])

    z = A[1] - m*A[0]

    现在我们需要通过 c 垂直于 ab 的线。如果这一行是 y = m'x + z',那么

    m' = -1/m = (A[0]-B[0])/(B[1]-A[1])

    z' = C[1] - m'*C[0]

    最后我们需要这些线的交点。我们设置 y=y 并求解

    mx+z = m'x + z'

    x(m-m') = z'-z

    x = (z'-z)/(m-m')

    y = m*x + z

    D = {(z'-z)/(m-m'), m*x + z}。 现在剩下的就是到 String 的简单转换。 希望对您有所帮助!

    【讨论】:

      【解决方案3】:

      一条直线上离一个点最近的点通常可以通过画一条与该点相交的垂线来确定。 要找到垂直斜率,请执行以下代码:

      var slope = (Number(a.substring(a.indexOf(",") + 1, a.length)) //The Y coordinate of A
       - Number(b.substring(b.indexOf(",") + 1, b.length))) // The Y coordinate of B
       / (Number(a.substring(0, a.indexOf(","))) // The X coordinate of A
       - Number(b.substring(0, b.indexOf(",")))); //The Y coordinate of B
      

      这是斜率公式 (y2 - y1) / (x2 - x1)
      现在我们有了坡度,很容易转换为垂直坡度。

      var perpendicularSlope = -1 / slope;
      

      现在,我们需要应用点斜率公式(y - y1 = 斜率 * (x - x1))。

      var newPointX = Number(c.substring(0, c.indexOf(",")); //Gets the X value of new point
      var newPointY = Number(c.substring(c.indexOf(",") + 1, c.length)); //Gets the Y value of new point
      //Note that in the formula provided above, y and x are not going to be assigned in code.
      //I'm going to bypass formatting it like that and go right to the slope intercept form
      var perpendicularBValue = newPointY - perpendicularSlope * newPointX;
      
      //Slope intercept form is y = mx + b. (m is slope and b is where the line intersects the y axis)
      

      接下来,我们要得到第一行的斜率截距形式。

      var lineX = Number(a.substring(0, a.indexOf(",")); 
      var lineY = Number(a.substring(a.indexOf(",") + 1, a.length));
      var lineB = lineY - slope * newPointY;
      

      我在这里创建了一个方程组。为了解决这个问题,我们必须使用传递性(如果 a = b 和 b = c,则 a = c);

      var xCollision = (lineB - perpendicularBValue) / (perpendicularSlope - slope);
      var yCollision = slope * xCollosion + lineB;
      var d = xCollision + "," + yCollision;
      

      我使用传递属性消除了 y 变量并将方程连接起来。然后我解决了x。然后我将 x 值插入并求解 y 值。这是原线和垂线相交的地方。

      还记得我之前说过这通常有效吗?
      由于您使用的是线 segments 而不是 lines,因此有时最近的点就是终点。
      以下是固定 d 值的方法

      var aDistance = Math.sqrt(
          Math.pow(lineX - newPointX, 2) +
          Math.pow(lineY - newPointY, 2));
      var bDistance = Math.sqrt(
          Math.pow(Number(b.substring(0, b.indexOf(",")) - newPointX, 2) +
          Math.pow(Number(b.substring(b.indexOf(",") + 1, b.length) - newPointY, 2));
      var dDistance = Math.sqrt(
          Math.pow(xCollision - newPointX, 2) +
          Math.pow(yCollision - newPointY, 2));
      var closestEndpoint = aDistance < bDistance ? aDistance : bDistance;
      var closestPoint = closestEndpoint < dDistance ? closestEndpoint : dDistance;
      

      我使用了一个称为距离公式((x1 - x2)^2 + (y1 - y2)^2 的平方根)的公式来确定点之间的距离。然后我使用速记 if 语句来确定最近点。
      如果您需要更多帮助,请发表评论。

      【讨论】:

      • 这可以处理水平线吗?看起来它可能会将垂线的斜率设为 -1/0。
      猜你喜欢
      • 2018-04-21
      • 2012-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多