TimeInterval и TimeIntervalCollection

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

TimeInterval представляет собой неизменяемый (immutable) диапазон времени с дополнительными метаданными. Он используется как фундаментальный строительный блок для описания временных данных в CesiumJS.

Структура TimeInterval

Каждый интервал включает:

  • начало (start)
  • конец (stop)
  • флаг включения границ
  • дополнительные данные (data)
  • идентификатор и метки

Ключевая идея — интервал не только описывает время, но и несёт связанное с ним состояние.

const interval = new Cesium.TimeInterval({
    start: Cesium.JulianDate.fromIso8601("2026-01-01T00:00:00Z"),
    stop: Cesium.JulianDate.fromIso8601("2026-01-01T06:00:00Z"),
    isStartIncluded: true,
    isStopIncluded: false,
    data: {
        label: "Ночной режим",
        intensity: 0.2
    }
});

Особенности модели интервалов

Модель TimeInterval построена вокруг нескольких принципов:

1. Иммутабельность После создания интервал не изменяется. Любая модификация создаёт новый экземпляр.

2. Универсальность данных Поле data может содержать произвольный объект: от чисел до сложных структур визуализации.

3. Точность времени Cesium использует JulianDate, обеспечивая высокую точность астрономического уровня.

4. Поддержка включённых границ Флаги isStartIncluded и isStopIncluded позволяют точно задавать поведение на стыках интервалов.


Проверка принадлежности времени интервалу

Одной из ключевых операций является проверка, входит ли момент времени в интервал.

const time = Cesium.JulianDate.fromIso8601("2026-01-01T02:00:00Z");

const isInInterval = interval.contains(time);

Метод contains учитывает границы интервала, включая параметры включённости начала и конца.


TimeIntervalCollection

Если TimeInterval описывает один временной сегмент, то TimeIntervalCollection управляет множеством таких сегментов, формируя временную структуру данных.

Коллекция используется для:

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

Создание коллекции

const intervals = new Cesium.TimeIntervalCollection([
    new Cesium.TimeInterval({
        start: Cesium.JulianDate.fromIso8601("2026-01-01T00:00:00Z"),
        stop: Cesium.JulianDate.fromIso8601("2026-01-01T06:00:00Z"),
        data: { color: "blue" }
    }),
    new Cesium.TimeInterval({
        start: Cesium.JulianDate.fromIso8601("2026-01-01T06:00:00Z"),
        stop: Cesium.JulianDate.fromIso8601("2026-01-01T12:00:00Z"),
        data: { color: "yellow" }
    })
]);

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

Основная операция коллекции — получение интервала, соответствующего моменту времени.

const time = Cesium.JulianDate.fromIso8601("2026-01-01T07:30:00Z");

const result = intervals.findIntervalContainingDate(time);
console.log(result.data.color); // yellow

Алгоритм поиска оптимизирован и использует сортировку по времени начала интервалов.


Добавление и управление интервалами

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

Добавление

intervals.addInterval(new Cesium.TimeInterval({
    start: Cesium.JulianDate.fromIso8601("2026-01-01T12:00:00Z"),
    stop: Cesium.JulianDate.fromIso8601("2026-01-01T18:00:00Z"),
    data: { color: "green" }
}));

Удаление

const toRemove = intervals.get(0);
intervals.removeInterval(toRemove);

Очистка

intervals.removeAll();

Пересечения интервалов

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

const overlap = new Cesium.TimeInterval({
    start: Cesium.JulianDate.fromIso8601("2026-01-01T05:00:00Z"),
    stop: Cesium.JulianDate.fromIso8601("2026-01-01T10:00:00Z"),
    data: { priority: 10 }
});

При перекрытии нескольких интервалов разработчик сам определяет стратегию выбора (например, приоритет по data.priority).


Интеграция с визуальными свойствами

TimeIntervalCollection часто используется для динамических свойств сущностей (Entity) — цвета, прозрачности, координат.

Пример: изменение цвета объекта во времени

const colorProperty = new Cesium.SampledProperty(Cesium.Color);

colorProperty.addSample(
    Cesium.JulianDate.fromIso8601("2026-01-01T00:00:00Z"),
    Cesium.Color.BLUE
);

colorProperty.addSample(
    Cesium.JulianDate.fromIso8601("2026-01-01T12:00:00Z"),
    Cesium.Color.YELLOW
);

entity.box.material = colorProperty;

Хотя в этом примере используется SampledProperty, аналогичная логика часто реализуется через TimeIntervalCollection, особенно при дискретных режимах.


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

При работе с большим количеством интервалов важно учитывать:

1. Сортировка по времени начала Ускоряет поиск интервалов.

2. Минимизация перекрытий Перекрывающиеся интервалы увеличивают сложность выбора.

3. Кэширование результатов поиска Особенно при анимации кадров.

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


Практический сценарий: суточный цикл освещения

const lighting = new Cesium.TimeIntervalCollection([
    new Cesium.TimeInterval({
        start: Cesium.JulianDate.fromIso8601("2026-01-01T00:00:00Z"),
        stop: Cesium.JulianDate.fromIso8601("2026-01-01T06:00:00Z"),
        data: { brightness: 0.1 }
    }),
    new Cesium.TimeInterval({
        start: Cesium.JulianDate.fromIso8601("2026-01-01T06:00:00Z"),
        stop: Cesium.JulianDate.fromIso8601("2026-01-01T18:00:00Z"),
        data: { brightness: 1.0 }
    }),
    new Cesium.TimeInterval({
        start: Cesium.JulianDate.fromIso8601("2026-01-01T18:00:00Z"),
        stop: Cesium.JulianDate.fromIso8601("2026-01-01T24:00:00Z"),
        data: { brightness: 0.3 }
    })
]);

Далее значение яркости можно извлекать в зависимости от текущего времени сцены:

const currentTime = viewer.clock.currentTime;

const interval = lighting.findIntervalContainingDate(currentTime);
scene.light.intensity = interval.data.brightness;

Взаимодействие с Clock и Timeline

TimeInterval и TimeIntervalCollection тесно связаны с Clock и Timeline CesiumJS. Они задают:

  • диапазон доступного времени
  • шаги анимации
  • реакцию сцены на изменение времени
viewer.clock.startTime = Cesium.JulianDate.fromIso8601("2026-01-01T00:00:00Z");
viewer.clock.stopTime  = Cesium.JulianDate.fromIso8601("2026-01-02T00:00:00Z");
viewer.clock.currentTime = viewer.clock.startTime;
viewer.clock.multiplier = 60;

Типичные ошибки при работе с интервалами

Перепутанные границы времени start должен быть строго меньше stop.

Отсутствие сортировки Ухудшает поиск в коллекции.

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

Использование неподходящего типа времени Cesium требует JulianDate, а не Date.


Роль в архитектуре временных данных CesiumJS

TimeInterval и TimeIntervalCollection формируют слой дискретного временного моделирования, на котором строятся:

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

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