Polyline визуализация

Polyline в CesiumJS представляет собой базовый примитив для отображения ломаных линий на поверхности глобуса или в 3D-пространстве сцены. Он используется для построения маршрутов, границ, траекторий движения объектов, а также любых линейных геометрических структур, где требуется последовательное соединение точек в пространстве.

В CesiumJS существует несколько уровней абстракции для работы с линиями: от низкоуровневых примитивов до высокоуровневых сущностей. Основные варианты включают Polyline, PolylineCollection и сущность Entity с графическим свойством polyline. Каждый из подходов имеет собственные особенности производительности, гибкости и способа интеграции в сцену.

Polyline в CesiumJS определяется как упорядоченный набор координат, соединённых прямыми отрезками. В отличие от полигонов, он не образует замкнутую область и не имеет внутренней поверхности. Координаты задаются в формате Cartesian3, чаще всего через преобразование из географических координат (долгота, широта, высота).

Основная особенность заключается в том, что визуализация линии происходит с учётом эллипсоидальной модели Земли, если включён режим следования поверхности (clamp to ground). Это позволяет линии повторять рельеф, а не проходить строго по прямым в 3D-пространстве.

Создание Polyline через Entity API

Entity API представляет собой высокоуровневый способ описания графических объектов. Polyline в этом контексте задаётся как свойство объекта:

const viewer = new Cesium.Viewer("cesiumContainer");

const polylineEntity = viewer.entities.add({
    polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
            30.5, 50.45,
            31.2, 50.47,
            32.0, 50.50
        ]),
        width: 3,
        material: Cesium.Color.CYAN
    }
});

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

Материал линии определяет её визуальные свойства. Помимо простого цвета, могут использоваться:

  • PolylineGlowMaterialProperty для свечения
  • PolylineOutlineMaterialProperty для контуров
  • ImageMaterialProperty для текстурирования

PolylineCollection и производительность

При работе с большим количеством линий использование PolylineCollection становится более эффективным по сравнению с Entity API. Это связано с тем, что коллекция работает ближе к графическому уровню и минимизирует накладные расходы абстракции.

const scene = viewer.scene;

const polylineCollection = scene.primitives.add(new Cesium.PolylineCollection());

polylineCollection.add({
    positions: Cesium.Cartesian3.fromDegreesArray([
        10.0, 45.0,
        20.0, 46.0,
        30.0, 47.0
    ]),
    width: 2,
    material: Cesium.Color.YELLOW
});

PolylineCollection оптимизирует рендеринг за счёт группировки геометрии и уменьшения количества draw calls. Это особенно важно при отображении тысяч маршрутов, телеметрии или географических сетей.

Материалы и визуальные эффекты

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

Цветовые материалы

Базовый вариант — статический цвет:

material: Cesium.Color.RED

Также доступен динамический цвет:

material: new Cesium.ColorMaterialProperty(
    new Cesium.CallbackProperty(() => {
        return Cesium.Color.fromRandom();
    }, false)
)

Свечение линии

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

material: new Cesium.PolylineGlowMaterialProperty({
    glowPower: 0.2,
    color: Cesium.Color.BLUE
})

Glow работает за счёт расширения альфа-канала и размытия краёв линии в шейдере.

Контурная линия

Polyline с контуром создаёт эффект двойной обводки:

material: new Cesium.PolylineOutlineMaterialProperty({
    color: Cesium.Color.WHITE,
    outlineWidth: 2,
    outlineColor: Cesium.Color.BLACK
})

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

Работа с высотой

Polyline может быть привязан к поверхности или существовать в 3D-пространстве. Основные режимы:

  • Clamp to ground — линия следует рельефу
  • Absolute height — координаты включают высоту
  • Relative height — высота относительно поверхности

Пример линии с высотой:

positions: Cesium.Cartesian3.fromDegreesArrayHeights([
    30.0, 50.0, 1000,
    31.0, 51.0, 1500,
    32.0, 52.0, 2000
])

При использовании 3D-режима важно учитывать, что визуальная длина линии может отличаться от геодезической из-за кривизны эллипсоида.

