Точки и маркеры

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

В CesiumJS существует несколько способов отображения точечных объектов:

  • объект PointGraphics;
  • объект BillboardGraphics;
  • коллекция PointPrimitiveCollection;
  • коллекция BillboardCollection;
  • комбинированное использование подписей (LabelGraphics) и маркеров.

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


Создание простой точки

Наиболее простой способ отображения точки — использование сущности (Entity) с компонентом point.

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(37.6176, 55.7558),
    point: {
        pixelSize: 12,
        color: Cesium.Color.RED
    }
});

Здесь:

  • position определяет координаты объекта;
  • pixelSize задаёт размер точки в пикселях;
  • color определяет цвет отображения.

После выполнения кода на поверхности Земли появится красная точка.


Настройка внешнего вида точки

Компонент PointGraphics предоставляет большое количество параметров оформления.

Размер точки

point: {
    pixelSize: 20
}

Чем больше значение, тем крупнее отображается объект.


Цвет точки

point: {
    pixelSize: 15,
    color: Cesium.Color.YELLOW
}

Поддерживаются все стандартные цвета Cesium.

Cesium.Color.BLUE
Cesium.Color.GREEN
Cesium.Color.ORANGE
Cesium.Color.CYAN

Также можно создавать собственные цвета.

color: new Cesium.Color(
    0.3,
    0.7,
    1.0,
    1.0
)

Компоненты задаются в диапазоне от 0 до 1.


Контур точки

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

point: {
    pixelSize: 16,
    color: Cesium.Color.RED,
    outlineColor: Cesium.Color.WHITE,
    outlineWidth: 3
}

Результатом станет красная точка с белым контуром.


Прозрачность

Прозрачность задаётся через альфа-канал.

point: {
    pixelSize: 18,
    color: Cesium.Color.RED.withAlpha(0.5)
}

Значение:

  • 1.0 — полностью непрозрачный объект;
  • 0.0 — полностью прозрачный объект.

Высота размещения точки

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

position: Cesium.Cartesian3.fromDegrees(
    37.6176,
    55.7558,
    1000
)

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


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

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

point: {
    pixelSize: 10,
    color: Cesium.Color.LIME,
    heightReference:
        Cesium.HeightReference.CLAMP_TO_GROUND
}

Доступны варианты:

Cesium.HeightReference.NONE
Cesium.HeightReference.CLAMP_TO_GROUND
Cesium.HeightReference.RELATIVE_TO_GROUND

NONE

Высота вычисляется относительно эллипсоида.

CLAMP_TO_GROUND

Точка прикрепляется к рельефу.

RELATIVE_TO_GROUND

Высота отсчитывается от поверхности рельефа.


Отображение маркеров через Billboard

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

Для этого применяется компонент billboard.

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(
        37.6176,
        55.7558
    ),
    billboard: {
        image: "marker.png"
    }
});

Вместо точки будет отображаться изображение.


Основные параметры Billboard

Изображение

billboard: {
    image: "images/city.png"
}

Поддерживаются:

  • PNG;
  • JPG;
  • SVG;
  • Canvas;
  • Data URL.

Размер изображения

billboard: {
    image: "marker.png",
    width: 48,
    height: 48
}

Размер задаётся в пикселях.


Масштабирование

billboard: {
    image: "marker.png",
    scale: 1.5
}

Значения:

  • 1.0 — исходный размер;
  • 2.0 — увеличение в два раза;
  • 0.5 — уменьшение в два раза.

Прозрачность

billboard: {
    image: "marker.png",
    color: Cesium.Color.WHITE.withAlpha(0.6)
}

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


Поворот маркера

billboard: {
    image: "arrow.png",
    rotation: Cesium.Math.toRadians(45)
}

Угол задаётся в радианах.


Смещение маркера

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

Горизонтальное и вертикальное смещение

billboard: {
    image: "marker.png",
    pixelOffset: new Cesium.Cartesian2(
        0,
        -20
    )
}

Первое значение отвечает за смещение по оси X, второе — по оси Y.


Смещение в мировых координатах

billboard: {
    image: "marker.png",
    eyeOffset: new Cesium.Cartesian3(
        0,
        0,
        -100
    )
}

Такое смещение работает в трёхмерном пространстве камеры.


Привязка изображения к точке

Очень часто нижняя часть иконки должна совпадать с координатой объекта.

Для этого используется параметр verticalOrigin.

billboard: {
    image: "pin.png",
    verticalOrigin:
        Cesium.VerticalOrigin.BOTTOM
}

Доступные варианты:

Cesium.VerticalOrigin.TOP
Cesium.VerticalOrigin.CENTER
Cesium.VerticalOrigin.BOTTOM

Горизонтальное выравнивание

billboard: {
    image: "pin.png",
    horizontalOrigin:
        Cesium.HorizontalOrigin.CENTER
}

Варианты:

Cesium.HorizontalOrigin.LEFT
Cesium.HorizontalOrigin.CENTER
Cesium.HorizontalOrigin.RIGHT

Создание маркера из Canvas

Необязательно загружать изображения с сервера. Маркер может формироваться программно.

const canvas =
    document.createElement("canvas");

canvas.width = 64;
canvas.height = 64;

