Группировка и фильтрация

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

На уровне API группировка реализуется через несколько фундаментальных механизмов: EntityCollection, DataSource, PrimitiveCollection, а также через высокоуровневые представления вроде GeoJsonDataSource и Cesium3DTileset. Каждый из этих уровней решает задачу агрегации объектов с различной степенью абстракции.

Entity-ориентированная модель позволяет объединять объекты в логические наборы, где каждый объект содержит набор свойств: геометрию, стили, временные интервалы, а также пользовательские атрибуты. При этом коллекции сущностей могут динамически изменяться во время выполнения, что делает группировку не статической, а реактивной.

EntityCollection как базовый механизм агрегации

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

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

const collection = new Cesium.EntityCollection();

const entityA = collection.add({
    id: "point-1",
    position: Cesium.Cartesian3.fromDegrees(30, 50),
    point: { pixelSize: 10 }
});

const entityB = collection.add({
    id: "point-2",
    position: Cesium.Cartesian3.fromDegrees(31, 51),
    point: { pixelSize: 10 }
});

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

DataSource как уровень тематической группировки

DataSource расширяет концепцию группировки, вводя тематические наборы данных. Каждый источник данных представляет собой самостоятельный слой, который может быть добавлен в DataSourceCollection.

Типичные реализации включают GeoJsonDataSource, CzmlDataSource, KmlDataSource. Каждый из них формирует логическую группу объектов на основе входного формата данных.

const geoJsonSource = await Cesium.GeoJsonDataSource.load("data/map.geojson");
viewer.dataSources.add(geoJsonSource);

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

PrimitiveCollection и низкоуровневая группировка

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

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

const primitives = new Cesium.PrimitiveCollection();

const primitive = new Cesium.Primitive({
    geometryInstances: new Cesium.GeometryInstance({
        geometry: new Cesium.BoxGeometry({
            maximum: new Cesium.Cartesian3(1000000, 1000000, 1000000)
        })
    })
});

primitives.add(primitive);
viewer.scene.primitives.add(primitives);

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

Фильтрация на уровне сущностей

Фильтрация объектов в Cesium чаще всего реализуется через свойства сущностей, условия отображения и динамические выражения. Основной механизм — изменение свойств show, которое определяет видимость объекта.

entity.show = false;

При работе с коллекциями возможно применение массовой фильтрации, основанной на обходе элементов и проверке их атрибутов:

collection.values.forEach(e => {
    if (e.properties && e.properties.type === "restricted") {
        e.show = false;
    }
});

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

Property-based фильтрация и условные выражения

Более гибкий механизм фильтрации реализуется через Property API. Он позволяет привязывать видимость и стиль к изменяющимся значениям.

entity.show = new Cesium.CallbackProperty(function (time) {
    return Cesium.JulianDate.toDate(time).getHours() > 6;
}, false);

Такой подход превращает фильтрацию в непрерывный процесс, зависящий от временной шкалы или пользовательских данных.

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

Фильтрация в 3D Tiles

Особое место занимает фильтрация в Cesium3DTileset, где используется стильовая система на основе условий.

tileset.style = new Cesium.Cesium3DTileStyle({
    color: "(${height} > 100) ? color('red') : color('white')"
});

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

Также применяется скрытие тайлов через show и управление выборкой через maximumScreenSpaceError, влияющее на уровень детализации.

Кластеризация как форма пространственной группировки

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

viewer.entities.clustering.enabled = true;
viewer.entities.clustering.pixelRange = 50;
viewer.entities.clustering.minimumClusterSize = 3;

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

Слойная фильтрация через видимость DataSource

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

geoJsonSource.show = false;

Это создаёт эффективный механизм переключения тематических слоёв без необходимости обхода всех сущностей внутри источника.

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

Пространственная фильтрация через камеру

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

const distance = Cesium.Cartesian3.distance(
    viewer.camera.position,
    entity.position.getValue(viewer.clock.currentTime)
);

entity.show = distance < 50000;

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

Комбинированные стратегии группировки и фильтрации

В реальных сценариях применяется комбинация нескольких уровней:

  • тематическая группировка через DataSource
  • логическая через EntityCollection
  • визуальная через PrimitiveCollection
  • производительная через 3D Tiles
  • динамическая через Property API

Система становится многослойной, где каждый уровень отвечает за свою часть фильтрации. Например, DataSource может скрывать целый слой, внутри которого Entity фильтрует объекты по времени, а Tileset ограничивает детализацию.

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