Расчёт расстояний между точками в Google Maps JavaScript API опирается на несколько уровней абстракции: геодезические вычисления, сферическая геометрия, сервисы маршрутизации и вспомогательные библиотеки. В зависимости от задачи используется либо математическое расстояние по поверхности Земли, либо дорожная дистанция, учитывающая реальную дорожную сеть.
Земля в большинстве расчётов в картографических API рассматривается как сфера или эллипсоид. В Google Maps JavaScript API чаще применяется сферическая модель с радиусом Земли:
R ≈ 6 371 000 м
Основная задача — вычислить кратчайшее расстояние по дуге большого круга между двумя точками, заданными координатами широты и долготы.
Классическая формула расчёта расстояния между двумя точками:
d = 2R ()
где:
Эта формула устойчива к численным ошибкам при малых расстояниях и широко применяется в геоинформационных системах.
function toRad(value) {
return value * Math.PI / 180;
}
function haversineDistance(lat1, lng1, lat2, lng2) {
const R = 6371000;
const dLat = toRad(lat2 - lat1);
const dLng = toRad(lng2 - lng1);
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
Math.sin(dLng / 2) * Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
Подход используется, когда необходимо быстро оценить расстояние без обращения к внешним сервисам.
В Google Maps JavaScript API встроен модуль geometry,
предоставляющий оптимизированные функции для работы с расстояниями и
геометрией.
Подключение:
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEY&libraries=geometry"></script>
Основная функция:
const pointA = new google.maps.LatLng(55.751244, 37.618423);
const pointB = new google.maps.LatLng(59.934280, 30.335099);
const distance = google.maps.geometry.spherical.computeDistanceBetween(
pointA,
pointB
);
console.log(distance);
Особенности:
Для ломаных линий используется расчёт длины полилинии:
const path = [
new google.maps.LatLng(55.751244, 37.618423),
new google.maps.LatLng(56.326797, 44.006516),
new google.maps.LatLng(59.934280, 30.335099)
];
const length = google.maps.geometry.spherical.computeLength(path);
Метод суммирует расстояния между последовательными точками.
Геодезическое расстояние не учитывает дороги, пробки и ограничения движения. Для реальных сценариев используется сервис маршрутов.
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin: { lat: 55.751244, lng: 37.618423 },
destination: { lat: 59.934280, lng: 30.335099 },
travelMode: google.maps.TravelMode.DRIVING
},
(result, status) => {
if (status === "OK") {
console.log(result.routes[0].legs[0].distance.value);
}
}
);
routes[]
legs[]
учитывает дорожную сеть
может изменяться во времени (пробки, перекрытия)
зависит от travelMode:
Геодезическое расстояние:
Маршрутное расстояние:
При работе с большим количеством координат возникает задача оптимизации вычислений.
function buildDistanceMatrix(points) {
const matrix = [];
for (let i = 0; i < points.length; i++) {
matrix[i] = [];
for (let j = 0; j < points.length; j++) {
matrix[i][j] = google.maps.geometry.spherical.computeDistanceBetween(
points[i],
points[j]
);
}
}
return matrix;
}
Сложность O(n²), что важно учитывать при больших наборах данных.
Встроенный сервис:
const service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [
{ lat: 55.751244, lng: 37.618423 }
],
destinations: [
{ lat: 59.934280, lng: 30.335099 }
],
travelMode: google.maps.TravelMode.DRIVING
},
(response, status) => {
console.log(response.rows[0].elements[0].distance.value);
}
);
Преимущества:
При визуализации расстояний на карте возникает дополнительная проблема искажений проекций. В Google Maps JavaScript API используется проекция Mercator.
Искажения:
Поэтому:
Маршруты часто представляются как набор сегментов:
const polyline = new google.maps.Polyline({
path: [
{ lat: 55.75, lng: 37.61 },
{ lat: 56.32, lng: 44.00 },
{ lat: 59.93, lng: 30.33 }
]
});
const distance = google.maps.geometry.spherical.computeLength(polyline.getPath());
Использование полилиний позволяет:
При интенсивной работе с координатами применяются стратегии оптимизации:
Пример bounding box фильтра:
function inBounds(point, bounds) {
return (
point.lat >= bounds.minLat &&
point.lat <= bounds.maxLat &&
point.lng >= bounds.minLng &&
point.lng <= bounds.maxLng
);
}
Типичные источники погрешностей:
Поведение API:
В реальных приложениях часто комбинируются методы:
Такая многоуровневая архитектура снижает нагрузку и повышает точность итоговых данных