const ctx = canvas.getContext("2d");

ctx.fillStyle = "red";

ctx.beginPath();
ctx.arc(32, 32, 25, 0, Math.PI * 2);
ctx.fill();

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(
        37.6176,
        55.7558
    ),
    billboard: {
        image: canvas
    }
});

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


Использование подписей вместе с маркерами

На практике точки часто сопровождаются текстом.

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(
        37.6176,
        55.7558
    ),
    billboard: {
        image: "city.png"
    },
    label: {
        text: "Москва"
    }
});

В одной сущности могут одновременно присутствовать:

  • точка;
  • маркер;
  • подпись;
  • трёхмерная модель;
  • геометрические примитивы.

Настройка подписей

Шрифт

label: {
    text: "Москва",
    font: "20px Arial"
}

Цвет текста

label: {
    text: "Москва",
    fillColor: Cesium.Color.WHITE
}

Контур текста

label: {
    text: "Москва",
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineColor: Cesium.Color.BLACK,
    outlineWidth: 3
}

Смещение подписи

label: {
    text: "Москва",
    pixelOffset:
        new Cesium.Cartesian2(0, -40)
}

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


Управление видимостью

Любая сущность может скрываться.

entity.show = false;

Повторное отображение:

entity.show = true;

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

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

entity.position =
    Cesium.Cartesian3.fromDegrees(
        38.0,
        56.0
    );

Маркер мгновенно переместится на новую позицию.


Анимация движения маркера

Для отображения движущихся объектов применяется SampledPositionProperty.

const position =
    new Cesium.SampledPositionProperty();

position.addSample(
    Cesium.JulianDate.now(),
    Cesium.Cartesian3.fromDegrees(
        37,
        55
    )
);

position.addSample(
    Cesium.JulianDate.addSeconds(
        Cesium.JulianDate.now(),
        60,
        new Cesium.JulianDate()
    ),
    Cesium.Cartesian3.fromDegrees(
        38,
        56
    )
);

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


Масштабирование по расстоянию

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

billboard: {
    image: "marker.png",
    scaleByDistance:
        new Cesium.NearFarScalar(
            1000,
            1.0,
            5000000,
            0.2
        )
}

При удалении камеры размер будет уменьшаться.


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

billboard: {
    image: "marker.png",
    translucencyByDistance:
        new Cesium.NearFarScalar(
            1000,
            1.0,
            5000000,
            0.0
        )
}

Удалённые объекты станут постепенно прозрачными.


Скрытие по расстоянию

billboard: {
    image: "marker.png",
    distanceDisplayCondition:
        new Cesium.DistanceDisplayCondition(
            0,
            300000
        )
}

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


Высокопроизводительные точки через PointPrimitiveCollection

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

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

const points =
    viewer.scene.primitives.add(
        new Cesium.PointPrimitiveCollection()
    );

points.add({
    position:
        Cesium.Cartesian3.fromDegrees(
            37.6176,
            55.7558
        ),
    pixelSize: 8,
    color: Cesium.Color.YELLOW
});

Преимущества:

  • высокая скорость рендеринга;
  • уменьшенное потребление памяти;
  • эффективная работа с большими объёмами данных.

Высокопроизводительные маркеры через BillboardCollection

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

const billboards =
    viewer.scene.primitives.add(
        new Cesium.BillboardCollection()
    );

billboards.add({
    position:
        Cesium.Cartesian3.fromDegrees(
            37.6176,
            55.7558
        ),
    image: "marker.png"
});

Такой механизм особенно полезен при отображении:

  • транспортных средств;
  • IoT-датчиков;
  • объектов мониторинга;
  • результатов геопространственного анализа;
  • данных телеметрии в реальном времени.

Выбор объектов мышью

Точки и маркеры могут участвовать во взаимодействии с пользователем.

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

handler.setInputAction(function(click) {

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

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

},
Cesium.ScreenSpaceEventType.LEFT_CLICK);

Метод pick() определяет объект под курсором.


Всплывающие описания

Для отображения дополнительной информации используется свойство description.

viewer.entities.add({
    position:
        Cesium.Cartesian3.fromDegrees(
            37.6176,
            55.7558
        ),

    billboard: {
        image: "city.png"
    },

    description: `
        <h2>Москва</h2>
        <p>Столица России</p>
    `
});

При выборе объекта содержимое будет показано в информационной панели Cesium.


Кластеризация маркеров

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

dataSource.clustering.enabled = true;

dataSource.clustering.pixelRange = 40;

dataSource.clustering.minimumClusterSize = 3;

Кластеризация:

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

Практические рекомендации

PointGraphics подходит для небольшого и среднего количества объектов, когда важна простота разработки.

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

PointPrimitiveCollection рекомендуется для десятков и сотен тысяч точек.

BillboardCollection эффективен при массовом отображении изображений.

LabelGraphics применяется для подписей, названий и поясняющей информации.

Комбинация точек, маркеров, подписей, динамического позиционирования, кластеризации и механизмов выбора объектов образует основу большинства геоинформационных приложений на базе CesiumJS, позволяя эффективно визуализировать как отдельные пространственные объекты, так и крупные наборы геоданных в глобальном трёхмерном пространстве.