【问题标题】:Find the final latitude longitude after a movement on the globe在地球上移动后找到最终的纬度经度
【发布时间】:2017-12-27 07:50:26
【问题描述】:

我正在使用Haversine 公式计算两个经纬度对的距离。

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
    var R = 6371; // Radius of the earth in km
    var dLat = deg2rad(lat2-lat1);
    var dLon = deg2rad(lon2-lon1); 
    var lat1 = deg2rad(lat1);
    var lat2 = deg2rad(lat2);

    var a = 
        Math.sin(dLat/2) * Math.sin(dLat/2) + 
        Math.sin(dLon/2) * Math.sin(dLon/2) * 
        Math.cos(lat1) * Math.cos(lat2);

    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
    var d = R * c;
    return d;
}

给定一个起点(lat1,lat2),在直线上移动所需的距离和角度,我需要确定终点(如lat2和lon2)。

请参阅下面的尝试:

function getFinalLatLon(lat1, lon1, distance, angle) {
    var R = 6371; // Radius of the earth in km
    var c = distance/R;
    // Math.atan2(Math.sqrt(a), Math.sqrt(1-a)) = c/2
    var a = // stuck here

    // looking for this part of the code

    return [lat2, lon2];
}

【问题讨论】:

标签: javascript math geolocation haversine earthdistance


【解决方案1】:

如果您是水平移动,您可以将经度增加distance / (R * cos(lat))。不需要atan


编辑:由于您想要一个适用于一般情况的公式,请考虑以下几何推导:

  • 前视图:

  • 侧视图:

  • 整个设置:

注意事项:

  • r是你起始位置的单位向量,s是终点。

  • a, b, c 是帮助计算的中间向量。

  • (θ, φ) 是(纬度、经度)坐标。
  • γ 是您将要行驶的方向的方位
  • δ 是经过的角度(距离/半径R = 6400000m)。

我们需要a, b 垂直于r 并且还需要a 与北对齐。这给出了:

c 由(简单三角函数)给出:

因此我们得到s(通过一些非常乏味的代数):

现在我们可以使用以下方法计算s 的最终(纬度、经度)坐标:


代码:

function deg2rad(deg) { return deg * (Math.PI / 180.0) }
function rad2deg(rad) { return rad * (180.0 / Math.PI) }

function getFinalLatLong(lat1, long1, distance, angle, radius) {
    // calculate angles
    var delta = distance / radius,
        theta = deg2rad(lat1),
        phi   = deg2rad(long1),
        gamma = deg2rad(angle);

    // calculate sines and cosines
    var c_theta = Math.cos(theta), s_theta = Math.sin(theta);
    var c_phi   = Math.cos(phi)  , s_phi   = Math.sin(phi)  ;
    var c_delta = Math.cos(delta), s_delta = Math.sin(delta);
    var c_gamma = Math.cos(gamma), s_gamma = Math.sin(gamma);

    // calculate end vector
    var x = c_delta * c_theta * c_phi - s_delta * (s_theta * c_phi * c_gamma + s_phi * s_gamma);
    var y = c_delta * c_theta * s_phi - s_delta * (s_theta * s_phi * c_gamma - c_phi * s_gamma);
    var z = s_delta * c_theta * c_gamma + c_delta * s_theta;

    // calculate end lat long
    var theta2 = Math.asin(z), phi2 = Math.atan2(y, x);

    return [rad2deg(theta2), rad2deg(phi2)];
}

测试用例:

  1. 输入(lat, long) = (45, 0)angle = 0distance = radius * deg2rad(90) => (45, 180)(我之前说过)

  2. 输入(lat, long) = (0, 0)angle = 90distance = radius * deg2rad(90) => (0, 90)(如预期的那样——从赤道开始,向东行驶90经度)

  3. 输入(lat, long) = (54, 29)angle = 36distance = radius * deg2rad(360) => (54, 29)(如预期的那样——从任意随机位置开始,向任意方向绕一圈)

  4. 有趣的案例:输入(lat, long) = (30, 0),其他都一样。 => (0, 90)(我们预计(30, 90)? - 不是从赤道开始,向北行进 90 度)

    原因是北纬 90 度不是东(如果你不在赤道)!此图应说明原因:

    如您所见,向北 90 度的移动路径向东方向。

【讨论】:

  • 在我接受之前让我证明这一点...听起来很简单,让我大吃一惊。
  • @TechyTimo 哎呀等一下,抱歉,有一点遗漏
  • @meowgoesthedog 乘以 180/Pi 得到以度为单位的经度增量
  • 很好的解释。似乎在通过第一个测试用例时失败了 - 以地球半径 = 6371000 米,距离 = 半径 * deg2rad(90) 和 getFinalLatLong(45, 0, distance, 90, radius) 返回 [4.96.., 90]跨度>
  • @TechyTimo 您没有显示 lat 值的其余部分 - 4.961562726608714e-15 - 即接近预期值零的非常小数字。这是这类计算典型的浮点错误,大约是双精度数的机器ε
【解决方案2】:

我刚刚发现了一个类似的问题here,我按照解决方案提出了一个适用于我的情况的函数。

希望对其他人有所帮助:

function getFinalLatLon(lat1, lon1, distance, angle){ 
    function deg2rad(deg) {
        return deg * (Math.PI/180)
    }
    // dy = R*sin(theta) 
    var dy = distance * Math.sin(deg2rad(angle)) 
    var delta_latitude = dy/110574
    // One degree of latitude on the Earth's surface equals (110574 meters
    delta_latitude = parseFloat(delta_latitude.toFixed(6));

    // final latitude = start_latitude + delta_latitude
    var lat2 = lat1 + delta_latitude

    // dx = R*cos(theta) 
    var dx = distance * Math.cos(deg2rad(angle)) 
    // One degree of longitude equals 111321 meters (at the equator)
    var delta_longitude = dx/(111321*Math.cos(deg2rad(lat1))) 
    delta_longitude = parseFloat(delta_longitude.toFixed(6));

    // final longitude = start_longitude + delta_longitude
    var lon2 = lon1 + delta_longitude

    return [lat2, lon2];
}

水平移动的角度为 0 度。你可以随意切换。如果有人向北移动,那将是 90 度。西北135度等等...

【讨论】:

  • 不确定这是否有效。假设您通过2 * (90 - lat) 向北移动。你应该再次以lat 结束,但你得到180 - lat,这是不正确的。
  • 我认为它已修复 - 我错过了非常需要的度数到弧度的转换。
  • 虽然有必要,但并不能解决我上面指出的问题。
  • 我不明白你的问题.. 你向北移动什么?你能用实际数字吗...
  • 说如果你在纬度= 45。如果你向北移动距离(地球半径)* 90,你应该仍然到达纬度45(就在地球的另一边,即你的经度变化 180)。但是,如果您运行代码,纬度变为 135,而经度根本不会改变;我认为这是一个不正确的结果。
猜你喜欢
  • 1970-01-01
  • 2015-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多