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

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 at lines 27-30, where the application derives GSD from the camera's ellipsoidal height:

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:

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 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, 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:

/**
 * 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:

/**
 * 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:

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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →