在最接近第三点javascript的行上找到一个点

时间:2015-08-28 23:28:22

标签: javascript math geometry

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

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

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

enter image description here

3 个答案:

答案 0 :(得分: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 };
}

答案 1 :(得分:0)

设A,B,C为双[],使得A的A = {x,y},B = {x,y}的b,C = {x,y}的c。 如果线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的简单转换。 希望它有所帮助!

答案 2 :(得分:0)

通常可以通过绘制与点相交的垂直线来确定到点的直线上的最近点。 要查找垂直斜率,请执行以下代码:

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 = slope *(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值。这是原始线和垂直线相遇的地方。

还记得早些时候我说这通常有用吗? 由于您使用的是而不是,因此有时最近的点将是终点。
以下是如何修复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语句来确定最接近的点 如果您需要更多帮助,请发表评论。