В веб-графике глобальных сцен библиотека CesiumJS оперирует не только координатами, но и ориентацией объектов в пространстве. Любое направление на глобусе задаётся через комбинацию географических и локальных систем координат, где ключевую роль играют азимуты, углы поворота камеры и преобразования между системами отсчёта.
Азимут представляет собой угол между направлением на север и проекцией направления объекта на горизонтальную плоскость.
В контексте CesiumJS азимут чаще всего связан с понятием heading — угла поворота относительно северного направления в локальной касательной плоскости Earth-Centered, Earth-Fixed (ECEF).
Формально:
В CesiumJS азимут выражается в радианах, а не в градусах, что требует постоянных преобразований:
const headingRad = Cesium.Math.toRadians(90);
const headingDeg = Cesium.Math.toDegrees(headingRad);
Работа с направлениями в CesiumJS невозможна без понимания локальной системы координат:
Преобразование между ними является основой для вычисления азимута:
const cartographic = Cesium.Cartographic.fromCartesian(position);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
В CesiumJS направление объекта задаётся через структуру HeadingPitchRoll, которая определяет вращение относительно локальной системы координат.
const hpr = new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(45), // heading
Cesium.Math.toRadians(-10), // pitch
Cesium.Math.toRadians(0) // roll
);
Для применения ориентации к объекту используется преобразование к кватерниону:
const quaternion = Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
);
Одной из ключевых задач является вычисление направления от одной точки на поверхности Земли к другой.
Алгоритм основан на геодезической формуле начального курса (initial bearing):
const start = Cesium.Cartographic.fromDegrees(lon1, lat1);
const end = Cesium.Cartographic.fromDegrees(lon2, lat2);
const geodesic = new Cesium.EllipsoidGeodesic(start, end);
const heading = geodesic.startHeading;
Значение startHeading возвращается в радианах и
соответствует азимуту от начальной точки к конечной.
Камера в CesiumJS имеет собственную систему ориентации, где азимут напрямую влияет на вращение сцены.
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(30, 50, 10000),
orientation: {
heading: Cesium.Math.toRadians(120),
pitch: Cesium.Math.toRadians(-30),
roll: 0
}
});
Здесь:
В CesiumJS локальные направления определяются относительно точки наблюдения:
Азимут (heading) фактически является углом между осью Y (север) и проекцией направления на плоскость X–Y.
Вектор направления камеры можно получить через матрицу преобразования:
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
const rotation = Cesium.Matrix4.getMatrix3(transform, new Cesium.Matrix3());
CesiumJS работает в радианах, но при расчётах часто возникает необходимость нормализации:
const normalized = Cesium.Math.zeroToTwoPi(angle);
Или приведение к стандартному диапазону:
const wrapped = Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(angle);
Для перевода математического угла в географический азимут используется соответствие:
| Угол (градусы) | Направление |
|---|---|
| 0 | Север |
| 90 | Восток |
| 180 | Юг |
| 270 | Запад |
CesiumJS использует математическую систему координат, где положительное направление вращения — против часовой стрелки, что важно при интерпретации азимута.
При работе с моделями (3D Tiles, glTF) направление объекта определяется не только heading, но и исходной ориентацией модели.
const modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
position,
hpr
);
Любое изменение heading изменяет ориентацию модели относительно глобального севера.
Азимут можно вычислить через вектор направления между двумя Cartesian3 точками:
const direction = Cesium.Cartesian3.subtract(
target,
origin,
new Cesium.Cartesian3()
);
Cesium.Cartesian3.normalize(direction, direction);
Далее проекция на плоскость ENU позволяет получить угол:
const enu = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
const inverse = Cesium.Matrix4.inverse(enu, new Cesium.Matrix4());
const localDir = Cesium.Matrix4.multiplyByPoint(inverse, direction, new Cesium.Cartesian3());
Азимут вычисляется как:
const heading = Math.atan2(localDir.x, localDir.y);
В задачах навигации heading применяется для:
Пример привязки ориентации к скорости движения:
const heading = Cesium.Math.toRadians(velocityBearing);
const hpr = new Cesium.HeadingPitchRoll(heading, 0, 0);
entity.orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
);
При вычислениях азимута в глобальных координатах возникают погрешности:
CesiumJS компенсирует эти эффекты через использование эллипсоида WGS84 и встроенных геодезических функций.
Азимут в CesiumJS является связующим элементом между:
Через heading формируется единая модель направления, применимая к камере, моделям, траекториям и геодезическим вычислениям в глобальной сцене.