# How to Calculate Off‑Nadir Angle from Camera Pitch in CesiumJS

> Learn how to calculate off-nadir angle from camera pitch in CesiumJS. Convert pitch, add 90 degrees, and clamp for accurate geospatial viewing. Optimize your camera controls today.

- Repository: [Bilawal Sidhu/gods-eye-view](https://github.com/bilawalsidhu/gods-eye-view)
- Tags: how-to-guide
- Published: 2026-08-30

---

**To calculate the off‑nadir angle in CesiumJS, convert the camera pitch from radians to degrees, add 90°, and clamp the result to a minimum of 0°, mapping a pitch of ‑90° (nadir) to 0° off‑nadir and 0° pitch to 90° off‑nadir.**

The *gods‑eye‑view* repository demonstrates how to derive precise sensor telemetry from CesiumJS camera states, including the transformation of camera pitch into the off‑nadir angle required for aerial imaging metadata. Understanding how to calculate off‑nadir angle from camera pitch in CesiumJS enables accurate ground‑sample distance estimates and sensor orientation displays in geospatial visualization tools.

## Understanding CesiumJS Camera Pitch Conventions

In CesiumJS, the camera pitch follows the right‑hand rule within the local east‑north‑up frame. A **pitch of ‑90°** indicates the camera is pointing straight down toward the Earth’s center (the nadir direction), while a **pitch of 0°** orients the camera toward the horizon. Positive pitch values tilt the camera above the horizon toward the zenith.

This convention means the pitch value represents an angular offset from the horizontal plane, where negative values look downward. The off‑nadir angle (ONA) represents the deviation from vertical, requiring a transformation to convert the Cesium pitch to a standard 0°–90° sensor angle used in photogrammetry.

## The Off‑Nadir Angle Formula

The conversion from CesiumJS pitch to off‑nadir angle follows a three‑step arithmetic process:

1. **Retrieve the pitch** from `camera.pitch`, which is stored in radians.
2. **Convert to degrees** using `Cesium.Math.toDegrees()` to obtain a signed decimal value.
3. **Add 90° and clamp** the result with `Math.max(0, 90 + pitchDeg)` to ensure the angle never drops below 0°.

This calculation maps the camera’s orientation to the standard off‑nadir definition: **0° ONA** when looking straight down and **90° ONA** at the horizon. The clamp ensures that if the camera pitch momentarily registers less than ‑90° (beyond straight down), the result floors at 0° rather than returning a negative value.

## Implementation in the Gods Eye View HUD

According to the `bilawalsidhu/gods-eye-view` source code, the logic resides in [`src/hud.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/hud.js) within the `IntelHUD._updateCameraData` method. This method executes each frame to update the heads‑up display telemetry, retrieving the camera pitch, applying the conversion formula, and injecting the formatted result into the DOM:

```javascript
// src/hud.js – lines 54‑60
const pitchDeg = Cesium.Math.toDegrees(camera.pitch);
const ona = Math.max(0, 90 + pitchDeg);
const onaEl = document.getElementById('hud-ona');
if (onaEl) onaEl.textContent = `ONA: ${ona.toFixed(1)}°`;

```

This code runs inside the HUD’s update loop, ensuring the off‑nadir angle displayed alongside **GSD** (Ground Sample Distance) and **NIIRS** ratings remains synchronized with the current camera orientation.

## Practical Code Examples

### Stand‑Alone Calculation

For custom geospatial tools that need to compute the off‑nadir angle without the full HUD, extract the pitch from the viewer’s camera and apply the same transformation used in the gods‑eye‑view repository:

```javascript
// Compute off‑nadir angle from Cesium camera pitch
function computeOffNadir(camera) {
  const pitchDeg = Cesium.Math.toDegrees(camera.pitch); // e.g., -30°
  const offNadir = Math.max(0, 90 + pitchDeg);          // → 60°
  return offNadir;
}

// Usage with a Cesium viewer instance
const ona = computeOffNadir(viewer.camera);
console.log(`Off‑nadir angle: ${ona.toFixed(1)}°`);

```

### Integrating into a Custom HUD

To display the ONA in a custom interface that updates every frame, register a callback with the scene’s post‑render event and format the output for your UI elements:

```javascript
function updateHUD() {
  const pitchDeg = Cesium.Math.toDegrees(viewer.camera.pitch);
  const offNadir = Math.max(0, 90 + pitchDeg);
  document.getElementById('my-ona').textContent = `ONA: ${offNadir.toFixed(1)}°`;
}

// Update once per render loop
viewer.scene.postRender.addEventListener(updateHUD);

```

Both snippets follow the arithmetic defined in [`src/hud.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/hud.js), ensuring consistency with the built‑in telemetry display.

## Summary

- **CesiumJS pitch** uses radians where ‑90° is nadir (straight down) and 0° is the horizon.
- **Off‑nadir angle** is calculated by adding 90° to the pitch (in degrees) and clamping to 0° minimum.
- The implementation resides in [`src/hud.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/hud.js) inside the `IntelHUD._updateCameraData` method.
- Use `Cesium.Math.toDegrees()` to convert from radians before applying the offset.
- Clamp with `Math.max(0, ...)` to prevent negative angles when the camera pitch exceeds ‑90°.

## Frequently Asked Questions

### What is the off‑nadir angle in CesiumJS aerial mapping?

The off‑nadir angle (ONA) is the angular deviation between the camera’s optical axis and the vertical (nadir) direction. In aerial mapping workflows using CesiumJS, this angle determines the tilt of the sensor relative to the ground, directly affecting ground coverage and image distortion calculations.

### Why add 90 degrees to the camera pitch?

CesiumJS defines **0° pitch as the horizon** and **‑90° pitch as straight down (nadir)**. Since off‑nadir angle is defined as 0° when looking straight down and 90° at the horizon, adding 90° to the Cesium pitch value reconciles these coordinate systems. For example, a pitch of ‑45° becomes 45° off‑nadir.

### Where is the ONA calculation implemented in the gods‑eye‑view repository?

The calculation is implemented in [`src/hud.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/hud.js) within the `IntelHUD._updateCameraData` method (lines 54‑60). This method reads `camera.pitch`, converts it to degrees using `Cesium.Math.toDegrees`, computes the off‑nadir value, and updates the DOM element with ID `hud-ona` to display the telemetry.

### Why is the off‑nadir angle clamped to 0°?

The `Math.max(0, ...)` clamp prevents negative off‑nadir angles when the camera pitch drops below ‑90° (beyond straight down), which can occur during rapid camera animations or specific orientation constraints. While pitch values above the horizon produce results greater than 90°, the clamp ensures the minimum value remains 0° for all downward‑looking orientations.