Профили маршрутизации

Понятие профиля маршрутизации

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

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

  • автомобильный (fastest, shortest, eco)
  • пешеходный (walking)
  • велосипедный (cycling)
  • грузовой (truck, heavy vehicle restrictions)
  • мультимодальный (сочетание транспорта)

Профиль задаёт:

  • допустимые типы дорог
  • ограничения скорости
  • штрафы за повороты
  • запреты (oneway, access restrictions)
  • приоритеты дорог (highway > residential и т.д.)

Разделение ответственности: MapLibre GL JS и маршрутизация

MapLibre GL JS не выполняет маршрутизацию самостоятельно. Его задача — визуализация:

  • отображение векторных тайлов
  • рендеринг слоёв (layers)
  • работа с источниками данных (sources)
  • интерактивность карты (events, controls)
  • отрисовка геометрии маршрута (LineString)

Маршрутизация выполняется внешними сервисами:

  • OSRM
  • GraphHopper
  • Valhalla
  • коммерческие Directions API

MapLibre GL JS лишь:

  1. отправляет запрос к API маршрутов
  2. получает GeoJSON LineString
  3. визуализирует результат на карте

Архитектура взаимодействия маршрутизации с MapLibre

Типичная схема:

  1. Пользователь задаёт точки A и B
  2. Клиент отправляет запрос в routing API с параметром profile
  3. Routing engine вычисляет путь
  4. API возвращает GeoJSON или polyline
  5. MapLibre GL JS обновляет источник данных
  6. маршрут отображается как слой линии

Пример структуры ответа маршрутизатора:

{
  "routes": [
    {
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [73.1, 49.8],
          [73.2, 49.85]
        ]
      },
      "distance": 5230,
      "duration": 620
    }
  ]
}

Основные типы профилей

Автомобильный профиль

Автомобильный профиль ориентирован на минимизацию времени или расстояния с учётом дорожной сети.

Ключевые параметры:

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

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

GET /route/v1/driving/73.1,49.8;73.2,49.85?overview=full&geometries=geojson

Параметр driving — это профиль маршрутизации.


Пешеходный профиль

Пешеходный профиль учитывает:

  • тропинки и пешеходные зоны
  • лестницы
  • парки и проходы
  • запреты для транспорта

Он может отдавать предпочтение:

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

Пример:

GET /route/v1/foot/73.1,49.8;73.2,49.85

Велосипедный профиль

Велосипедные профили более сложны, чем пешеходные, поскольку учитывают:

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

В GraphHopper профиль может быть задан как:

profiles:
  - name: bike
    vehicle: bike
    weighting: fastest

Внутреннее устройство профиля маршрутизации

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

1. Весовая функция (weighting)

Определяет стоимость ребра графа:

cost = time + penalties + restrictions

Где:

  • time — время прохождения ребра
  • penalties — штрафы (повороты, светофоры)
  • restrictions — запреты

2. Скоростная модель

Каждому типу дороги назначается скорость:

Тип дороги Скорость (км/ч)
motorway 110
primary 80
residential 40
track 20

3. Ограничения доступа

  • vehicle access = yes/no
  • one way = forward/backward
  • toll roads
  • private roads

4. Turn penalties

Повороты могут увеличивать стоимость маршрута:

  • левый поворот: +2–5 секунд
  • разворот: +10–30 секунд
  • сложные развязки: дополнительный штраф

Подключение профиля маршрутизации к MapLibre GL JS

MapLibre GL JS работает с результатом маршрутизации как с GeoJSON-источником.

Добавление маршрута на карту

map.addSource('route', {
  type: 'geojson',
  data: {
    type: 'Feature',
    geometry: {
      type: 'LineString',
      coordinates: []
    }
  }
});

Отрисовка линии маршрута

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

Обновление маршрута после запроса

async function getRoute(start, end) {
  const response = await fetch(
    `https://router.example.com/route/v1/driving/${start};${end}?geometries=geojson`
  );

  const data = await response.json();

  const route = data.routes[0].geometry;

  map.getSource('route').setData({
    type: 'Feature',
    geometry: route
  });
}

Переключение профилей маршрутизации

Одна из ключевых задач интерфейса — динамическая смена профиля.

Пример логики:

let currentProfile = 'driving';

function setProfile(profile) {
  currentProfile = profile;
  updateRoute();
}

Запрос:

fetch(`https://router.example.com/route/v1/${currentProfile}/${coords}`)

Сравнение маршрутов разных профилей

Один и тот же маршрут может существенно отличаться:

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

В интерфейсах часто реализуется:

  • параллельный расчёт нескольких профилей
  • отображение альтернативных маршрутов
  • сравнение времени и расстояния

Продвинутые профили

Грузовой транспорт

Особенности:

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

Экологический профиль

Оптимизация:

  • минимизация выбросов CO₂
  • выбор маршрутов с равномерной скоростью
  • избегание пробок

Профиль “быстрее в реальном времени”

Использует:

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

Кастомные профили маршрутизации

В GraphHopper и OSRM можно создавать собственные профили.

Пример логики кастомного профиля:

function edgeWeight(edge) {
  let weight = edge.distance / edge.speed;

  if (edge.roadType === 'residential') {
    weight *= 1.2;
  }

  if (edge.isToll) {
    weight += 30;
  }

  return weight;
}

Формирование маршрута на стороне клиента

Хотя обычно маршрутизация выполняется сервером, возможен гибридный подход:

  • сервер отдаёт граф или упрощённые маршруты
  • клиент выполняет локальную фильтрацию
  • MapLibre GL JS визуализирует результат

Это применяется в:

  • офлайн-картах
  • приложениях с ограниченной связью
  • специализированных GIS-системах

Взаимодействие профилей с визуализацией

MapLibre GL JS позволяет визуально различать профили:

  • разные цвета линий
  • разные стили (dashed, solid)
  • анимация движения по маршруту

Пример стилизации:

paint: {
  'line-color': [
    'match',
    ['get', 'profile'],
    'driving', '#2563eb',
    'walking', '#16a34a',
    'cycling', '#f97316',
    '#000000'
  ],
  'line-width': 4
}

Масштабирование маршрутизации в реальных системах

При большом количестве запросов профили маршрутизации становятся узким местом.

Используются оптимизации:

  • предварительная индексация графа
  • contraction hierarchies
  • multi-level Dijkstra
  • кэширование популярных маршрутов
  • разделение профилей на отдельные сервисы

Ошибки при работе с профилями маршрутизации

Частые проблемы:

  • несоответствие профиля данным карты
  • отсутствие доступа к дорогам (bad OSM tagging)
  • игнорирование turn restrictions
  • неправильные скорости
  • смешение профилей в одном запросе

Интеграция профилей в пользовательский интерфейс

Обычно интерфейс включает:

  • переключатель профиля (car / bike / walk)
  • отображение ETA (estimated time of arrival)
  • сравнение альтернатив
  • визуализацию маршрута на MapLibre GL JS

При этом карта остаётся чисто визуальным слоем, а вся логика маршрутизации вынесена в отдельный сервисный слой архитектуры.