Система визуализации CesiumJS предоставляет набор готовых геометрических примитивов: прямоугольники, полигоны, эллипсы, коридоры, цилиндры, сферы и многие другие. Однако при разработке специализированных геоинформационных систем, инженерных платформ, цифровых двойников или научных приложений часто возникает необходимость отображать объекты, форма которых не соответствует стандартным примитивам.
В таких случаях используются пользовательские геометрии (Custom Geometries) — объекты, создаваемые вручную путем определения вершин, индексов и дополнительных атрибутов.
На низком уровне любая геометрия в CesiumJS представляет собой набор данных:
Основным классом для создания собственной геометрии является
Cesium.Geometry.
Геометрический объект состоит из нескольких компонентов:
| Компонент | Назначение |
|---|---|
| Geometry | Хранение вершин и индексов |
| GeometryAttribute | Атрибуты вершин |
| GeometryInstance | Экземпляр геометрии |
| Primitive | Отображение на сцене |
| Appearance | Настройка визуального представления |
Типичная цепочка выглядит следующим образом:
Geometry
↓
GeometryInstance
↓
Primitive
↓
Scene
Таким образом, сама геометрия содержит только математическое описание объекта и не отображается напрямую.
Минимальная пользовательская геометрия содержит:
const geometry = new Cesium.Geometry({
attributes: {
position: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.DOUBLE,
componentsPerAttribute: 3,
values: positions
})
},
indices: indices,
primitiveType: Cesium.PrimitiveType.TRIANGLES,
boundingSphere: Cesium.BoundingSphere.fromVertices(positions)
});
Основные свойства:
Содержит набор атрибутов вершин.
Пример:
attributes: {
position: ...,
normal: ...,
st: ...,
color: ...
}
Определяет порядок соединения вершин.
Указывает способ интерпретации вершин.
Поддерживаются:
Cesium.PrimitiveType.POINTS
Cesium.PrimitiveType.LINES
Cesium.PrimitiveType.LINE_LOOP
Cesium.PrimitiveType.LINE_STRIP
Cesium.PrimitiveType.TRIANGLES
Cesium.PrimitiveType.TRIANGLE_STRIP
Cesium.PrimitiveType.TRIANGLE_FAN
Используется системой отсечения невидимых объектов и оптимизации рендеринга.
Любая геометрия начинается с описания вершин.
Например, треугольник:
const positions = new Float64Array([
0.0, 0.0, 0.0,
100.0, 0.0, 0.0,
0.0, 100.0, 0.0
]);
Каждая вершина содержит три координаты:
x
y
z
В Cesium координаты обычно задаются в мировой системе координат ECEF (Earth-Centered Earth-Fixed).
Для перевода географических координат используется:
const cartesian = Cesium.Cartesian3.fromDegrees(
37.6173,
55.7558,
100
);
Простейшая пользовательская геометрия:
const positions = new Float64Array([
0.0, 0.0, 0.0,
500.0, 0.0, 0.0,
0.0, 500.0, 0.0
]);
const indices = new Uint16Array([
0, 1, 2
]);
const geometry = new Cesium.Geometry({
attributes: {
position: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.DOUBLE,
componentsPerAttribute: 3,
values: positions
})
},
indices: indices,
primitiveType: Cesium.PrimitiveType.TRIANGLES,
boundingSphere:
Cesium.BoundingSphere.fromVertices(positions)
});
После создания геометрию необходимо обернуть в экземпляр:
const instance = new Cesium.GeometryInstance({
geometry: geometry
});
Для отображения геометрии создается примитив.
viewer.scene.primitives.add(
new Cesium.Primitive({
geometryInstances: instance,
appearance: new Cesium.PerInstanceColorAppearance({
flat: true
}),
asynchronous: false
})
);
Каждая вершина может иметь собственный цвет.
Создание массива цветов:
const colors = new Uint8Array([
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255
]);
Добавление атрибута:
color: new Cesium.GeometryAttribute({
componentDatatype:
Cesium.ComponentDatatype.UNSIGNED_BYTE,
componentsPerAttribute: 4,
normalize: true,
values: colors
})
Теперь каждая вершина получает свой цвет.
При использовании разных цветов на вершинах GPU автоматически выполняет интерполяцию.
Например:
Вершина 1 → красный
Вершина 2 → зелёный
Вершина 3 → синий
Внутри треугольника образуется плавный градиент.
Такой подход активно применяется для:
Для сложных фигур вершины обычно используются многократно.
Рассмотрим квадрат:
0 ----- 1
| |
| |
3 ----- 2
Вершины:
const positions = new Float64Array([
0, 0, 0,
1, 0, 0,
1, 1, 0,
0, 1, 0
]);
Индексы:
const indices = new Uint16Array([
0, 1, 2,
0, 2, 3
]);
Квадрат состоит из двух треугольников.
Нормаль определяет направление поверхности.
Она необходима для:
Пример массива нормалей:
const normals = new Float32Array([
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1
]);
Добавление:
normal: new Cesium.GeometryAttribute({
componentDatatype:
Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 3,
values: normals
})
Для треугольника нормаль рассчитывается через векторное произведение.
Пусть:
A
B
C
Тогда:
AB = B - A
AC = C - A
Нормаль:
N = AB × AC
После вычисления выполняется нормализация вектора.
Это обеспечивает единичную длину нормали.
Для наложения текстур используются координаты UV.
В Cesium они называются st.
Пример:
const sts = new Float32Array([
0, 0,
1, 0,
1, 1,
0, 1
]);
Добавление:
st: new Cesium.GeometryAttribute({
componentDatatype:
Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 2,
values: sts
})
После задания координат текстура может быть использована через материал.
appearance: new Cesium.MaterialAppearance({
material: Cesium.Material.fromType(
"Image",
{
image: "texture.jpg"
}
)
})
Координаты st определяют, какая область изображения
будет отображаться на поверхности.
Пользовательские геометрии позволяют формировать полноценные трёхмерные объекты.
Например:
Куб
Пирамида
Призма
Башня
Резервуар
Мост
Для этого необходимо описать:
Количество треугольников быстро возрастает, поэтому обычно геометрия генерируется программно.
Вершины куба:
const positions = [
-1, -1, -1,
1, -1, -1,
1, 1, -1,
-1, 1, -1,
-1, -1, 1,
1, -1, 1,
1, 1, 1,
-1, 1, 1
];
Каждая грань состоит из двух треугольников.
Всего:
6 граней
12 треугольников
36 индексов
Часто пользовательская геометрия должна быть привязана к реальным координатам.
Создание вершин:
const p1 = Cesium.Cartesian3.fromDegrees(
37.61, 55.75, 0
);
const p2 = Cesium.Cartesian3.fromDegrees(
37.62, 55.75, 0
);
const p3 = Cesium.Cartesian3.fromDegrees(
37.62, 55.76, 0
);
Преобразование в массив:
const positions =
new Float64Array([
p1.x, p1.y, p1.z,
p2.x, p2.y, p2.z,
p3.x, p3.y, p3.z
]);
Теперь геометрия располагается непосредственно на глобусе.
Cesium предоставляет набор инструментов обработки геометрии.
Основной модуль:
Cesium.GeometryPipeline
Он позволяет:
Пример:
geometry =
Cesium.GeometryPipeline.computeNormal(
geometry
);
При работе с крупными моделями количество вершин может достигать сотен тысяч и миллионов.
Основные методы оптимизации:
Плохо:
каждый треугольник имеет собственные вершины
Хорошо:
треугольники используют общие вершины
Если текстуры не используются:
st
не следует создавать.
Если освещение отсутствует:
normal
также можно исключить.
Неверно рассчитанная сфера приводит к лишней отрисовке.
Правильный вариант:
Cesium.BoundingSphere.fromVertices(
positions
);
Следует использовать:
Float32Array
Float64Array
Uint16Array
Uint32Array
Вместо:
Array
Это уменьшает потребление памяти и ускоряет передачу данных в GPU.
Пользовательские геометрии особенно полезны при создании собственных шейдеров.
Дополнительные атрибуты могут передаваться напрямую в GPU.
Например:
temperature
pressure
velocity
density
Каждая вершина может содержать научные или инженерные данные.
Шейдер затем использует их для расчета цвета, прозрачности или анимации.
Создание собственного атрибута:
customValue:
new Cesium.GeometryAttribute({
componentDatatype:
Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 1,
values: values
})
Такой атрибут становится доступным внутри GLSL-шейдера.
Подобный подход широко применяется при визуализации:
Если форма объекта меняется во времени, возможны два подхода.
Создается новый объект:
Geometry
GeometryInstance
Primitive
Старый удаляется.
Подходит для редких обновлений.
Для высокочастотной анимации предпочтительно изменять содержимое буферов GPU.
Такой подход применяется при отображении:
Пользовательские геометрии особенно востребованы в следующих задачах:
Благодаря прямому управлению вершинами, индексами и атрибутами пользовательские геометрии предоставляют максимальную гибкость при построении сложных трёхмерных объектов и позволяют реализовывать визуализации, которые невозможно создать с помощью стандартных примитивов CesiumJS.