Полигоны и области

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

В CesiumJS полигоны могут:

  • отображаться непосредственно на поверхности Земли;
  • иметь собственную высоту;
  • формировать объемные объекты путем экструзии;
  • содержать отверстия;
  • использовать различные материалы и текстуры;
  • участвовать во взаимодействии с пользователем.

Создание полигонов осуществляется через сущности (Entity) или примитивы (Primitive). Для большинства прикладных задач используется механизм сущностей.


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

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

const polygon = viewer.entities.add({
    polygon: {
        hierarchy: Cesium.Cartesian3.fromDegreesArray([
            37.6176, 55.7558,
            37.6276, 55.7558,
            37.6276, 55.7658,
            37.6176, 55.7658
        ]),
        material: Cesium.Color.RED.withAlpha(0.5)
    }
});

Здесь:

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

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


Структура PolygonGraphics

Полигон внутри сущности представлен объектом PolygonGraphics.

viewer.entities.add({
    polygon: {
        hierarchy: positions,
        material: Cesium.Color.BLUE,
        outline: true,
        outlineColor: Cesium.Color.WHITE
    }
});

Наиболее важные свойства:

Свойство Назначение
hierarchy Геометрия полигона
material Материал поверхности
outline Отображение контура
outlineColor Цвет контура
height Высота основания
extrudedHeight Высота экструзии
fill Заливка
show Видимость объекта

Иерархия вершин

Контур полигона задается через объект PolygonHierarchy.

const hierarchy = new Cesium.PolygonHierarchy(
    Cesium.Cartesian3.fromDegreesArray([
        30, 50,
        31, 50,
        31, 51,
        30, 51
    ])
);

Использование:

viewer.entities.add({
    polygon: {
        hierarchy: hierarchy,
        material: Cesium.Color.GREEN
    }
});

Такой подход особенно полезен при работе со сложными областями и отверстиями.


Работа с высотой полигона

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

Для размещения полигона выше поверхности используется свойство height.

viewer.entities.add({
    polygon: {
        hierarchy: Cesium.Cartesian3.fromDegreesArray([
            30, 50,
            31, 50,
            31, 51,
            30, 51
        ]),
        height: 1000,
        material: Cesium.Color.ORANGE
    }
});

В данном случае объект будет расположен на высоте 1000 метров.


Экструдированные полигоны

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

viewer.entities.add({
    polygon: {
        hierarchy: Cesium.Cartesian3.fromDegreesArray([
            30, 50,
            31, 50,
            31, 51,
            30, 51
        ]),
        extrudedHeight: 5000,
        material: Cesium.Color.CYAN.withAlpha(0.6)
    }
});

Результатом станет трехмерная призма высотой 5000 метров.


Комбинирование высоты и экструзии

Можно задавать как высоту основания, так и высоту верхней грани.

viewer.entities.add({
    polygon: {
        hierarchy: coordinates,
        height: 2000,
        extrudedHeight: 7000,
        material: Cesium.Color.YELLOW
    }
});

В этом случае:

  • нижняя грань располагается на высоте 2000 метров;
  • верхняя грань находится на высоте 7000 метров.

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


Контур полигона

Контур помогает визуально отделять объект от окружающей поверхности.

viewer.entities.add({
    polygon: {
        hierarchy: positions,
        material: Cesium.Color.BLUE.withAlpha(0.4),
        outline: true,
        outlineColor: Cesium.Color.WHITE
    }
});

Толщина контура на большинстве платформ ограничивается возможностями WebGL и может различаться между браузерами.


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

Прозрачность регулируется методом withAlpha().

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

Пример:

viewer.entities.add({
    polygon: {
        hierarchy: positions,
        material: Cesium.Color.GREEN.withAlpha(0.2)
    }
});

Полупрозрачные полигоны особенно полезны при наложении нескольких тематических слоев.


Полигоны с отверстиями

Некоторые географические объекты содержат внутренние области, которые необходимо исключить из отображения.

Например:

  • озеро внутри территории;
  • анклав;
  • запрещенная зона внутри общей области.

Для этого используются отверстия (holes).

const outerRing = Cesium.Cartesian3.fromDegreesArray([
    30, 50,
    35, 50,
    35, 55,
    30, 55
]);

const innerRing = Cesium.Cartesian3.fromDegreesArray([
    31, 51,
    34, 51,
    34, 54,
    31, 54
]);

viewer.entities.add({
    polygon: {
        hierarchy: new Cesium.PolygonHierarchy(
            outerRing,
            [
                new Cesium.PolygonHierarchy(innerRing)
            ]
        ),
        material: Cesium.Color.RED.withAlpha(0.5)
    }
});

Внутренняя область останется пустой.


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

Материал полигона может быть представлен изображением.

viewer.entities.add({
    polygon: {
        hierarchy: positions,
        material: "./images/texture.png"
    }
});

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

