Найти последнюю широту долготы после движения по земному шару

Я использую формулу 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];
}

2 ответа

Если вы двигаетесь горизонтально, вы можете увеличить долготу на 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 = 0, distance = radius * deg2rad(90) => (45, 180) (как я сказал ранее)

  2. вход (lat, long) = (0, 0), angle = 90, distance = radius * deg2rad(90) => (0, 90) (как и ожидалось - начинайте на экваторе, двигайтесь на восток на 90 градусов)

  3. вход (lat, long) = (54, 29), angle = 36, distance = radius * deg2rad(360) => (54, 29) (как и ожидалось - начинайте с любой случайной позиции и проходите полный круг в любом направлении)

  4. Интересный случай: вход (lat, long) = (30, 0), все остальное же. => (0, 90) (мы ожидали (30, 90)? - не на экваторе, проезд на 90 градусов к северу)

    Причина этого в том, что 90 градусов к северу - это не восток (если вы не на экваторе)! Эта диаграмма должна показать почему:

    Как видите, траектория движения под углом 90 градусов к северу не в восточном направлении.

Я только что нашел подобный вопрос здесь, и я следовал за решением, чтобы придумать функцию, которая работает для моего случая.

Надеюсь, это поможет кому-то еще:

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 градусов на северо-запад и так далее...

Другие вопросы по тегам