Гугл карты: как измерить расстояние «по линейке» через гугл скрипт

Google maps умеет измерять расстояние по прямой через «измерить расстояние» по правому клику мыши на картах:

Делает он это через определения долготы и широты. Так, например, чтобы измерить расстояние от Москвы до Волгограда на картах необходимо добавить 2 точки и получить результат в 919,23 км

А что если надо получать этот же результат, но уже как число в гугл таблицах?

Class Geocoder

Получить долготу и широту в гугл скриптах можно через класс Geocoder:

function geoTest() {
  const response = Maps.newGeocoder().geocode('Москва')
  console.log(response)
}

Geocode возвращает объект с данными, где помимо всего прочего содержится массив, в котором по ключу геометрии можно получить широту и долготу

Если посмотреть в response.results, который является массивом, первый [0] элемент массива будет объект c ключом geometry:

В котором есть объект по ключу location.

Итого полный путь до долготы и широты будет: response.results[0].geometry.location с результатом { lng: 37.6173, lat: 55.755826 }

Мне нужны эти данные виде переменных.

Дестуктуризация объекта

Деструктурирующее присваивание – это специальный синтаксис, который позволяет «распаковать» объекты в переменные, так как иногда это более удобно.

Более подробно можно почитать тут — https://learn.javascript.ru/destructuring-assignment

function geoTest() {
  const response = Maps.newGeocoder().geocode('Москва')
  const {lat, lng} = response.results[0].geometry.location;
  console.log(lat, lng)
}

Если данные из объекта необходимо передать в свои переменные отличные от имени ключа, доступен следующий синтаксис:

function geoTest() {
  const response = Maps.newGeocoder().geocode('Москва')
  const {lat: lat1, lng: lng1} = response.results[0].geometry.location;
  console.log('lat1: ' + lat1,'lng1: ' + lng1)
}

Результат будет следующим:

Как измерить расстояние

Сначала продемонстрирую скрипт:

function geoCodeBasic(cityStart = 'Москва', cityEnd = 'Волгоград'){
  const responseStart = Maps.newGeocoder().geocode(cityStart);
  let {lat: lat1, lng: lng1} = responseStart.results[0].geometry.location

  const responseEnd = Maps.newGeocoder().geocode(cityEnd);
  let {lat: lat2, lng: lng2} = responseEnd.results[0].geometry.location
  
  const km = distance(lat1, lng1, lat2, lng2)
  console.log(km)

}

function distance(lat1, lon1, lat2, lon2) {
  const p = 0.017453292519943295;    // Math.PI / 180
  const c = Math.cos;
  const a = 0.5 - c((lat2 - lat1) * p)/2 + 
          c(lat1 * p) * c(lat2 * p) * 
          (1 - c((lon2 - lon1) * p))/2;

  return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}

Первая часть понятна и разобрана выше. Что может немного смутить:

(cityStart = 'Москва', cityEnd = 'Волгоград')значения параметров функции по умолчанию.

Расстояние через формулу гаверсин

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

Сложные детали для тех, кто хочет понять суть — https://en.wikipedia.org/wiki/Haversine_formula

Если чуть-чуть озаботиться гуглением переложения формулы гаверсин на js, то найдется следующая функция расчета расстояния:

function distance(lat1, lon1, lat2, lon2) {
  const p = 0.017453292519943295;    // Math.PI / 180
  const c = Math.cos;
  const a = 0.5 - c((lat2 - lat1) * p)/2 + 
          c(lat1 * p) * c(lat2 * p) * 
          (1 - c((lon2 - lon1) * p))/2;

  return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}

И результат расчета расстояния между Москвой и Волгоградом «по линейке» через гугл скрипт будет следующим:

Что почти равно указанному выше на скриншоте гугл карт в 919 километров. Разница заключается в том, что при расчете через скрипт берутся фактические координаты Москвы и Волгограда по данным гугла. Так, например, Москва в базе данных гугла считается от нулевого километра. В то время как при клике на «Москву» точность может быть иной.

Чтобы функция заработала как формула, необходим внести следующие изменения:

  const km = distance(lat1, lng1, lat2, lng2)
  console.log(km)

Заменить на:

  return distance(lat1, lng1, lat2, lng2)

Добавить комментарий