Создание и управление Entity

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

В основе подхода лежит коллекция EntityCollection, которая хранится внутри Viewer и управляет жизненным циклом всех добавленных объектов.

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

Создание Entity через EntityCollection

Основной способ создания объекта — добавление его в коллекцию viewer.entities.

const entity = viewer.entities.add({
    id: "unique-object-1",
    position: Cesium.Cartesian3.fromDegrees(37.6173, 55.7558),
    point: {
        pixelSize: 10,
        color: Cesium.Color.RED
    }
});

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


Основные свойства Entity

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

Геометрическое положение

Позиция задаётся через position:

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

Поддерживаются также динамические позиции через Property:

const positionProperty = new Cesium.SampledPositionProperty();

positionProperty.addSample(
    Cesium.JulianDate.now(),
    Cesium.Cartesian3.fromDegrees(37.6, 55.7)
);

entity.position = positionProperty;

Визуальные компоненты

Entity может одновременно содержать несколько типов визуализации:

Точка (PointGraphics)

point: {
    pixelSize: 12,
    color: Cesium.Color.YELLOW,
    outlineColor: Cesium.Color.BLACK,
    outlineWidth: 2
}

Метка (LabelGraphics)

label: {
    text: "Объект",
    font: "14pt sans-serif",
    fillColor: Cesium.Color.WHITE,
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth: 2
}

Billboard (иконка)

billboard: {
    image: "/assets/icon.png",
    width: 32,
    height: 32
}

Линии и полигоны

polyline: {
    positions: Cesium.Cartesian3.fromDegreesArray([
        37.6, 55.7,
        38.0, 55.8
    ]),
    width: 3,
    material: Cesium.Color.CYAN
}
polygon: {
    hierarchy: Cesium.Cartesian3.fromDegreesArray([
        30.0, 50.0,
        35.0, 50.0,
        35.0, 55.0,
        30.0, 55.0
    ]),
    material: Cesium.Color.BLUE.withAlpha(0.4)
}

Идентификация и управление жизненным циклом

Каждый Entity может иметь уникальный идентификатор:

id: "city-marker-001"

По этому идентификатору объект может быть получен или удалён.

Получение Entity

const entity = viewer.entities.getById("city-marker-001");

Удаление Entity

viewer.entities.remove(entity);

Удаление по идентификатору:

const entity = viewer.entities.getById("city-marker-001");
viewer.entities.remove(entity);

Полная очистка коллекции:

viewer.entities.removeAll();

Обновление Entity в рантайме

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

const entity = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(37.6, 55.7),
    point: {
        pixelSize: 10,
        color: Cesium.Color.RED
    }
});

entity.point.color = Cesium.Color.GREEN;
entity.point.pixelSize = 20;

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


Динамические свойства и Property API

CesiumJS использует систему Property для описания изменяющихся во времени значений.

ConstantProperty

entity.position = new Cesium.ConstantProperty(
    Cesium.Cartesian3.fromDegrees(37.6, 55.7)
);

SampledPositionProperty

Используется для анимации движения:

const property = new Cesium.SampledPositionProperty();

property.addSample(
    Cesium.JulianDate.fromIso8601("2026-06-07T10:00:00Z"),
    Cesium.Cartesian3.fromDegrees(37.6, 55.7)
);

property.addSample(
    Cesium.JulianDate.fromIso8601("2026-06-07T10:10:00Z"),
    Cesium.Cartesian3.fromDegrees(38.0, 55.8)
);

entity.position = property;

CallbackProperty

Позволяет вычислять значение на лету:

entity.position = new Cesium.CallbackProperty(() => {
    const time = Cesium.JulianDate.now();
    return Cesium.Cartesian3.fromDegrees(37.6 + Math.sin(time.secondsOfDay), 55.7);
}, false);

Временные диапазоны Entity

Entity может существовать только в определённый интервал времени через availability.

entity.availability = new Cesium.TimeIntervalCollection([
    new Cesium.TimeInterval({
        start: Cesium.JulianDate.fromIso8601("2026-06-07T10:00:00Z"),
        stop: Cesium.JulianDate.fromIso8601("2026-06-07T12:00:00Z")
    })
]);

Вне этого диапазона объект автоматически не отображается.


Ориентация и направление

Entity может быть ориентирован в пространстве через orientation.

entity.orientation = Cesium.Transforms.headingPitchRollQuaternion(
    entity.position.getValue(Cesium.JulianDate.now()),
    new Cesium.HeadingPitchRoll(
        Cesium.Math.toRadians(90),
        0,
        0
    )
);

Для моделей часто используется привязка ориентации к движению:

entity.orientation = new Cesium.VelocityOrientationProperty(entity.position);

Работа с 3D-моделями

Entity поддерживает загрузку glTF-моделей:

entity.model = {
    uri: "/models/vehicle.glb",
    minimumPixelSize: 64,
    maximumScale: 200
};

Модель становится частью Entity и наследует его позицию и ориентацию.


Групповое управление EntityCollection

Коллекция viewer.entities предоставляет методы для массовых операций.

Итерация по Entity

viewer.entities.values.forEach((e) => {
    console.log(e.id);
});

Фильтрация

const visible = viewer.entities.values.filter(e => e.show);

События изменений

viewer.entities.collectionChanged.addEventListener((collection, added, removed) => {
    console.log("Добавлено:", added.length);
    console.log("Удалено:", removed.length);
});

Связь Entity и DataSource

Entity часто создаются не напрямую, а через DataSource:

const dataSource = new Cesium.CustomDataSource("custom");
viewer.dataSources.add(dataSource);

dataSource.entities.add({
    position: Cesium.Cartesian3.fromDegrees(37.6, 55.7),
    point: {
        pixelSize: 10
    }
});

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


Производительность и особенности использования

Модель Entity упрощает разработку, но требует внимания к производительности при больших наборах данных.

  • большое количество динамических CallbackProperty снижает FPS
  • частые изменения position требуют пересчёта сцены
  • предпочтительно использовать SampledPositionProperty вместо непрерывных вычислений
  • группировка через DataSource упрощает управление памятью

При работе с тысячами объектов Entity может уступать низкоуровневым Primitive по эффективности, но остаётся более удобной для прикладных задач.


Взаимодействие с Entity через API сцены

Entity интегрируется с системой picking:

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

handler.setInputAction((click) => {
    const picked = viewer.scene.pick(click.position);
    if (Cesium.defined(picked) && picked.id) {
        console.log(picked.id);
    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

Объект picked.id обычно содержит Entity, что позволяет быстро связывать пользовательские события с объектной моделью сцены.


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

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

entity.polyline.material = Cesium.Color.ORANGE;
entity.label.text = "Обновлённый текст";
entity.billboard.scale = 1.5;

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


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

Entity может комбинировать несколько визуальных представлений:

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(37.6, 55.7),
    point: { pixelSize: 8, color: Cesium.Color.WHITE },
    billboard: { image: "/icon.png" },
    label: { text: "Node" }
});

Каждый компонент рендерится независимо, но связан с одной координатной сущностью.


Привязка данных к Entity

Entity может служить контейнером для произвольных данных:

entity.properties = {
    name: new Cesium.ConstantProperty("Объект A"),
    type: new Cesium.ConstantProperty("sensor"),
    idInternal: new Cesium.ConstantProperty(42)
};

Эти свойства доступны при взаимодействии:

console.log(entity.properties.name.getValue());

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