material: new Cesium.ImageMaterialProperty({
    image: "./images/grid.png"
})

Текстуры применяются для отображения:

  • карт покрытия;
  • схем коммуникаций;
  • тематических сеток;
  • спутниковых фрагментов.

ImageMaterialProperty

Настройка изображения предоставляет дополнительные возможности.

material: new Cesium.ImageMaterialProperty({
    image: "./images/pattern.png",
    transparent: true,
    color: Cesium.Color.WHITE
})

Свойства:

Свойство Назначение
image Источник изображения
repeat Повторение текстуры
transparent Поддержка прозрачности
color Цветовой множитель

Шахматный материал

Cesium содержит готовые процедурные материалы.

material: new Cesium.CheckerboardMaterialProperty({
    evenColor: Cesium.Color.WHITE,
    oddColor: Cesium.Color.BLACK,
    repeat: new Cesium.Cartesian2(8, 8)
})

Такой материал удобен для тестирования геометрии.


Полосатый материал

material: new Cesium.StripeMaterialProperty({
    evenColor: Cesium.Color.BLUE,
    oddColor: Cesium.Color.WHITE,
    repeat: 20
})

Материал формирует повторяющиеся полосы.


Сетчатый материал

material: new Cesium.GridMaterialProperty({
    color: Cesium.Color.YELLOW,
    cellAlpha: 0.3,
    lineCount: new Cesium.Cartesian2(10, 10)
})

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


Классификация поверхности

Полигоны способны классифицировать объекты сцены.

viewer.entities.add({
    polygon: {
        hierarchy: positions,
        material: Cesium.Color.BLUE.withAlpha(0.3),
        classificationType: Cesium.ClassificationType.TERRAIN
    }
});

Варианты:

Cesium.ClassificationType.TERRAIN
Cesium.ClassificationType.CESIUM_3D_TILE
Cesium.ClassificationType.BOTH

Это особенно важно при работе с фотограмметрией и 3D Tiles.


Геодезическая и румбовая интерполяция

По умолчанию стороны полигона строятся по кратчайшему пути на эллипсоиде.

arcType: Cesium.ArcType.GEODESIC

Альтернативный вариант:

arcType: Cesium.ArcType.RHUMB

Где:

  • GEODESIC — ортодромия;
  • RHUMB — локсодромия.

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


Отображение на рельефе

Полигоны могут повторять форму местности.

viewer.entities.add({
    polygon: {
        hierarchy: positions,
        material: Cesium.Color.GREEN.withAlpha(0.5),
        perPositionHeight: false
    }
});

При использовании актуальных данных рельефа область будет визуально адаптироваться к поверхности.


Индивидуальная высота вершин

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

const positions = Cesium.Cartesian3.fromDegreesArrayHeights([
    30, 50, 1000,
    31, 50, 3000,
    31, 51, 5000,
    30, 51, 2000
]);

Создание полигона:

viewer.entities.add({
    polygon: {
        hierarchy: positions,
        perPositionHeight: true,
        material: Cesium.Color.ORANGE
    }
});

В результате получается наклонная поверхность.


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

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

const polygonEntity = viewer.entities.add({
    polygon: {
        hierarchy: new Cesium.CallbackProperty(() => {
            return new Cesium.PolygonHierarchy(dynamicPositions);
        }, false),
        material: Cesium.Color.RED
    }
});

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

Подобная техника используется для:

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

Выбор полигона пользователем

Каждая сущность может участвовать в механизме выбора.

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

handler.setInputAction(function(click) {

    const picked = viewer.scene.pick(
        click.position
    );

    if (Cesium.defined(picked)) {
        console.log(picked.id);
    }

}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

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


Информационные окна

Полигоны могут содержать описательные данные.

viewer.entities.add({
    name: "Охраняемая территория",
    description: `
        <h2>Заповедник</h2>
        <p>Площадь: 1200 км²</p>
    `,
    polygon: {
        hierarchy: positions,
        material: Cesium.Color.GREEN
    }
});

При выборе объекта Cesium автоматически отображает информационную карточку.


Расчет площади полигона

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

Типичный алгоритм включает:

  1. получение координат вершин;
  2. преобразование в картографические координаты;
  3. проекцию на локальную плоскость;
  4. вычисление площади геометрическим методом.

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


Производительность при работе с большим количеством областей

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

Основные рекомендации:

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

Для крупных геоинформационных систем нередко применяется комбинация:

  • GeoJSON;
  • DataSource;
  • Primitive;
  • 3D Tiles.

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


Загрузка полигонов из GeoJSON

Большинство геоданных распространяется в формате GeoJSON.

Cesium.GeoJsonDataSource.load(
    "./data/regions.geojson",
    {
        stroke: Cesium.Color.WHITE,
        fill: Cesium.Color.BLUE.withAlpha(0.4),
        strokeWidth: 2
    }
).then(function(dataSource) {

    viewer.dataSources.add(dataSource);

});

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

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