Линии и полилинии

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

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


Создание простой полилинии

Наиболее распространённый способ создания линии — добавление сущности через коллекцию viewer.entities.

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

viewer.entities.add({
    polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
            37.6176, 55.7558,
            30.3141, 59.9386,
            27.5615, 53.9023
        ]),
        width: 4,
        material: Cesium.Color.RED
    }
});

В данном примере создаётся линия, проходящая через:

  • Москву;
  • Санкт-Петербург;
  • Минск.

Основные параметры:

Параметр Назначение
positions Массив координат вершин
width Толщина линии
material Материал отображения

Формирование координат

Использование массива координат

Самый удобный способ задания полилинии:

Cesium.Cartesian3.fromDegreesArray([
    lon1, lat1,
    lon2, lat2,
    lon3, lat3
]);

Пример:

positions: Cesium.Cartesian3.fromDegreesArray([
    -74.0060, 40.7128,
    -118.2437, 34.0522,
    -122.4194, 37.7749
])

Линия соединит:

  • Нью-Йорк;
  • Лос-Анджелес;
  • Сан-Франциско.

Использование массива объектов Cartesian3

Иногда координаты формируются динамически.

positions: [
    Cesium.Cartesian3.fromDegrees(10, 50),
    Cesium.Cartesian3.fromDegrees(20, 55),
    Cesium.Cartesian3.fromDegrees(30, 60)
]

Такой подход удобен при программной генерации маршрутов.


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

Толщина задаётся свойством width.

polyline: {
    positions: positions,
    width: 10,
    material: Cesium.Color.BLUE
}

Возможны любые значения:

width: 1

Тонкая линия.

width: 20

Широкая линия.

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


Цвет линии

Для окраски используется материал.

material: Cesium.Color.YELLOW

Пример:

viewer.entities.add({
    polyline: {
        positions: positions,
        width: 5,
        material: Cesium.Color.YELLOW
    }
});

Настройка прозрачности

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

material: Cesium.Color.RED.withAlpha(0.5)

Пример:

polyline: {
    positions: positions,
    width: 6,
    material: Cesium.Color.GREEN.withAlpha(0.3)
}

Высота линии над поверхностью

По умолчанию точки располагаются на уровне поверхности Земли.

Высота задаётся третьим параметром.

Cesium.Cartesian3.fromDegrees(
    longitude,
    latitude,
    height
)

Пример:

positions: [
    Cesium.Cartesian3.fromDegrees(30, 50, 10000),
    Cesium.Cartesian3.fromDegrees(40, 55, 10000)
]

Линия будет проходить на высоте 10 километров.


Полилинии в трёхмерном пространстве

Каждая вершина может иметь собственную высоту.

positions: [
    Cesium.Cartesian3.fromDegrees(10, 50, 0),
    Cesium.Cartesian3.fromDegrees(20, 55, 5000),
    Cesium.Cartesian3.fromDegrees(30, 60, 15000)
]

Получается пространственная ломаная линия.

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

  • авиационных маршрутов;
  • траекторий спутников;
  • телеметрии;
  • визуализации подъёма и спуска объектов.

Следование рельефу

Линия может повторять форму поверхности Земли.

polyline: {
    positions: positions,
    clampToGround: true,
    width: 4,
    material: Cesium.Color.ORANGE
}

Параметр:

clampToGround: true

заставляет линию прилегать к рельефу.

Особенно полезно для отображения:

  • дорог;
  • границ участков;
  • туристических маршрутов;
  • инженерных сетей.

Геодезические линии

По умолчанию Cesium строит сегменты вдоль поверхности эллипсоида.

Такие линии соответствуют кратчайшему пути по поверхности Земли.

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

viewer.entities.add({
    polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
            -74.0060, 40.7128,
            139.6917, 35.6895
        ]),
        width: 3,
        material: Cesium.Color.CYAN
    }
});

Линия будет следовать по геодезической дуге.


Управление детализацией дуги

Параметр granularity определяет плотность промежуточных точек.

polyline: {
    positions: positions,
    width: 5,
    granularity: Cesium.Math.toRadians(1)
}

Меньшее значение:

granularity: Cesium.Math.toRadians(0.1)

создаёт более гладкую линию.

Большее значение снижает количество вычислений.


Тип построения дуги

Свойство arcType определяет алгоритм соединения вершин.

Геодезическая дуга

arcType: Cesium.ArcType.GEODESIC

Используется по умолчанию.


Румбовая линия

arcType: Cesium.ArcType.RHUMB

Сохраняет постоянный азимут.

Применяется в навигационных задачах.


Прямая линия

arcType: Cesium.ArcType.NONE

Соединяет точки напрямую в трёхмерном пространстве.

polyline: {
    positions: positions,
    arcType: Cesium.ArcType.NONE
}

Подходит для инженерных и технических визуализаций.


Использование материалов

Материалы позволяют создавать более сложный внешний вид линий.

Однотонный материал

material: Cesium.Color.RED

Полупрозрачный материал

material: Cesium.Color.BLUE.withAlpha(0.4)

Свечение

