Tour Planning

Планирование туров в экосистеме HERE Technologies строится вокруг задач маршрутизации, оптимизации последовательности точек посещения и синхронизации геоданных с интерактивной картой. В JavaScript API этот процесс объединяет несколько уровней: отображение карты, работа с геокодированием, построение маршрутов и расчет оптимального порядка остановок.

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


Модель данных тура

Основой любого туристического маршрута выступает набор структурированных сущностей:

  • Waypoints (точки маршрута) — географические координаты или адреса
  • Start/End точки — начало и завершение маршрута
  • Stopovers (остановки) — промежуточные пункты
  • Constraints (ограничения) — временные окна, приоритеты, запреты на тип дорог
  • Transport mode — автомобиль, пешком, грузовой транспорт

Пример логической модели:

const tour = {
  start: "52.5200,13.4050",
  end: "52.5200,13.4050",
  waypoints: [
    "52.5160,13.3779",
    "52.5186,13.4081",
    "52.5096,13.3760"
  ],
  optimizeOrder: true
};

Инициализация карты и базового слоя маршрутов

Отображение тура начинается с инициализации карты и подключения слоя маршрутов:

const platform = new H.service.Platform({
  apikey: "YOUR_API_KEY"
});

const defaultLayers = platform.createDefaultLayers();

const map = new H.Map(
  document.getElementById("map"),
  defaultLayers.vector.normal.map,
  {
    center: { lat: 52.5200, lng: 13.4050 },
    zoom: 13
  }
);

Интерактивность обеспечивается через обработчики событий и систему объектов карты (Map Objects), позволяющую динамически добавлять точки маршрута.


Геокодирование точек тура

Перед построением маршрута адреса преобразуются в координаты через геокодирование:

const geocoder = platform.getSearchService();

geocoder.geocode(
  { q: "Alexanderplatz Berlin" },
  (result) => {
    const location = result.items[0].position;
    console.log(location);
  },
  (error) => {
    console.error(error);
  }
);

Геокодирование критично для туров, где пользователь задаёт не координаты, а текстовые описания мест.


Построение маршрута между точками

Маршрутизация выполняется через Routing API. В турпланировании ключевым режимом является оптимизация последовательности точек.

const routingService = platform.getRoutingService(null, 8);

const routingParameters = {
  routingMode: "fast",
  transportMode: "car",
  origin: "52.5200,13.4050",
  destination: "52.5200,13.4050",
  via: new H.service.Url.MultiValueQueryParameter([
    "52.5160,13.3779",
    "52.5186,13.4081",
    "52.5096,13.3760"
  ]),
  return: "polyline,summary"
};

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


Оптимизация порядка остановок

Оптимизация маршрута является центральной задачей Tour Planning. Алгоритм перестраивает порядок посещения точек для минимизации времени или расстояния.

routingParameters.optimizeWaypoints = true;

При включенной оптимизации система:

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

Использование Routing API для сложных туров

Для больших наборов точек используется расширенный запрос:

const request = {
  origin: "52.5200,13.4050",
  destination: "52.5200,13.4050",
  via: "52.5160,13.3779;52.5186,13.4081;52.5096,13.3760",
  return: "polyline,summary,actions",
  transportMode: "car",
  routingMode: "fast",
  optimizeWaypoints: true
};

Сервер возвращает:

  • геометрию маршрута (polyline)
  • последовательность сегментов
  • инструкции движения
  • суммарное время и расстояние

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

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

const lineString = H.geo.LineString.fromFlexiblePolyline(
  response.routes[0].sections[0].polyline
);

const routeLine = new H.map.Polyline(lineString, {
  style: { strokeColor: "blue", lineWidth: 4 }
});

map.addObject(routeLine);

Дополнительно добавляются маркеры остановок:

const marker = new H.map.Marker({ lat: 52.5160, lng: 13.3779 });
map.addObject(marker);

Многоэтапные туры и сегментация

Сложные туры часто разбиваются на сегменты:

  • утренний маршрут
  • дневной маршрут
  • вечерний маршрут

Каждый сегмент рассчитывается отдельно, затем объединяется логически.

const segments = [
  { start: A, stops: [B, C], end: D },
  { start: D, stops: [E, F], end: A }
];

Такой подход снижает вычислительную сложность и повышает управляемость маршрута.


Матрица расстояний для туроптимизации

Для сценариев с большим количеством точек используется Distance Matrix API:

const matrixParams = {
  origins: ["52.5200,13.4050", "52.5160,13.3779"],
  destinations: ["52.5186,13.4081", "52.5096,13.3760"],
  transportMode: "car"
};

Результат представляет собой таблицу расстояний и времени между всеми парами точек, что используется для построения оптимального тура.


Временные окна и ограничения

В реальных сценариях туры ограничиваются временем:

  • доступность локаций
  • график работы
  • длительность посещения

Логика обработки:

const constraints = {
  timeWindows: [
    { start: "09:00", end: "11:00" },
    { start: "12:00", end: "15:00" }
  ]
};

При расчёте маршрута система учитывает невозможность прибытия в недоступные интервалы.


Интерактивное обновление тура

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

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

Каждое изменение инициирует пересчет маршрута:

tour.waypoints.push("52.5210,13.4090");
recalculateRoute(tour);

Интерактивность обеспечивается пересозданием маршрута без перезагрузки карты.


Визуализация оптимизированного тура

Визуальная структура тура включает:

  • основной маршрут
  • альтернативные ветки
  • пронумерованные точки посещения
  • временные метки

Нумерация точек добавляется через кастомные маркеры:

const icon = new H.map.Icon("number-icon.png");
const numberedMarker = new H.map.Marker(position, { icon });

Производительность при масштабных турах

При увеличении числа точек возникает необходимость оптимизации:

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

Особенно критично при количестве точек > 25, где задача становится вычислительно сложной.


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

Tour Planning часто связывается с UI-компонентами:

  • списки остановок (drag-and-drop)
  • временные шкалы маршрута
  • фильтры типов локаций
  • режимы просмотра (карта/список/граф)

Изменение UI состояния напрямую влияет на пересчет маршрута через события:

ui.on("reorder", (newOrder) => {
  tour.waypoints = newOrder;
  recalculateRoute(tour);
});

Обработка ошибок маршрутизации

Типичные ошибки:

  • недоступные дороги
  • некорректные координаты
  • превышение лимитов API
  • отсутствие маршрута между точками

Обработка выполняется через callback ошибки:

(error) => {
  if (error) {
    console.log("Route calculation failed");
  }
};

Расширенные сценарии турпланирования

Сложные применения включают:

  • логистика доставки с множеством точек
  • экскурсионные маршруты
  • мобильные сервисные бригады
  • мультимодальные маршруты (авто + пешком)

В таких сценариях комбинируются несколько API: routing, geocoding, matrix, fleet optimization.


Структурирование больших маршрутов

При росте количества точек применяется иерархическая модель:

  • уровень 1: кластеры точек
  • уровень 2: маршруты внутри кластеров
  • уровень 3: объединяющий маршрут

Такой подход снижает нагрузку на Routing API и повышает стабильность вычислений.