Найти последнюю широту долготы после движения по земному шару
Я использую формулу 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)];
}
Тестовые случаи:
вход
(lat, long) = (45, 0)
,angle = 0
,distance = radius * deg2rad(90)
=>(45, 180)
(как я сказал ранее)вход
(lat, long) = (0, 0)
,angle = 90
,distance = radius * deg2rad(90)
=>(0, 90)
(как и ожидалось - начинайте на экваторе, двигайтесь на восток на 90 градусов)вход
(lat, long) = (54, 29)
,angle = 36
,distance = radius * deg2rad(360)
=>(54, 29)
(как и ожидалось - начинайте с любой случайной позиции и проходите полный круг в любом направлении)Интересный случай: вход
(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 градусов на северо-запад и так далее...