计算经纬度坐标的中点

Calculate the mid point of latitude and longitude co-ordinates

有谁知道获取一对纬度和经度点的中点的最佳方法吗?

我mm使用d3.js在地图上画点,需要在两点之间画一条曲线,所以我需要创建一个中点来画线中的曲线。

请查看下图以更好地理解我正在尝试做的事情:

检查this问题,你可以用它来找到你在google地图上的协调中心。我将其定制为与 d3js 一起使用。 希望对你有帮助。

D3

function midpoint (lat1, lng1, lat2, lng2) {

lat1= deg2rad(lat1);
lng1= deg2rad(lng1);
lat2= deg2rad(lat2);
lng2= deg2rad(lng2);

dlng = lng2 - lng1;
Bx = Math.cos(lat2) * Math.cos(dlng);
By = Math.cos(lat2) * Math.sin(dlng);
lat3 = Math.atan2( Math.sin(lat1)+Math.sin(lat2),
Math.sqrt((Math.cos(lat1)+Bx)*(Math.cos(lat1)+Bx) + By*By ));
lng3 = lng1 + Math.atan2(By, (Math.cos(lat1) + Bx));

   return (lat3*180)/Math.PI .' '. (lng3*180)/Math.PI;
}

function deg2rad (degrees) {
    return degrees * Math.PI / 180;
};

更新 1

如果你想画曲线,你应该创建一个协调的路径,例如:

var lat1=53.507651,lng1=10.046997,lat2=52.234528,lng2=10.695190;


    var svg=d3.select("body").append("svg").attr({width:700 , height:600});
    svg.append("path").attr("d", function (d) {
      var dC="M "+lat1+","+lng1+ " A " + midpoint (lat1, lng1, lat2, lng2)
         + " 0 1,0 " +lat2 +" , "+lng2 +"Z";
        return dC;

    })
    .style("fill","none").style("stroke" ,"steelblue");

您需要在 d3 中根据需要创建曲线。 JsFiddle here.

对于准确的一面:

您可以使用 Esri 网络 API。没有什么能比得上数十年的投影系统和基准面实施经验...虽然 ArcGIS for Server 系列是商业产品,但 JS API 是免费的,这里有一个纯 JS 函数,可以满足您的需求想要:geometryEngine.densify ; that function requires an interval parameter, that you can, in your case, get by dividing by two the results of geometryEngine.geodesicLength

这需要您以非常基本的方式熟悉 Polyline class,例如 var mySegment = new Polyline([[50,3], [55,8]]);,可能仅此而已。

对于视觉方面:

你的段有两个中间?您可能还对 geometryEngine.offset 感兴趣;首先在每个方向上偏移原始线段一次,然后获取每个结果线段的中心点。

实用方面:

考虑到所涉及的距离很短,如果你不是在处理离两极太近的奇怪地方,我会简单地使用 X 和 Y 的算术平均值,然后 add/subtract 一个旋转的矢量来抵消你的两个 "middles"。这样做在机器上会更轻(没有库可以从 CDN 加载),对你来说更容易,只要它的目的是一个很好的显示,结果就足够了。

(根据评论添加:样本)

// Your known starting points, and a k factor of your choice.
var a = {x:3, y:50};
var b = {x:8, y:55};
var k = 0.2;

// Intermediate values
var vab =       {x:b.x-a.x, y:b.y-a.y};
var v_rotated = {x:-k*vab.y, y:k*vab.x};
var middle =    {x:a.x+vab.x/2, y:a.y+vab.y/2};

// Your two resulting points
var result_i = {x: middle.x + v_rotated.x,  y: middle.y + v_rotated.y};
var result_j = {x: middle.x - v_rotated.x,  y: middle.y - v_rotated.y};

为冗长的脚本道歉 - 画东西似乎很有趣 :-)。我已经标记了不需要的部分

// your latitude / longitude
var co2 = [70, 48];
var co1 = [-70, -28];


// NOT REQUIRED
var ctx = document.getElementById("myChart").getContext("2d");

function drawPoint(color, point) {
    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.arc(point.x, point.y, 5, 0, 2 * Math.PI, false);
    ctx.fill();
}

function drawCircle(point, r) {
    ctx.strokeStyle = 'gray';
    ctx.setLineDash([5, 5]);
    ctx.beginPath();
    ctx.arc(point.x, point.y, r, 0, 2 * Math.PI, false);
    ctx.stroke();
}


// REQUIRED
// convert to cartesian
var projection = d3.geo.equirectangular()

var cot1 = projection(co1);
var cot2 = projection(co2);

var p0 = { x: cot1[0], y: cot1[1] };
var p1 = { x: cot2[0], y: cot2[1] };


// NOT REQUIRED
drawPoint('green', p0);
drawPoint('green', p1);


// REQUIRED
function dfn(p0, p1) {
    return Math.pow(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2), 0.5);
}

