Point Cloud (облако точек) представляет собой набор пространственных точек, каждая из которых содержит координаты и дополнительные атрибуты: цвет, интенсивность отражённого сигнала, классификацию, нормали поверхности и другие данные. Облака точек широко применяются в геодезии, картографии, строительстве, горнодобывающей промышленности, городском планировании и системах цифровых двойников.
В экосистеме CesiumJS облака точек чаще всего используются для визуализации данных лазерного сканирования (LiDAR), фотограмметрии и результатов трёхмерной съёмки территорий. Благодаря поддержке стандарта 3D Tiles, движок способен эффективно отображать миллиарды точек, автоматически подгружая только необходимые данные.
Основные преимущества использования Point Cloud в CesiumJS:
В большинстве случаев облака точек загружаются через формат 3D Tiles Point Cloud.
Структура обычно состоит из:
tileset.json
├── tile_0.pnts
├── tile_1.pnts
├── tile_2.pnts
└── ...
Файл tileset.json содержит описание иерархии тайлов, а
файлы .pnts хранят непосредственно точки.
Cesium использует механизм:
Подобный подход позволяет работать даже с очень большими облаками точек.
Наиболее распространённый способ отображения облака точек выглядит следующим образом:
const viewer = new Cesium.Viewer("cesiumContainer");
const pointCloud = await Cesium.Cesium3DTileset.fromUrl(
"./tileset/tileset.json"
);
viewer.scene.primitives.add(pointCloud);
await viewer.zoomTo(pointCloud);
После загрузки Cesium автоматически определяет тип содержимого тайлов. Если внутри находятся данные Point Cloud, будет использован соответствующий рендерер.
Файлы Point Cloud в 3D Tiles используют расширение:
.pnts
Каждая точка может содержать:
| Атрибут | Описание |
|---|---|
| POSITION | Координаты точки |
| RGB | Цвет |
| RGBA | Цвет и прозрачность |
| NORMAL | Нормаль |
| INTENSITY | Интенсивность сигнала LiDAR |
| CLASSIFICATION | Класс объекта |
| BATCH_ID | Идентификатор группы |
Например, точка может описываться следующими данными:
X: 412345.22
Y: 5842231.11
Z: 112.45
R: 120
G: 180
B: 210
Intensity: 86
Classification: Building
Многие облака точек уже содержат геопривязку и автоматически отображаются в правильном месте.
Однако иногда требуется дополнительное преобразование.
const tileset = await Cesium.Cesium3DTileset.fromUrl(
"./tileset/tileset.json"
);
viewer.scene.primitives.add(tileset);
const translation = Cesium.Cartesian3.fromElements(
10,
20,
5
);
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(
translation
);
const heading = Cesium.Math.toRadians(90);
const matrix =
Cesium.Transforms.headingPitchRollToFixedFrame(
Cesium.Cartesian3.fromDegrees(
37.62,
55.75,
0
),
new Cesium.HeadingPitchRoll(
heading,
0,
0
)
);
tileset.modelMatrix = matrix;
Для облаков точек важным параметром является размер отображаемых элементов.
Cesium предоставляет объект:
Cesium.PointCloudShading
Пример настройки:
tileset.pointCloudShading =
new Cesium.PointCloudShading({
attenuation: true
});
tileset.pointCloudShading =
new Cesium.PointCloudShading({
attenuation: true,
geometricErrorScale: 2.0
});
Параметр geometricErrorScale влияет на визуальную
плотность и размер отображаемых точек.
Система шейдинга позволяет сделать изображение более реалистичным.
Пример:
tileset.pointCloudShading =
new Cesium.PointCloudShading({
attenuation: true,
eyeDomeLighting: true
});
Eye Dome Lighting (EDL) создаёт псевдо-тени между соседними точками.
Без EDL:
Объекты выглядят плоскими.
С EDL:
Появляется визуальная глубина.
Улучшается читаемость рельефа.
Повышается различимость мелких деталей.
Настройка:
tileset.pointCloudShading =
new Cesium.PointCloudShading({
eyeDomeLighting: true,
eyeDomeLightingStrength: 1.5,
eyeDomeLightingRadius: 2.0
});
Cesium позволяет менять внешний вид точек через систему стилей.
Создание стиля:
tileset.style = new Cesium.Cesium3DTileStyle({
color: "color('yellow')"
});
Все точки будут окрашены в жёлтый цвет.
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${POSITION}[2] > 100", "color('red')"],
["${POSITION}[2] > 50", "color('orange')"],
["true", "color('green')"]
]
}
});
Здесь используется координата Z.
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${Intensity} > 200", "color('white')"],
["${Intensity} > 100", "color('gray')"],
["true", "color('black')"]
]
}
});
Подобный подход часто применяется для анализа лазерного сканирования.
Многие LiDAR-данные содержат поле классификации.
Типичные значения:
| Код | Объект |
|---|---|
| 1 | Не классифицировано |
| 2 | Земля |
| 3 | Растительность |
| 6 | Здание |
| 9 | Вода |
Стилизация по классу:
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${Classification} === 2", "color('brown')"],
["${Classification} === 3", "color('green')"],
["${Classification} === 6", "color('gray')"],
["true", "color('white')"]
]
}
});
Отображение только определённых объектов:
tileset.style = new Cesium.Cesium3DTileStyle({
show: "${Classification} === 6"
});
Будут отображаться только здания.
Фильтрация по высоте:
tileset.style = new Cesium.Cesium3DTileStyle({
show: "${POSITION}[2] > 50"
});
Комбинированная фильтрация:
tileset.style = new Cesium.Cesium3DTileStyle({
show:
"${Classification} === 6 && " +
"${POSITION}[2] > 100"
});
Cesium автоматически выбирает подходящий уровень детализации.
Основной параметр:
tileset.maximumScreenSpaceError = 8;
Меньшее значение:
tileset.maximumScreenSpaceError = 2;
Преимущества:
Недостатки:
Для повышения производительности:
tileset.maximumScreenSpaceError = 32;
В этом случае движок будет отображать меньше данных.
Крупные облака точек способны занимать несколько гигабайт данных.
Контроль кэша:
tileset.cacheBytes = 1024 * 1024 * 512;
Пример ограничивает кэш до 512 МБ.
Настройка максимального объёма:
tileset.maximumCacheOverflowBytes =
1024 * 1024 * 256;
Выбор объекта выполняется через механизм picking.
const handler =
new Cesium.ScreenSpaceEventHandler(
viewer.canvas
);
handler.setInputAction(function(click) {
const picked =
viewer.scene.pick(click.position);
console.log(picked);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
После выбора точки можно получить её свойства.
const feature =
viewer.scene.pick(click.position);
if (feature) {
console.log(
feature.getProperty("Intensity")
);
console.log(
feature.getProperty("Classification")
);
}
Point Cloud часто используется совместно с:
Пример совместного отображения:
viewer.scene.primitives.add(pointCloud);
viewer.scene.primitives.add(buildingTileset);
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(
37.62,
55.75
),
point: {
pixelSize: 12
}
});
| Характеристика | Point Cloud | Photogrammetry |
|---|---|---|
| Точность измерений | Очень высокая | Средняя |
| Размер данных | Большой | Большой |
| Геометрия | Точки | Треугольники |
| Скорость рендера | Высокая | Средняя |
| Работа с измерениями | Отлично | Хорошо |
| Визуальная реалистичность | Средняя | Очень высокая |
Point Cloud чаще применяется для инженерных задач, тогда как фотограмметрические модели ориентированы на визуализацию.
Для крупных проектов рекомендуется:
Разбиение данных на тайлы позволяет Cesium загружать только видимую часть сцены.
tileset.pointCloudShading =
new Cesium.PointCloudShading({
attenuation: true
});
Это уменьшает визуальные артефакты при большом удалении камеры.
tileset.maximumScreenSpaceError = 16;
Баланс между качеством и производительностью достигается экспериментальным подбором значения.
tileset.style = new Cesium.Cesium3DTileStyle({
show: "${Classification} !== 1"
});
Удаление ненужных категорий снижает нагрузку на графическую подсистему.
const viewer = new Cesium.Viewer(
"cesiumContainer"
);
const tileset =
await Cesium.Cesium3DTileset.fromUrl(
"./lidar/tileset.json"
);
tileset.maximumScreenSpaceError = 8;
tileset.pointCloudShading =
new Cesium.PointCloudShading({
attenuation: true,
eyeDomeLighting: true,
eyeDomeLightingStrength: 1.2
});
tileset.style =
new Cesium.Cesium3DTileStyle({
color: {
conditions: [
[
"${Classification} === 2",
"color('saddlebrown')"
],
[
"${Classification} === 3",
"color('green')"
],
[
"${Classification} === 6",
"color('gray')"
],
[
"true",
"color('white')"
]
]
}
});
viewer.scene.primitives.add(
tileset
);
viewer.zoomTo(
tileset
);
Данный пример демонстрирует типичный сценарий визуализации LiDAR-данных: загрузку облака точек в формате 3D Tiles, настройку уровня детализации, включение улучшенного шейдинга и раскрашивание объектов на основе классификации данных.