Path Style Extension

Назначение расширения PathStyleExtension

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

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

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


Архитектурная модель расширения

PathStyleExtension работает как слой абстракции над атрибутной системой deck.gl. Вместо фиксированных uniform-параметров, стилизация переносится в instanced attributes, вычисляемые на уровне каждого объекта данных.

Основные принципы:

  • переход от глобальных стилей слоя к пер-объектной стилизации
  • использование GPU-атрибутов вместо CPU-рендеринга геометрии
  • расширение стандартного пайплайна PathLayer без изменения исходного API данных

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


Подключение расширения

PathStyleExtension передаётся в массив extensions слоя:

import {PathLayer} fr om '@deck.gl/layers';
import {PathStyleExtension} from '@deck.gl/extensions';

const layer = new PathLayer({
  id: 'paths',
  data: paths,
  getPath: d => d.path,
  getColor: d => d.color,
  getWidth: d => d.width,
  extensions: [new PathStyleExtension({offset: true})]
});

Флаг offset включает поддержку смещения линии относительно её геометрического центра, что позволяет реализовывать сложные визуальные эффекты, такие как параллельные трассы или многополосные маршруты.


Пер-объектная стилизация линий

Основная ценность PathStyleExtension заключается в возможности задавать стиль через функции доступа (accessors), возвращающие значения для каждого объекта.

Толщина линии

getWidth: d => d.thickness

Толщина может задаваться в различных единицах (пиксели или метры), в зависимости от настроек слоя:

widthUnits: 'meters'

или

widthUnits: 'pixels'

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


Управление соединениями линий

PathStyleExtension предоставляет доступ к параметрам, управляющим поведением соединений сегментов.

Тип соединения (joins)

Поддерживаются следующие типы:

  • miter — острые углы
  • round — скруглённые соединения
  • bevel — срезанные углы

Пример:

getJointType: d => d.jointType

Где значение может быть строкой или числовым кодом, в зависимости от реализации данных.


Обработка окончаний линий (caps)

Окончания линий влияют на визуальное восприятие траекторий, особенно при отображении маршрутов и потоков.

Поддерживаемые варианты:

  • butt — обрезанное окончание
  • round — округлое окончание
  • square — квадратное продолжение

Пример динамического задания:

getCapRounded: d => d.roundEnds

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


Дашированные линии

Одной из ключевых функций PathStyleExtension является поддержка dashed-геометрии на уровне GPU.

getDashArray: d => d.dashPattern

Формат массива обычно задаёт последовательность:

[длина_штриха, длина_пробела]

Пример:

getDashArray: d => [10, 5]

или более сложные паттерны:

getDashArray: d => [8, 4, 2, 4]

Это позволяет создавать визуально различимые классы маршрутов: активные, второстепенные, временные или скрытые.


Смещение линий (offset rendering)

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

new PathStyleExtension({offset: true})

И соответствующий accessor:

getOffset: d => d.sideOffset

Применение:

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

Внутри WebGL смещение рассчитывается перпендикулярно направлению сегмента, что обеспечивает корректное поведение на кривых участках.


Митр-ограничения и сглаживание углов

Для острых соединений используется параметр miter lim it, который ограничивает длину «острия» на углах.

getMiterLimit: d => d.miterLimit

При превышении порога система автоматически переключается на bevel-режим, предотвращая артефакты растяжения геометрии.


Взаимодействие с PathLayer

PathStyleExtension не заменяет PathLayer, а расширяет его внутреннюю модель атрибутов. Это означает:

  • исходный API слоя остаётся неизменным
  • расширение внедряется через pipeline атрибутов
  • шейдеры автоматически переключаются на extended-вариант

Типичный набор параметров слоя:

new PathLayer({
  data,
  getPath: d => d.path,
  getColor: d => d.color,
  getWidth: d => d.width,
  widthMinPixels: 1,
  widthMaxPixels: 10,
  extensions: [new PathStyleExtension()]
});

Производительность и GPU-оптимизация

PathStyleExtension проектировался с учётом минимизации CPU-overhead. Основные оптимизации:

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

Это особенно важно при работе с большими наборами геоданных:

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

Особенности комбинирования стилей

PathStyleExtension позволяет комбинировать несколько параметров одновременно, создавая сложные визуальные модели:

  • переменная толщина + dashed pattern
  • offset + разные caps
  • цветовая интерполяция + joins

Пример комплексной конфигурации:

new PathLayer({
  data,
  getPath: d => d.path,
  getColor: d => d.color,
  getWidth: d => d.width,
  getDashArray: d => d.dash,
  getOffset: d => d.offset,
  extensions: [new PathStyleExtension({offset: true})]
});

Ограничения и поведение в крайних случаях

При использовании PathStyleExtension важно учитывать ограничения WebGL:

  • чрезмерно сложные dash-patterns могут снижать производительность
  • большие значения offset требуют аккуратной нормализации координат
  • miter join может давать артефакты при острых углах в географических проекциях

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


Влияние на структуру данных

Использование PathStyleExtension часто требует пересмотра структуры входных данных. Типичный объект маршрута может включать:

{
  path: [[lng, lat], [lng, lat], ...],
  width: 4,
  color: [255, 0, 0],
  dash: [6, 3],
  offset: 2,
  jointType: 'round'
}

Такая модель делает геометрию и стиль единым источником правды, что упрощает генерацию и трансформацию данных на уровне backend или preprocessing pipeline.


Шейдерная модель расширения

На уровне GPU PathStyleExtension добавляет:

  • атрибуты вершин (width, offset, dash scale)
  • ветвления логики в fragment/vertex shaders
  • дополнительные varyings для передачи параметров вдоль сегментов

Это позволяет реализовать:

  • плавное изменение толщины вдоль линии
  • корректную интерполяцию dash-pattern
  • стабильные соединения на стыках сегментов

Практическое применение в картографических системах

PathStyleExtension широко применяется в задачах визуализации:

  • транспортные сети (дороги, железные дороги)
  • логистические маршруты
  • телекоммуникационные линии
  • потоковые диаграммы (flow maps)

За счёт комбинации offset + dash + per-instance width достигается высокая информативность без увеличения геометрической сложности сцены.