Пользовательские источники данных

CesiumJS построен вокруг концепции источников данных (DataSource), которые отделяют получение и обновление пространственных данных от их отображения в сцене. Такая архитектура позволяет унифицировать работу с различными форматами — от GeoJSON и CZML до полностью пользовательских потоков данных, поступающих из API, WebSocket или собственных вычислительных моделей.

Внутри CesiumJS слой данных отделён от слоя рендеринга. Viewer не работает напрямую с геометрией, он взаимодействует с абстракцией DataSource через коллекцию viewer.dataSources.

Каждый источник данных отвечает за три ключевых аспекта:

  • хранение сущностей (Entity)
  • обновление состояния во времени
  • предоставление данных для отрисовки

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

Базовая идея: DataSource — это адаптер между внешними данными и внутренней моделью сущностей Cesium.


Интерфейс DataSource

Любой источник данных в CesiumJS реализует интерфейс, включающий следующие обязательные элементы:

  • entities — коллекция сущностей
  • clock (опционально) — управление временем
  • show — видимость источника
  • changedEvent — сигнал обновления данных
  • errorEvent — обработка ошибок загрузки
  • isLoading — состояние загрузки
  • update() — метод синхронизации состояния

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

Entity — это высокоуровневая абстракция над примитивами (Primitive API), позволяющая описывать объекты декларативно.


Создание собственного источника данных

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

Простейшая структура кастомного источника:

  • создание коллекции сущностей
  • загрузка внешних данных
  • преобразование данных в Entity
  • обновление состояния

Основная логика строится вокруг преобразования входного формата в Entity-представление.

Типовой сценарий: получение данных с REST API и отображение объектов на карте.


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

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

Псевдоструктура:

  • запрос данных
  • парсинг JSON
  • создание Entity
  • добавление в entities.add()

Entity может включать:

  • координаты (Cartesian3 / Cartographic)
  • геометрию (точка, линия, полигон)
  • описание стиля (цвет, прозрачность, материал)
  • временные интервалы (TimeIntervalCollection)

Интеграция с Viewer

Все источники данных подключаются через:

  • viewer.dataSources.add(dataSource)
  • viewer.dataSources.remove(dataSource)

После добавления источник автоматически становится частью сцены, а Viewer начинает учитывать его в:

  • рендеринге
  • подборе объектов (picking)
  • обработке времени
  • масштабировании (zoom to entities)

Важно, что Viewer не делает различий между встроенными и пользовательскими источниками.


Асинхронная загрузка данных

Большинство пользовательских источников работает асинхронно. CesiumJS поддерживает Promise-based загрузку через методы:

  • load()
  • update()

Асинхронность используется для:

  • загрузки больших GeoJSON файлов
  • потоковых данных (WebSocket)
  • динамических API (например, телеметрия)

Типовая модель:

  1. инициализация источника
  2. запуск запроса
  3. заполнение entities после получения данных
  4. уведомление через changedEvent

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

CesiumJS тесно связан с концепцией времени. DataSource может быть временно-зависимым.

Clock в CesiumJS управляет:

  • текущим временем сцены
  • скоростью воспроизведения
  • диапазоном времени

Entity может содержать:

  • Availability (доступность во времени)
  • SampledPositionProperty (траектории)
  • TimeIntervalCollectionProperty

Это позволяет строить динамические системы:

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

События и реактивность

Каждый DataSource поддерживает событийную модель:

  • changedEvent — изменения данных
  • errorEvent — ошибки загрузки
  • loadingEvent — состояние загрузки

События используются для синхронизации UI и внешней логики без постоянного опроса состояния.

Типичный сценарий — обновление интерфейса при завершении загрузки данных.


Преобразование внешних форматов

Пользовательские источники часто выступают в роли адаптеров для стандартных форматов:

  • GeoJSON → Entity
  • CSV → точки и линии
  • API JSON → динамические объекты
  • бинарные потоки → оптимизированные геометрии

GeoJSONDataSource внутри CesiumJS уже реализует подобную логику, но пользовательские источники позволяют расширять её под специфические структуры.

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

  • WGS84 (широта/долгота)
  • Cartesian3 (внутренняя система Cesium)
  • локальные системы координат

Стилизация сущностей

После создания Entity внешний вид управляется через свойства:

  • point
  • billboard
  • polyline
  • polygon

Каждое из них поддерживает:

  • цвет
  • прозрачность
  • масштаб
  • динамические свойства (Property API)

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

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

Оптимизация и кластеризация

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

Основные механизмы:

  • кластеризация точек (Entity clustering)
  • уровень детализации (LOD)
  • фильтрация по времени
  • виртуализация сущностей

Кластеризация особенно важна при отображении тысяч точек:

  • объединение близких объектов
  • динамическое разбиение при зуме
  • уменьшение нагрузки на GPU

CesiumJS поддерживает кластеризацию на уровне EntityCollection через entityCluster.


Потоковые данные и WebSocket-интеграция

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

Типичная архитектура:

  • WebSocket соединение
  • получение координат в реальном времени
  • обновление существующих Entity вместо создания новых
  • ограничение частоты обновления

В таких системах критично:

  • переиспользование Entity
  • минимизация аллокаций
  • контроль частоты перерисовки сцены

Управление жизненным циклом данных

Пользовательский DataSource проходит несколько фаз:

  • инициализация
  • загрузка
  • активное обновление
  • выгрузка

При удалении источника важно:

  • очистить entities
  • отключить подписки
  • освободить ссылки на внешние ресурсы

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


Паттерны проектирования пользовательских источников

На практике применяются несколько устойчивых архитектурных подходов:

  • Adapter Pattern — преобразование внешних API в Entity
  • Observer Pattern — реакция на потоковые обновления
  • Factory Pattern — создание сущностей по типам данных
  • Repository Pattern — централизованное управление источниками

Особенно эффективна комбинация Adapter + Observer при работе с телеметрией.


Расширяемые источники и композиция

Источники данных могут комбинироваться:

  • несколько DataSource в одном Viewer
  • агрегирование данных на уровне приложения
  • фильтрация по слоям

Это позволяет строить сложные сцены:

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

Каждый источник остаётся независимым, но визуально интегрированным в единую сцену.


Работа с ошибками и устойчивость

При работе с внешними источниками данных неизбежны:

  • сетевые сбои
  • некорректные данные
  • задержки API

CesiumJS предоставляет errorEvent, но логика устойчивости обычно реализуется на уровне пользовательского источника:

  • повторные попытки загрузки
  • fallback-данные
  • частичное обновление Entity

Динамическая фильтрация данных

Пользовательские источники часто включают механизмы фильтрации:

  • по типу объекта
  • по времени
  • по значению параметров

Фильтрация может выполняться:

  • до создания Entity
  • после добавления в коллекцию
  • через изменение свойства show

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