Вычислить точку между двумя координатами в процентах

Я ищу функцию, которая возвращает точку (широта, долгота) между двумя точками (где я также указываю их широту и долготу), и эта точка основана на проценте расстояния.

Итак, я указываю Lat1, Lon1, Lat2, Lon2 и% в функции, и она возвращает точку, например, удаленную на 20% от первой точки до второй.


person mignz    schedule 25.11.2015    source источник
comment
Если вы работаете с API Карт Google, ознакомьтесь с интерполировать, который вычисляет точку между двумя другими точками с некоторой долей (0-1) между ними.   -  person Christiaan Westerbeek    schedule 04.01.2017


Ответы (3)


Предполагая, что координата является десятичным числом. Вы можете использовать это уравнение.

function midpoint(lat1, long1, lat2, long2, per) {
     return [lat1 + (lat2 - lat1) * per, long1 + (long2 - long1) * per];
}

Верните новую желаемую координату [широта, долгота] на основе процента (например, per = 0,2 для 20%).

person lguiel    schedule 25.11.2015
comment
Средняя точка долготы широты обычно не является средней точкой, вычисляемой по этой формуле, потому что это координаты на сфере, а не на плоской поверхности. - person spirographer; 25.11.2015
comment
Iguiel Я тоже думал об этом, но это не работает. Например, для P1 (37,740675, -25,661043) и P2 (37,738096, -25,669267) 20% возвращает P3 (7,5478771, -5,133031). Это помещает меня в Африку, а не на Азорские острова между точками P1 и P2. - person mignz; 25.11.2015
comment
Привет, Swift-R, я вижу, я думаю, что в моем уравнении есть ошибка, оно должно быть: [lat1 + (lat2-lat1) * per, long1 + (long2-long1) * per] Я отредактирую свой ответ. Надеюсь, это сработает для вас. - person lguiel; 25.11.2015
comment
Помимо карт, это действительно хорошая функция для других творческих вещей, связанных с javascript - я взял ее для тест-драйва в этой ручке codepen.io/headwinds/pen/BLVXwa?editors=0010 - person headwinds; 14.10.2016
comment
Это уравнение НЕ является математически правильным. Линейная интерполяция широты и долготы не является правильной сферической математикой. - person Meekohi; 19.06.2018

Вот ссылка, которая очень поможет (проверьте внизу)

http://www.movable-type.co.uk/scripts/latlong.html

Промежуточная точка

Также может быть вычислена промежуточная точка в любой части пути большого круга между двумя точками.

Формула:

a = sin((1−f)⋅δ) / sin δ
b = sin(f⋅δ) / sin δ
x = a ⋅ cos φ1 ⋅ cos λ1 + b ⋅ cos φ2 ⋅ cos λ2
y = a ⋅ cos φ1 ⋅ sin λ1 + b ⋅ cos φ2 ⋅ sin λ2
z = a ⋅ sin φ1 + b ⋅ sin φ2
φi = atan2(z, √x² + y²)
λi = atan2(y, x)

где f - дробь вдоль маршрута большого круга (f = 0 - точка 1, f = 1 - точка 2), δ < / em> - угловое расстояние d / R между двумя точками.

person spirographer    schedule 25.11.2015
comment
Не понимаю, где тут процент. - person mignz; 25.11.2015
comment
f - это доля от точки 1 до точки 2. Процент - это дробь, знаменатель которой равен 100. Например, если ваш процент равен 39%, тогда дробь f = 39/100 . - person spirographer; 25.11.2015

Оба ответа могут быть полезны для определенных пользователей, но я хотел бы указать на некоторые проблемы.

Решение lguiel подходит для игр или небольших расстояний, но не работает для геометрических вычислений на Земле как глобусе.

Ответ спирографа правильный, но, поскольку он носит теоретический характер, его может быть слишком сложно запрограммировать.

Я перевел второй ответ на практический язык программирования, чтобы вы могли использовать его в своих проектах.

Полный код | Запускать в Интернете

// Original calculation from https://www.movable-type.co.uk/scripts/latlong.html
LatLng calculateIntermediatePoint(LatLng point1, LatLng point2, double perc) {
  //const φ1 = this.lat.toRadians(), λ1 = this.lon.toRadians();
  //const φ2 = point.lat.toRadians(), λ2 = point.lon.toRadians();
  double lat1 = degreesToRadians(point1.latitude);
  double lng1 = degreesToRadians(point1.longitude);
  double lat2 = degreesToRadians(point2.latitude);
  double lng2 = degreesToRadians(point2.longitude);

  //const Δφ = φ2 - φ1;
  //const Δλ = λ2 - λ1;
  double deltaLat = lat2 - lat1;
  double deltaLng = lng2 - lng1;

  //const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ/2) * Math.sin(Δλ/2);
  //const δ = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  double calcA = sin(deltaLat / 2) * sin(deltaLat / 2) +
      cos(lat1) * cos(lat2) * sin(deltaLng / 2) * sin(deltaLng / 2);
  double calcB = 2 * atan2(sqrt(calcA), sqrt(1 - calcA));

  //const A = Math.sin((1-fraction)*δ) / Math.sin(δ);
  //const B = Math.sin(fraction*δ) / Math.sin(δ);
  double A = sin((1 - perc) * calcB) / sin(calcB);
  double B = sin(perc * calcB) / sin(calcB);

  //const x = A * Math.cos(φ1) * Math.cos(λ1) + B * Math.cos(φ2) * Math.cos(λ2);
  //const y = A * Math.cos(φ1) * Math.sin(λ1) + B * Math.cos(φ2) * Math.sin(λ2);
  //const z = A * Math.sin(φ1) + B * Math.sin(φ2);
  double x = A * cos(lat1) * cos(lng1) + B * cos(lat2) * cos(lng2);
  double y = A * cos(lat1) * sin(lng1) + B * cos(lat2) * sin(lng2);
  double z = A * sin(lat1) + B * sin(lat2);

  //const φ3 = Math.atan2(z, Math.sqrt(x*x + y*y));
  //const λ3 = Math.atan2(y, x);
  double lat3 = atan2(z, sqrt(x * x + y * y));
  double lng3 = atan2(y, x);

  //const lat = φ3.toDegrees();
  //const lon = λ3.toDegrees();
  return LatLng(radiansToDegrees(lat3), radiansToDegrees(lng3));
}
person James Cameron    schedule 28.01.2020