Расчет времени в пути

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

В Mapbox GL JS отображение маршрутов и работа с данными маршрутизации обычно разделяются на два уровня:

  • визуализация геометрии маршрута на карте
  • получение маршрута и его метаданных через API

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


Использование Directions API для получения времени маршрута

Основной источник данных о времени в пути — сервис маршрутизации Mapbox. Он возвращает маршрут в виде GeoJSON-подобной структуры с набором метаданных, где ключевым параметром является duration.

Запрос к API маршрута формируется через HTTP:

const accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';

const url = `https://api.mapbox.com/directions/v5/mapbox/driving/30.3351,59.9343;30.3609,59.9227
  ?alternatives=false
  &geometries=geojson
  &steps=true
  &access_token=${accessToken}`;

fetch(url)
  .then(res => res.json())
  .then(data => {
    const route = data.routes[0];
    console.log(route.duration);
  });

Поле duration возвращается в секундах и отражает оценочное время прохождения всего маршрута.


Интерпретация duration и distance

Каждый маршрут содержит несколько ключевых метрик:

  • distance — длина маршрута в метрах
  • duration — время в секундах
  • legs — сегменты маршрута между точками

Пример структуры:

{
  "routes": [
    {
      "distance": 5230.4,
      "duration": 812.6,
      "legs": [
        {
          "distance": 5230.4,
          "duration": 812.6
        }
      ]
    }
  ]
}

Перевод в удобный формат обычно выполняется на стороне клиента:

function formatDuration(seconds) {
  const minutes = Math.round(seconds / 60);
  return `${minutes} мин`;
}

Отображение маршрута в Mapbox GL JS

После получения геометрии маршрута данные добавляются как источник (source) и слой (layer):

map.on('load', () => {
  map.addSource('route', {
    type: 'geojson',
    data: {
      type: 'Feature',
      geometry: route.geometry
    }
  });

  map.addLayer({
    id: 'route-line',
    type: 'line',
    source: 'route',
    paint: {
      'line-color': '#3b82f6',
      'line-width': 5
    }
  });
});

Время в пути обычно связывается с UI-элементами:

document.getElementById('time').textContent =
  formatDuration(route.duration);

Учёт дорожного трафика

Расчёт времени может учитывать трафик при использовании соответствующих профилей маршрутизации:

  • driving
  • driving-traffic

При включении трафика значение duration становится динамическим и зависит от времени суток.

const url = `https://api.mapbox.com/directions/v5/mapbox/driving-traffic/${coords}
  ?access_token=${accessToken}`;

Разница между режимами:

  • driving — статическая модель скорости
  • driving-traffic — прогноз с учётом текущей и исторической загруженности дорог

Матрица времени в пути (Matrix API)

Для расчёта времени между множеством точек используется Matrix API. Он возвращает таблицу попарных значений времени.

Пример запроса:

const url = `https://api.mapbox.com/directions-matrix/v1/mapbox/driving/30.3,59.9;30.4,59.92;30.5,59.91
  ?access_token=${accessToken}`;

fetch(url)
  .then(res => res.json())
  .then(data => {
    console.log(data.durations);
  });

Результат:

{
  "durations": [
    [0, 120, 240],
    [110, 0, 180],
    [230, 190, 0]
  ]
}

Каждое значение — время в секундах между точками.


Использование матрицы для задач маршрутизации

Matrix API применяется для:

  • поиска ближайшей точки
  • оптимизации маршрутов доставки
  • расчёта времени до нескольких объектов

Пример поиска минимального времени:

function findNearest(durations) {
  const origin = durations[0];
  let min = Infinity;
  let index = -1;

  for (let i = 1; i < origin.length; i++) {
    if (origin[i] < min) {
      min = origin[i];
      index = i;
    }
  }

  return { index, time: min };
}

Расчёт времени через геометрию маршрута

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

function estimateTime(distanceMeters, avgSpeedKmh) {
  const distanceKm = distanceMeters / 1000;
  return (distanceKm / avgSpeedKmh) * 3600;
}

Этот подход используется:

  • при отсутствии маршрута
  • для предварительных оценок
  • в офлайн-режимах

Обновление времени в реальном времени

При движении объекта по маршруту время пересчитывается динамически. Логика основана на остаточном расстоянии.

function remainingTime(remainingDistance, avgSpeedKmh) {
  return estimateTime(remainingDistance, avgSpeedKmh);
}

Визуализация часто включает:

  • прогресс движения по линии
  • обновление ETA (estimated time of arrival)
  • пересчёт при отклонении от маршрута

Привязка времени к геометрии маршрута

Маршрут состоит из набора координат. Для более точного расчёта используется сегментация:

function segmentDistance(coords) {
  let total = 0;

  for (let i = 1; i < coords.length; i++) {
    const [x1, y1] = coords[i - 1];
    const [x2, y2] = coords[i];

    total += Math.sqrt((x2 - x1)**2 + (y2 - y1)**2);
  }

  return total;
}

Хотя это упрощённая модель (без проекции на сферу), она используется в визуальных слоях для оценки прогресса.


Интеграция времени маршрута в интерфейс Mapbox GL JS

Типичный сценарий объединяет маршрут и UI:

map.on('click', (e) => {
  const coords = `${startLng},${startLat};${e.lngLat.lng},${e.lngLat.lat}`;

  fetch(`https://api.mapbox.com/directions/v5/mapbox/driving/${coords}?access_token=${accessToken}`)
    .then(res => res.json())
    .then(data => {
      const route = data.routes[0];

      map.getSource('route').setData(route.geometry);

      document.getElementById('eta').textContent =
        Math.round(route.duration / 60) + ' мин';
    });
});

Кэширование результатов маршрутизации

Для уменьшения количества запросов применяются стратегии кэширования:

  • кэш по координатам (hash)
  • округление координат до сетки
  • хранение результатов в memory cache или localStorage
const cache = new Map();

function getCachedRoute(key) {
  return cache.get(key);
}

function setCachedRoute(key, value) {
  cache.set(key, value);
}

Пограничные случаи и особенности расчёта

При работе с временем маршрута возникают специфические ситуации:

  • отсутствие дорог между точками
  • резкое изменение трафика
  • закрытые дороги или ограничения
  • альтернативные маршруты с разным временем

В таких случаях API возвращает несколько маршрутов:

data.routes.forEach(r => {
  console.log(r.duration, r.distance);
});

Выбор маршрута обычно производится по минимальному duration, если не задана иная стратегия оптимизации.