В CesiumJS полигон рассматривается не как плоская фигура в двумерной декартовой системе координат, а как геометрический объект, наложенный на поверхность эллипсоида WGS84. Это фундаментально влияет на способы вычисления площади: классические формулы планиметрии становятся неточными при больших размерах или при расположении в высоких широтах.
Площадь полигона в CesiumJS определяется в зависимости от выбранной модели вычисления:
В CesiumJS полигон задаётся через структуру иерархии:
const polygon = new Cesium.Entity({
polygon: {
hierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray([
30.0, 10.0,
40.0, 10.0,
40.0, 20.0,
30.0, 20.0
])
)
}
});
PolygonHierarchy содержит:
Именно эта структура используется далее при вычислении площади, так как наличие отверстий требует вычитания соответствующих площадей.
Наиболее точный способ вычисления площади в CesiumJS основан на геодезических свойствах эллипсоида.
Ключевой инструмент — EllipsoidGeodesic, который позволяет работать с дугами большого круга и учитывать кривизну поверхности.
Идея вычисления:
CesiumJS не предоставляет одной универсальной функции площади полигона, поэтому используется комбинация низкоуровневых геодезических вычислений:
Практически распространённый метод — разбиение полигона на треугольники в трёхмерном пространстве.
Каждый треугольник задаётся тремя точками:
Площадь вычисляется через векторное произведение:
function triangleArea3D(a, b, c) {
const ab = Cesium.Cartesian3.subtract(b, a, new Cesium.Cartesian3());
const ac = Cesium.Cartesian3.subtract(c, a, new Cesium.Cartesian3());
const cross = Cesium.Cartesian3.cross(ab, ac, new Cesium.Cartesian3());
return Cesium.Cartesian3.magnitude(cross) * 0.5;
}
Общая площадь полигона:
function polygonAreaCartesian(positions) {
let area = 0.0;
const origin = positions[0];
for (let i = 1; i < positions.length - 1; i++) {
area += triangleArea3D(origin, positions[i], positions[i + 1]);
}
return area;
}
Данный метод:
Более корректный подход использует перевод координат в географические:
function polygonAreaGeodesic(positions) {
const ellipsoid = Cesium.Ellipsoid.WGS84;
let total = 0.0;
for (let i = 0; i < positions.length; i++) {
const p1 = Cesium.Cartographic.fromCartesian(positions[i]);
const p2 = Cesium.Cartographic.fromCartesian(
positions[(i + 1) % positions.length]
);
const geodesic = new Cesium.EllipsoidGeodesic(p1, p2);
const distance = geodesic.surfaceDistance;
total += p1.longitude * p2.latitude - p2.longitude * p1.latitude;
}
return Math.abs(total) * ellipsoid.maximumRadius * ellipsoid.maximumRadius / 2.0;
}
Такой подход ближе к сферической модели и используется как основа для приближённых расчётов больших областей.
В CesiumJS координаты полигона могут изменяться во времени. Для этого используется CallbackProperty, что влияет и на вычисление площади.
polygon: {
hierarchy: new Cesium.CallbackProperty(function () {
return new Cesium.PolygonHierarchy(dynamicPositions);
}, false)
}
При динамическом обновлении:
Основные источники погрешностей:
1. Кривизна эллипсоида
2. Разреженность вершин
3. Самопересечения
4. Высотная компонента
При работе с большим количеством полигонов в сцене CesiumJS важно учитывать производительность вычислений.
Применяются следующие подходы:
Кэширование результатов
Упрощение геометрии
Асинхронные вычисления
Локальная система координат
const center = Cesium.BoundingSphere.fromPoints(positions).center;
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
На практике часто используется гибридная стратегия:
Такой подход позволяет балансировать между точностью и производительностью, сохраняя корректность визуализации и аналитических вычислений в глобальных сценах CesiumJS.