Skip to content

Use Case #2: «Out & Back» (Возврат на старт) и проблема наложения линий

Терминологическая оговорка (Product Management Context): В индустрии эти функции обычно разделяют:

  1. Return to Start (Возврат на старт): Система строит путь от последней точки обратно к первой кратчайшим/оптимальным путем. Он может пойти по новой дороге, а может частично/полностью по старой.
  2. Out & Back (Туда-обратно - классика): Система берет весь трек и строго зеркалит его. Мы возвращаемся "след в след" по тем же самым дорогам (А → Б → С → Б → А).

1. Интент (Намерение пользователя)

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

2. Идеальная логика системы

  • Создание финиша: Создается новая точка «Финиш» (D), координаты которой полностью совпадают с точкой «Старт» (А).
  • Смена ролей: Точка (С), которая была финишем, становится промежуточной (Waypoint) с иконкой «Разворот» (U-turn) или просто порядковым номером.
  • Построение маршрута: Алгоритм строит путь от С к D(А) согласно выбранному типу активности (и/или зеркалит существующий трек в случае строгого Out & Back).

3. UI и решение проблемы наложения (Visual Overlapping)

Проблема: Если обратный путь совпадает с путем "туда", линия накладывается сама на себя пиксель-в-пиксель. Юзер смотрит на карту и не понимает — кнопка сработала? Почему дистанция выросла, а линия осталась той же?

Решения (Best Practices):

  1. Двунаправленные шевроны (База): На линии трека обязательно должны быть стрелки направления движения ( >>> ). Если участок едется в обе стороны, стрелки должны показывать встречное движение: > < > < > < или использоваться специальный паттерн двойных стрелок.
  2. Смещение линии / Parallel Offset (Высший пилотаж): Если два ребра графа (путь туда и обратно) полностью совпадают, линия обратного пути отрисовывается со смещением на 2-4 пикселя вбок (имитируя правостороннее движение). Получается "двойная сплошная", и юзер четко видит две нитки маршрута.
  3. Стилевое кодирование: Путь "туда" — сплошная линия. Путь "обратно" (если он накладывается) рисуется поверх пунктирной линией другого оттенка, сквозь которую проглядывает нижняя.
  4. Связка с графиком высот (Elevation Profile): При клике на возврат график внизу экрана должен удлиниться в два раза. При наведении курсора на вторую половину графика, точка-маркер на карте должна бежать в обратную сторону. Это моментально снимает все вопросы пользователя.

Эпики и Задачи (Epics & Tasks)

Декомпозиция Use Case #2 для разработки.

Epic 1: Логика состояния "Возврат на старт" (Return to Start State)

  • Task 1.1: Быстрое замыкание (Action Button).
    • Добавить в UI кнопку "Return to Start" (или "Out & Back").
    • При нажатии логика в plannerStore автоматически копирует координаты точки [0] и вставляет их в конец массива точек. Предпоследняя точка становится Waypoint'ом.
  • Task 1.2: Strict Out & Back vs Return to Start (Опционально).
    • Разделить логику: если выбран "Out & Back", фронтенд не делает запрос к BRouter, а локально дублирует и реверсит массив LineString-геометрии (А → Б превращается в А → Б → А), экономя ресурсы API. Если "Return to Start" — делается стандартный API запрос от Б к А.

Epic 3: Решение проблемы визуального наложения (Visual Overlapping)

  • Task 3.1: Двунаправленные шевроны (Bi-directional Chevrons).
    • Обновить слой symbol в MapLibre (useRouteLayer.ts). Использовать иконку стрелки. Настроить symbol-placement: line и проверять наложение, чтобы визуализировать направление "Туда" и "Обратно" на перекрывающихся сегментах.
  • Task 3.2: Parallel Offset (Смещение линии).
    • Изучить возможность использования свойства line-offset в MapLibre GL JS для обратного трека.
    • Написать утилиту, определяющую совпадающие (пересекающиеся) сегменты маршрута, и выносить их в отдельный слой (или применять динамический offset в зависимости от направления).
  • Task 3.3: Стилевое кодирование (Dashed Overlay).
    • Настроить line-dasharray для слоя обратного маршрута. Подобрать цвета в theme.ts так, чтобы нижний слой просвечивал через верхний, визуально объединяя их в двустороннюю дорогу.

Epic 4: Интеграция с Elevation Profile (График высот)

  • Task 4.1: Бесшовное удвоение графика.
    • Гарантировать, что компонент ElevationProfile мгновенно перерисовывается при возврате, удваивая общую дистанцию.
    • Если это "Out & Back" — зеркально отразить профиль высот без лишних запросов к API.
  • Task 4.2: Обратный трекинг по графику (Reverse Hover Tracking).
    • Связать события onMouseMove на графике высот с позицией маркера на карте.
    • Убедиться, что при наведении на вторую (обратную) часть графика, маркер корректно движется в обратном направлении (от Б к А) по перекрывающейся линии.