# Calculating Ground Sample Distance (GSD) from Camera Altitude in CesiumJS

> Learn how to calculate Ground Sample Distance GSD in CesiumJS using camera altitude. Discover the simple formula and its practical applications for geospatial projects.

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

---

**Ground Sample Distance (GSD) in CesiumJS is calculated by multiplying the camera's ellipsoidal altitude in meters by an empirical scale factor of 0.000375, clamped to a minimum of 0.01 meters per pixel to prevent unrealistic values at low altitudes.**

In the **God's Eye View** open-source project, the Heads-Up Display (HUD) computes real-time GSD directly from the Cesium camera position to drive image quality metrics. This article breaks down the exact implementation found in the source code, explains the empirical constants, and provides reusable functions for your own geospatial applications.

## The Linear GSD Formula Used in God's Eye View

The core calculation resides in [`src/hud.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/hud.js) at lines 27-30, where the application derives GSD from the camera's ellipsoidal height:

```javascript
const gsd = Math.max(0.01, altM * 0.000375);   // meters per pixel

```

**`altM`** represents the camera height in meters extracted from `camera.positionCartographic.height`. The multiplication by **`0.000375`** applies an empirical scale factor derived for the default Cesium camera configuration, representing approximately 0.375 millimeters of ground resolution per meter of altitude.

### Understanding the Scale Factor (0.000375)

The factor `0.000375` captures the linear relationship between altitude and pixel footprint for a standard satellite-style view. Doubling the camera altitude roughly doubles the ground area covered by each pixel, maintaining a consistent ratio of 0.000375 meters of ground per pixel per meter of altitude. This approximation assumes default Cesium field-of-view settings and typical screen resolutions.

### Handling Edge Cases with Clamping

The **`Math.max(0.01, ...)`** operation clamps the GSD to a hard floor of 0.01 meters per pixel (1 centimeter). This prevents pathological sub-centimeter values that occur when the camera approaches the surface, avoiding potential division-by-zero errors or unrealistic precision claims in the HUD display.

## Converting GSD to NIIRS Image Quality

After computing GSD in meters, the HUD transforms the value to inches and applies the General Image Quality Equation (GIQE) to generate a NIIRS (National Imagery Interpretability Rating Scale) rating:

```javascript
const gsdInches = gsd * 39.37;
const niirs = Math.max(0, Math.min(9,
               10.25 - 3.32 * Math.log10(gsdInches)));

```

The conversion multiplies by **39.37** to convert meters to inches, then applies the logarithmic GIQE formula. The result is clamped between 0 and 9 to ensure valid NIIRS ratings regardless of extreme altitude values.

## Implementation in src/hud.js

According to the God's Eye View source code, the GSD calculation executes within the HUD module's update cycle, refreshing every 250 milliseconds (4 Hz). The [`src/hud.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/hud.js) file imports the camera position from the Cesium `Viewer` instance, extracts the ellipsoidal height, and passes it through the linear formula before displaying both the GSD and derived NIIRS rating in the overlay.

The repository also includes [`src/data/geoid.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/geoid.js), which provides optional geoid-undulation utilities for more accurate altitude corrections above mean sea level, though the basic GSD calculation uses ellipsoidal height directly.

## Reusable Code Examples

### Standalone GSD Calculation

Use this function in any Cesium-based project to replicate the HUD's ground sample distance logic:

```javascript
/**
 * Compute Ground Sample Distance (GSD) in metres per pixel.
 * @param {number} altitudeM – Camera height above the ellipsoid (meters).
 * @returns {number} GSD (m/px)
 */
function computeGSD(altitudeM) {
  // Linear approximation – matches the HUD implementation
  const scale = 0.000375;          // metres of ground per metre of altitude
  return Math.max(0.01, altitudeM * scale);
}

// Example usage:
const camera = viewer.camera;
const altitude = camera.positionCartographic.height; // metres
const gsd = computeGSD(altitude);
console.log(`GSD = ${gsd.toFixed(2)} m px⁻¹`);

```

### Deriving NIIRS from GSD

Mirror the HUD's GIQE conversion to calculate image interpretability ratings:

```javascript
/**
 * Convert GSD (metres per pixel) to NIIRS rating (0-9).
 * @param {number} gsdM - Ground Sample Distance in metres per pixel.
 * @returns {number} NIIRS (clamped between 0 and 9)
 */
function gsdToNIIRS(gsdM) {
  const inches = gsdM * 39.37;                 // metres → inches
  const niirs = 10.25 - 3.32 * Math.log10(inches);
  return Math.max(0, Math.min(9, niirs));
}

// Example:
const niirs = gsdToNIIRS(gsd);
console.log(`NIIRS ≈ ${niirs.toFixed(1)}`);

```

### Integrating into a Cesium Render Loop

Update a DOM element with real-time GSD and NIIRS values using the same 250ms cadence as the original HUD:

```javascript
const gsdEl = document.getElementById('hud-gsd');

function updateGSD() {
  const cam = viewer.camera;
  const alt = cam.positionCartographic.height;
  const gsd = computeGSD(alt);
  const niirs = gsdToNIIRS(gsd);
  gsdEl.textContent = `GSD: ${gsd.toFixed(2)} m  NIIRS: ${niirs.toFixed(1)}`;
}

// Run at 4 Hz (250 ms) – same cadence as the HUD
setInterval(updateGSD, 250);

```

## Summary

- **Ground Sample Distance** in God's Eye View uses a linear approximation: `altitude * 0.000375`
- The calculation clamps to **0.01 m/px** minimum to avoid unrealistic precision at low altitudes
- **NIIRS ratings** derive from GSD using the logarithmic GIQE formula with meter-to-inch conversion
- The implementation lives in **[`src/hud.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/hud.js)** and updates at **250ms intervals**
- The **0.000375** factor is empirical and calibrated for default Cesium camera FOV and screen resolution

## Frequently Asked Questions

### What is the exact formula for calculating GSD from altitude in CesiumJS?

The exact formula used in the God's Eye View repository is `GSD = Math.max(0.01, altitudeM * 0.000375)`, where `altitudeM` is the camera's ellipsoidal height in meters retrieved from `camera.positionCartographic.height`. The result represents ground meters per pixel.

### Why is the GSD clamped to 0.01 meters per pixel?

The clamp prevents pathological values when the camera flies extremely close to the terrain surface. Without this floor, the linear formula would generate sub-centimeter GSD values that are physically unrealistic for standard visualization purposes and could cause numerical instability in downstream calculations like the NIIRS rating.

### How accurate is the linear approximation for GSD calculation?

The linear approximation is accurate for typical satellite-style nadir views within the default Cesium camera configuration. The 0.000375 factor was derived empirically and assumes a standard field-of-view and screen resolution. For oblique angles or extreme zoom levels, the actual pixel footprint may vary from this approximation.

### Can I use this GSD calculation for orthorectified imagery analysis?

While the formula provides a useful approximation for heads-up display purposes, production orthorectification workflows typically require more sophisticated calculations accounting for sensor geometry, terrain elevation models, and precise camera parameters. The God's Eye View implementation is optimized for real-time visualization rather than photogrammetric precision.