В ядре CesiumJS используется несколько взаимосвязанных систем координат, каждая из которых решает конкретный класс задач: от отображения точек на эллипсоиде до расчёта ориентации 3D-моделей в локальных и глобальных пространствах.
Основные типы представлений:
Конвертация между ними выполняется через утилиты
Cesium.Cartesian3 и Cesium.Cartographic.
const cartesian = Cesium.Cartesian3.fromDegrees(69.6, 42.3, 1000);
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
Ключевой момент: внутренняя сцена всегда работает в Cartesian3, а географические координаты используются только на уровне API.
При работе с поверхностью Земли необходимо учитывать рельеф, который
задаётся через terrain-provider. Прямое использование
fromDegrees игнорирует высоту поверхности, поэтому
применяется уточнение через выборку высот.
const position = Cesium.Cartesian3.fromDegrees(69.6, 42.3);
const updatedPosition = Cesium.Cartesian3.fromDegrees(
69.6,
42.3,
0
);
const terrainPosition = Cesium.Cartesian3.fromDegrees(
69.6,
42.3,
Cesium.sampleTerrainMostDetailed
);
В реальных сценариях используется асинхронная выборка:
const positions = [Cesium.Cartographic.fromDegrees(69.6, 42.3)];
Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, positions)
.then((updated) => {
console.log(updated[0].height);
});
Для ориентации объектов в локальном пространстве используется система ENU (East-North-Up). Она формирует локальную базу осей относительно точки на поверхности эллипсоида.
const origin = Cesium.Cartesian3.fromDegrees(69.6, 42.3);
const enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
Эта матрица преобразует локальные координаты (X — восток, Y — север, Z — вверх) в глобальные Cartesian3.
Применение:
const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
viewer.entities.add({
position: origin,
model: {
uri: "model.glb",
modelMatrix: modelMatrix
}
});
Ключевой момент: ENU используется для «привязки» объектов к поверхности с сохранением локальной логики движения.
Для управления направлением объектов применяется система углов:
Эта система широко используется в авиационной и навигационной визуализации.
const heading = Cesium.Math.toRadians(90);
const pitch = Cesium.Math.toRadians(0);
const roll = Cesium.Math.toRadians(0);
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
Cesium.Cartesian3.fromDegrees(69.6, 42.3),
hpr
);
Применение в сущностях:
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(69.6, 42.3),
orientation: orientation,
model: {
uri: "aircraft.glb"
}
});
Внутренне Cesium использует кватернионы для представления вращений, что устраняет проблему gimbal lock и обеспечивает стабильную интерполяцию.
Создание кватерниона напрямую:
const hpr = Cesium.HeadingPitchRoll.fromDegrees(45, 10, 0);
const quaternion = Cesium.Quaternion.fromHeadingPitchRoll(hpr);
Кватернионы используются в:
Полное управление положением объекта часто требует использования
Matrix4.
const translation = Cesium.Cartesian3.fromDegrees(69.6, 42.3, 0);
const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(translation);
Для кастомных преобразований:
const scale = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(2.0, 2.0, 2.0));
Cesium.Matrix4.multiply(modelMatrix, scale, modelMatrix);
Матричная цепочка обычно включает:
Камера в Cesium — полноценный объект с позиционированием и ориентацией в 3D пространстве.
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(69.6, 42.3, 10000),
orientation: {
heading: Cesium.Math.toRadians(90),
pitch: Cesium.Math.toRadians(-30),
roll: 0
}
});
Методы управления:
lookAt — привязка камеры к точкеflyTo — анимированный переходsetView — мгновенная установкаПример привязки:
const target = Cesium.Cartesian3.fromDegrees(69.6, 42.3);
viewer.camera.lookAt(
target,
new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(0),
Cesium.Math.toRadians(-20),
5000
)
);
Cesium поддерживает различные системы отсчёта:
Преобразование:
const fixedFrame = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(69.6, 42.3)
);
И обратное преобразование:
const inverse = Cesium.Matrix4.inverseTransformation(fixedFrame, new Cesium.Matrix4());
Это позволяет строить иерархические сцены: объекты внутри объектов.
Entity-система автоматически вычисляет модельные матрицы при наличии
position и orientation.
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(69.6, 42.3),
orientation: Cesium.Transforms.headingPitchRollQuaternion(
Cesium.Cartesian3.fromDegrees(69.6, 42.3),
new Cesium.HeadingPitchRoll(0, 0, 0)
),
box: {
dimensions: new Cesium.Cartesian3(100, 100, 100)
}
});
Если orientation не задана, объект ориентируется по
глобальной системе координат без вращения.
Для динамических объектов используются функции обновления на каждом кадре:
viewer.clock.onTick.addEventListener(() => {
const time = viewer.clock.currentTime;
const position = Cesium.Cartesian3.fromDegrees(
69.6 + Math.sin(Cesium.JulianDate.secondsDifference(time, viewer.clock.startTime)) * 0.1,
42.3
);
viewer.entities.getById("moving").position = position;
});
Ориентация может обновляться синхронно с движением:
entity.orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
new Cesium.HeadingPitchRoll(angle, 0, 0)
);
Для сложных сценариев, например следования рельефу, используется нормаль поверхности.
const position = Cesium.Cartesian3.fromDegrees(69.6, 42.3);
const surfaceNormal = viewer.scene.globe.ellipsoid.geodeticSurfaceNormal(
position,
new Cesium.Cartesian3()
);
Это позволяет ориентировать объект вдоль поверхности Земли.
Типичная цепочка трансформаций объекта в Cesium:
Каждый слой влияет на итоговую визуализацию и может быть
переопределён вручную через Matrix4 или автоматически через
Entity API.
Комбинированные сценарии часто требуют явного разделения:
const position = Cesium.Cartesian3.fromDegrees(69.6, 42.3);
const hpr = new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(120),
0,
0
);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
viewer.entities.add({
position,
orientation,
model: { uri: "vehicle.glb" }
});