Геодезические и экранные линии

CesiumJS различает типы интерполяции между точками:

  • Geodesic — кратчайшая линия по поверхности эллипсоида
  • Rhumb line — линия с постоянным азимутом
  • Straight — прямое соединение в мировом пространстве

Настройка геодезической интерполяции:

polyline: {
    positions: Cesium.Cartesian3.fromDegreesArray([...]),
    arcType: Cesium.ArcType.GEODESIC
}

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

Динамические полилинии

Polyline может обновляться в реальном времени через CallbackProperty. Это используется для отображения движущихся объектов или изменяющихся маршрутов.

const dynamicPositions = [];

viewer.entities.add({
    polyline: {
        positions: new Cesium.CallbackProperty(() => {
            return Cesium.Cartesian3.fromDegreesArray(dynamicPositions);
        }, false),
        width: 2,
        material: Cesium.Color.ORANGE
    }
});

При каждом кадре сцены функция пересчитывает координаты, обеспечивая анимацию линии.

Z-index и порядок отрисовки

При наложении нескольких линий важным параметром становится zIndex. Он влияет на порядок рендеринга при совпадении глубины.

polyline: {
    positions: [...],
    width: 3,
    zIndex: 2
}

Также можно управлять глубинным тестированием:

  • disableDepthTestDistance позволяет игнорировать перекрытия
  • clampToGround влияет на взаимодействие с terrain

Привязка к поверхности земли

Polyline может быть «приклеена» к terrain:

polyline: {
    positions: Cesium.Cartesian3.fromDegreesArray([...]),
    clampToGround: true
}

Этот режим использует геометрию высотного слоя и требует включённого terrain provider.

При работе с большим количеством таких линий производительность может снижаться из-за необходимости пересчёта геометрии относительно рельефа.

Оптимизация большого количества линий

При визуализации тысяч объектов критически важны следующие подходы:

  • Использование PolylineCollection вместо Entity
  • Минимизация количества уникальных материалов
  • Отключение unnecessary shadows
  • Использование static geometry (freeze)
  • Группировка линий по материалам

Также важно учитывать уровень детализации камеры. CesiumJS автоматически снижает сложность отображения при удалении камеры от объекта.

Полилинии и координатные преобразования

CesiumJS оперирует несколькими системами координат. Для корректного построения линий используется преобразование:

  • WGS84 (longitude, latitude, height)
  • Cartesian3 (мировые координаты)
  • Cartographic (радианные координаты)

Пример преобразования:

const cartographic = Cesium.Cartographic.fromDegrees(30, 50);
const cartesian = Cesium.Ellipsoid.WGS84.cartographicToCartesian(cartographic);

Polyline всегда требует Cartesian3, поэтому преобразование является обязательным этапом при работе с географическими данными.

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

Polyline может быть интерактивной через picking:

const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

handler.setInputAction((movement) => {
    const picked = viewer.scene.pick(movement.position);
    if (Cesium.defined(picked)) {
        console.log("Линия выбрана");
    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

Picking работает на уровне примитивов и сущностей, возвращая идентификатор объекта сцены.

Разделение по уровням детализации

Для сложных сцен используется Level of Detail стратегия. Polyline может иметь разные представления в зависимости от расстояния до камеры:

  • упрощённая геометрия на дальних расстояниях
  • детализированная линия при приближении

Это достигается через динамическое изменение массива positions или через custom shader материал.

Шейдерная природа Polyline

Внутри CesiumJS линия реализована через GPU-шейдеры. Это позволяет:

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

Ширина линии при этом не является геометрической толщиной в мировых координатах, а рассчитывается в экранных пикселях.

Типичные ошибки при работе с Polyline

  • Использование слишком большого количества Entity вместо PolylineCollection
  • Отсутствие преобразования координат в Cartesian3
  • Попытка использовать 2D координаты без высоты в 3D сцене
  • Чрезмерное использование динамических CallbackProperty без необходимости
  • Игнорирование terrain-зависимых вычислений

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