material: new Cesium.PolylineGlowMaterialProperty({
    glowPower: 0.3,
    color: Cesium.Color.CYAN
})

Пример:

polyline: {
    positions: positions,
    width: 12,
    material: new Cesium.PolylineGlowMaterialProperty({
        glowPower: 0.2,
        color: Cesium.Color.LIME
    })
}

Создаётся эффект неонового свечения.


Пунктирные линии

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

material: new Cesium.PolylineDashMaterialProperty({
    color: Cesium.Color.YELLOW
})

Полный пример:

viewer.entities.add({
    polyline: {
        positions: positions,
        width: 4,
        material: new Cesium.PolylineDashMaterialProperty({
            color: Cesium.Color.WHITE,
            dashLength: 16
        })
    }
});

Настройка штрихов

Длина штриха

dashLength: 20

Цвет промежутков

gapColor: Cesium.Color.TRANSPARENT

Цвет линии

color: Cesium.Color.ORANGE

Пример:

material: new Cesium.PolylineDashMaterialProperty({
    color: Cesium.Color.ORANGE,
    gapColor: Cesium.Color.BLACK,
    dashLength: 10
})

Анимированные линии

Материалы могут изменяться динамически.

Простейшая анимация:

let alpha = 1;

viewer.clock.onTick.addEventListener(function() {

    alpha -= 0.01;

    if (alpha <= 0) {
        alpha = 1;
    }

    line.polyline.material =
        Cesium.Color.RED.withAlpha(alpha);

});

Эффект напоминает мигание маршрута.


Динамическое изменение маршрута

Положение линии может обновляться во время работы приложения.

const positions = [];

const line = viewer.entities.add({
    polyline: {
        positions: new Cesium.CallbackProperty(
            function() {
                return positions;
            },
            false
        ),
        width: 5,
        material: Cesium.Color.YELLOW
    }
});

Добавление новых точек:

positions.push(
    Cesium.Cartesian3.fromDegrees(
        longitude,
        latitude
    )
);

Подход используется для:

  • GPS-трекинга;
  • мониторинга транспорта;
  • отображения полётов;
  • систем телеметрии.

Линии через Primitive API

Для больших наборов данных использование Entity API может стать менее эффективным.

В таких случаях применяется низкоуровневый API примитивов.

const instance = new Cesium.GeometryInstance({
    geometry: new Cesium.PolylineGeometry({
        positions: positions,
        width: 5
    })
});

Создание примитива:

viewer.scene.primitives.add(
    new Cesium.Primitive({
        geometryInstances: instance,
        appearance:
            new Cesium.PolylineColorAppearance()
    })
);

Преимущества:

  • высокая производительность;
  • меньшие накладные расходы;
  • работа с тысячами объектов.

PolylineCollection

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

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

Добавление линии:

collection.add({
    positions: [
        Cesium.Cartesian3.fromDegrees(10, 50),
        Cesium.Cartesian3.fromDegrees(20, 55)
    ],
    width: 3
});

Преимущества коллекций:

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

Удаление полилиний

Удаление отдельной сущности:

viewer.entities.remove(line);

Удаление всех сущностей:

viewer.entities.removeAll();

Удаление примитива:

viewer.scene.primitives.remove(polyline);

Практический пример маршрута

const route = viewer.entities.add({
    polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
            37.6176, 55.7558,
            49.1064, 55.7963,
            60.5975, 56.8389,
            82.9204, 55.0302
        ]),
        width: 6,
        material: new Cesium.PolylineGlowMaterialProperty({
            color: Cesium.Color.CYAN,
            glowPower: 0.25
        }),
        clampToGround: true
    }
});

viewer.zoomTo(route);

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

Рекомендации по производительности

Использование Entity API для небольших наборов данных

Для десятков и сотен линий наиболее удобным решением остаются сущности.

viewer.entities.add(...)

Код получается компактным и легко поддерживается.

Использование Primitive API для больших объёмов данных

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

Cesium.Primitive

или

Cesium.PolylineCollection

Это позволяет существенно снизить нагрузку на процессор и систему управления сущностями.

Минимизация обновлений

Если линия не изменяется, не следует использовать:

CallbackProperty

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

Оптимальный уровень детализации

Чрезмерно маленькое значение granularity увеличивает количество промежуточных вершин.

Рационально подбирать баланс между:

  • плавностью линий;
  • скоростью визуализации;
  • объёмом памяти.

Ограничение количества динамических материалов

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

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

Полилинии являются одним из наиболее востребованных инструментов визуализации в CesiumJS и применяются для отображения:

  • автомобильных маршрутов;
  • железнодорожных путей;
  • морских трасс;
  • авиационных коридоров;
  • орбит космических аппаратов;
  • границ государств;
  • административных контуров;
  • кабельных сетей;
  • трубопроводов;
  • линий электропередачи;
  • GPS-треков;
  • телеметрических данных;
  • траекторий движения объектов в реальном времени.

Гибкость настройки геометрии, материалов, высоты, типа дуги и динамического обновления делает полилинии одним из ключевых инструментов пространственной визуализации в экосистеме CesiumJS.