Это продолжение этот вопрос.
Кажется, я зациклился на этом. По сути, мне нужно иметь возможность конвертировать туда и обратно для ссылки на координаты либо в стандартной системе градусов, либо путем измерения расстояния к северу от южного полюса вдоль международной линии дат, а затем расстояния на восток, начиная с этой точки на дату. линия. Для этого (а также для некоторых более общих задач измерения расстояния) у меня есть один метод определения расстояния между двумя точками широты / долготы и другой метод, который берет точку широты / долготы, направление и расстояние и возвращает точка широты / долготы в конце этого курса.
Вот два статических метода, которые я определил:
/* 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;
В вашей первой функции было бы лучше использовать две переменные: 'double angle = ... 1st expression; double dist = ... 2-е выражение изменено на опорный угол; '. Фактически, первое значение - это вовсе не расстояние. Просто педантичная возня.





Проверить 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; возвращает расстояние в метрах, а не в километрах.
Что касается вашего обновленного вопроса: не следует
double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[0];
быть
double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];
Я понял большую проблему с этими формулами, помимо ошибок реализации, упомянутых в других ответах и обновлениях.
Большая проблема заключалась в следующем: метод Distance (для вычисления расстояния между двумя точками) вычислял расстояния по большому кругу. Что, конечно, имеет смысл - это кратчайший путь между двумя точками. тем не мение, расстояние по дуге большого круга между двумя точками, лежащими на одной параллели (линии широты), НЕ совпадает с расстоянием между этими двумя точками при движении непосредственно вдоль линии широты, если только вы не находитесь на экваторе.
Итак: функции РАБОТАЮТ правильно; однако альтернативная система координат, которую я предложил в исходном вопросе, требует, чтобы мы смотрели только на расстояние на север вдоль IDL, а затем на расстояние на восток вдоль параллели на полученной широте. И вычисление расстояния по определенной параллели сильно отличается от вычисления расстояния по большому кругу!
В любом случае, вот оно.
В качестве справочного материала вы можете ознакомиться с movable-type.co.uk/scripts/latlong-vincenty.html и movable-type.co.uk/scripts/latlong-vincenty-direct.html (реализации javascript включены.