Геопространственные координаты и расстояние в километрах

Это продолжение этот вопрос.

Кажется, я зациклился на этом. По сути, мне нужно иметь возможность конвертировать туда и обратно для ссылки на координаты либо в стандартной системе градусов, либо путем измерения расстояния к северу от южного полюса вдоль международной линии дат, а затем расстояния на восток, начиная с этой точки на дату. линия. Для этого (а также для некоторых более общих задач измерения расстояния) у меня есть один метод определения расстояния между двумя точками широты / долготы и другой метод, который берет точку широты / долготы, направление и расстояние и возвращает точка широты / долготы в конце этого курса.

Вот два статических метода, которые я определил:

/* Takes two lon/lat pairs and returns the distance between them in kilometers.
*/
public static double distance (double lat1, double lon1, double lat2, double lon2) {
    double theta = toRadians(lon1-lon2);
    lat1 = toRadians(lat1);
    lon1 = toRadians(lon1);
    lat2 = toRadians(lat2);
    lon2 = toRadians(lon2);

    double dist = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(theta);
    dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;

    return dist;
}

/* endOfCourse takes a lat/lon pair, a heading (in degrees clockwise from north), and a distance (in kilometers), and returns
 * the lat/lon pair that would be reached by traveling that distance in that direction from the given point.
 */
public static double[] endOfCourse (double lat1, double lon1, double tc, double dist) {
    double pi = Math.PI;
    lat1 = toRadians(lat1);
    lon1 = toRadians(lon1);
    tc = toRadians(tc);
    double dist_radians = toRadians(dist / (60 * 1.1515 * 1.609344 * 1000));
    double lat = asin(sin(lat1) * cos(dist_radians) + cos(lat1) * sin(dist_radians) * cos(tc));
    double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
    double lon = ((lon1-dlon + pi) % (2*pi)) - pi;
    double[] endPoint = new double[2];
    endPoint[0] = lat; endPoint[1] = lon;
    return endPoint;
}

А вот функция, которую я использую для проверки:

public static void main(String args[]) throws java.io.IOException, java.io.FileNotFoundException {
    double distNorth = distance(0.0, 0.0, 72.0, 0.0);
    double distEast = distance(72.0, 0.0, 72.0, 31.5);
    double lat1 = endOfCourse(0.0, 0.0, 0.0, distNorth)[0];
    double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];
    System.out.println("end at: " + lat1 + " / " + lon1);
    return;
}

Значения «конца в» должны быть прибл. 72,0 / 31,5. Но вместо этого я получаю примерно 1,25 / 0,021.

Я предполагаю, что мне не хватает чего-то глупого, я забыл где-то преобразовать единицы или что-то еще ... Любая помощь будет принята с благодарностью!

ОБНОВЛЕНИЕ 1:

Я (правильно) написал функцию расстояния для возврата метров, но по ошибке написал километры в комментариях ... что, конечно, смутило меня, когда я вернулся к этому сегодня. В любом случае, теперь это исправлено, и я исправил ошибку факторинга в методе endOfCourse, и я также понял, что забыл преобразовать обратно в градусы из радианов в этом методе. В любом случае: хотя кажется, что теперь я получаю правильное число широты (71,99 ...), число долготы неверно (я получаю 3,54 вместо 11,5).

ОБНОВЛЕНИЕ 2: У меня была опечатка в тесте, как указано ниже. Теперь это исправлено в коде. Однако число долготы по-прежнему неверное: теперь я получаю -11,34 вместо 11,5. Я думаю, что с этими строками что-то не так:

double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
double lon = ((lon1-dlon + pi) % (2*pi)) - pi;

В качестве справочного материала вы можете ознакомиться с movable-type.co.uk/scripts/latlong-vincenty.html и movable-type.co.uk/scripts/latlong-vincenty-direct.html (реализации javascript включены.

Brendan Cashman 23.12.2008 19:00

В вашей первой функции было бы лучше использовать две переменные: 'double angle = ... 1st expression; double dist = ... 2-е выражение изменено на опорный угол; '. Фактически, первое значение - это вовсе не расстояние. Просто педантичная возня.

Jonathan Leffler 24.12.2008 02:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
14
2
20 334
4

Ответы 4

Проверить http://www.movable-type.co.uk/scripts/latlong.html

На этом сайте есть много различных формул и кода Javascript, которые должны вам помочь. Я успешно перевел его как на C#, так и на UDF SQL Server, и я использую их повсюду.

Например, для Javascript для расчета расстояния:

var R = 6371; // km
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();

var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
        Math.cos(φ1) * Math.cos(φ2) *
        Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

var d = R * c; 

Наслаждаться!

Ваше преобразование между км и радианами неверно. Морская миля составляет 1/60 градуса, поэтому предположим, что 1,15 ... это ваше преобразование из миль в морские мили, а 1,6 ... это преобразование из км в уставные мили,

   nm = km /  (1.1515 * 1.609344);
   deg = nm / 60;
   rad = toRadians(deg);

Другими словами, я думаю, что вы ошиблись в 1000 раз.

Ага. Я не имею ни малейшего представления, о чем я думал с помощью метода Distance; возвращает расстояние в метрах, а не в километрах.

DanM 23.12.2008 20:08

Что касается вашего обновленного вопроса: не следует

double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[0];

быть

double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];

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

Большая проблема заключалась в следующем: метод Distance (для вычисления расстояния между двумя точками) вычислял расстояния по большому кругу. Что, конечно, имеет смысл - это кратчайший путь между двумя точками. тем не мение, расстояние по дуге большого круга между двумя точками, лежащими на одной параллели (линии широты), НЕ совпадает с расстоянием между этими двумя точками при движении непосредственно вдоль линии широты, если только вы не находитесь на экваторе.

Итак: функции РАБОТАЮТ правильно; однако альтернативная система координат, которую я предложил в исходном вопросе, требует, чтобы мы смотрели только на расстояние на север вдоль IDL, а затем на расстояние на восток вдоль параллели на полученной широте. И вычисление расстояния по определенной параллели сильно отличается от вычисления расстояния по большому кругу!

В любом случае, вот оно.

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