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)