// from http://math.stackexchange.com/a/87374
var d = dfn(p0, p1);
var m = {
    x: (p0.x + p1.x) / 2,
    y: (p0.y + p1.y) / 2,
}

var u = (p1.x - p0.x) / d
var v = (p1.y - p0.y) / d;

// increase 1, if you want a larger curvature
var r = d * 1;
var h = Math.pow(Math.pow(r, 2) - Math.pow(d, 2) / 4, 0.5);

// 2 possible centers
var c1 = {
    x: m.x - h * v,
    y: m.y + h * u
}
var c2 = {
    x: m.x + h * v,
    y: m.y - h * u
}


// NOT REQUIRED
drawPoint('gray', c1)
drawPoint('gray', c2)

drawCircle(c1, r)
drawCircle(c2, r)


// REQUIRED

// from http://math.stackexchange.com/a/919423
function mfn(p0, p1, c) {
    // the -c1 is for moving the center to 0 and back again
    var mt1 = {
        x: r * (p0.x + p1.x - c.x * 2) / Math.pow(Math.pow(p0.x + p1.x - c.x * 2, 2) + Math.pow(p0.y + p1.y - c.y * 2, 2), 0.5)
    };
    mt1.y = (p0.y + p1.y - c.y * 2) / (p0.x + p1.x - c.x * 2) * mt1.x;

    var ma = {
        x: mt1.x + c.x,
        y: mt1.y + c.y,
    }

    var mb = {
        x: -mt1.x + c.x,
        y: -mt1.y + c.y,
    }

    return (dfn(ma, p0) < dfn(mb, p0)) ? ma : mb;
}

var m1 = mfn(p0, p1, c1);
var m2 = mfn(p0, p1, c2);

var mo1 = projection.invert([m1.x, m1.y]);
var mo2 = projection.invert([m2.x, m2.y]);


// NOT REQUIRED
drawPoint('blue', m1);
drawPoint('blue', m2);

// your final output (in lat long)
console.log(mo1);
console.log(mo2);

Fiddle - https://jsfiddle.net/srjuc2gd/



这只是相关部分(大部分只是从这个答案的开头复制意大利面)

var Q31428016 = (function () {

    // adjust curvature
    var CURVATURE = 1;


    // project to convert from lat / long to cartesian
    var projection = d3.geo.equirectangular();

    // distance between p0 and p1
    function dfn(p0, p1) {
        return Math.pow(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2), 0.5);
    }

    // mid point between p0 and p1
    function cfn(p0, p1) {
        return {
            x: (p0.x + p1.x) / 2,
            y: (p0.y + p1.y) / 2,
        }
    }

    // get arc midpoint given end points, center and radius - http://math.stackexchange.com/a/919423
    function mfn(p0, p1, c, r) {

        var m = cfn(p0, p1);

        // the -c1 is for moving the center to 0 and back again
        var mt1 = {
            x: r * (m.x - c.x) / Math.pow(Math.pow(m.x - c.x, 2) + Math.pow(m.y - c.y, 2), 0.5)
        };
        mt1.y = (m.y - c.y) / (m.x - c.x) * mt1.x;

        var ma = {
            x: mt1.x + c.x,
            y: mt1.y + c.y,
        }

        var mb = {
            x: -mt1.x + c.x,
            y: -mt1.y + c.y,
        }

        return (dfn(ma, p0) < dfn(mb, p0)) ? ma : mb;
    }

    var Q31428016 = {};
    Q31428016.convert = function (co1, co2) {

        // convert to cartesian
        var cot1 = projection(co1);
        var cot2 = projection(co2);

        var p0 = { x: cot1[0], y: cot1[1] };
        var p1 = { x: cot2[0], y: cot2[1] };


        // get center - http://math.stackexchange.com/a/87374
        var d = dfn(p0, p1);
        var m = cfn(p0, p1);

        var u = (p1.x - p0.x) / d
        var v = (p1.y - p0.y) / d;

        var r = d * CURVATURE;
        var h = Math.pow(Math.pow(r, 2) - Math.pow(d, 2) / 4, 0.5);

        // 2 possible centers
        var c1 = {
            x: m.x - h * v,
            y: m.y + h * u
        }
        var c2 = {
            x: m.x + h * v,
            y: m.y - h * u
        }


        // get arc midpoints
        var m1 = mfn(p0, p1, c1, r);
        var m2 = mfn(p0, p1, c2, r);


        // convert back to lat / long
        var mo1 = projection.invert([m1.x, m1.y]);
        var mo2 = projection.invert([m2.x, m2.y]);

        return [mo1, mo2]
    }

    return Q31428016;
})();


// your latitude / longitude
var co1 = [-70, -28];
var co2 = [70, 48];

var mo = Q31428016.convert(co1, co2)

// your output
console.log(mo[0]);
console.log(mo[1]);

我一直用geo-lib 并且工作