How to Calculate Sun Elevation in CesiumJS: Astronomical Implementation Guide
To calculate sun elevation in CesiumJS, compute the solar declination from the day-of-year, derive the hour angle from local solar time, and solve the classical elevation formula using Cesium.Math.toRadians and Cesium.Math.toDegrees for precision unit conversions.
The God’s Eye View repository demonstrates how to calculate sun elevation in CesiumJS using a self-contained astronomical model that requires no external libraries. The implementation resides in src/hud.js, where the _estimateSunElevation function processes observer coordinates and UTC time to return a signed degree value indicating the sun's altitude above the horizon.
The Solar Elevation Formula
The algorithm implements the standard astronomical formula for solar elevation:
sin(elevation) = sin(φ) × sin(δ) + cos(φ) × cos(δ) × cos(H)
Where:
- φ represents the observer's latitude in radians
- δ represents the solar declination angle (approximated from the calendar date)
- H represents the hour angle derived from local solar time
Implementation in src/hud.js
The _estimateSunElevation function in src/hud.js executes a five-step calculation to determine the sun's position.
1. Determine Local Solar Time
The function converts UTC to local solar time by applying the longitude correction (15 degrees per hour).
2. Calculate Hour Angle
The hour angle H equals (localSolarTime - 12) × 15°, representing the sun's angular distance from solar noon.
3. Approximate Solar Declination
The declination uses a sinusoidal approximation with 23.45° amplitude:
const declination = 23.45 *
Math.sin(Cesium.Math.toRadians(
(360 / 365) *
(now.getUTCDate() + 30 * now.getUTCMonth() - 81)
));
4. Solve the Elevation Equation
Using Cesium.Math.toRadians, the function converts latitude, declination, and hour angle to radians before computing the sine of elevation.
5. Clamp and Convert to Degrees
The result is clamped to [-1, 1] to prevent floating-point drift before applying Math.asin, with final conversion via Cesium.Math.toDegrees.
Working Code Example
The following implementation from src/hud.js calculates sun elevation for any latitude and longitude:
// Import Cesium if not already in scope
import * as Cesium from 'cesium';
// Example: compute sun elevation for New York City (40.7128 N, -74.0060 W)
function sunElevationNYC() {
const lat = 40.7128;
const lon = -74.0060;
const elevationDeg = _estimateSunElevation(lat, lon);
console.log(`Sun elevation in NYC: ${elevationDeg.toFixed(1)}°`);
}
// The core routine (excerpted from src/hud.js)
function _estimateSunElevation(lat, lon) {
const now = new Date();
const hours = now.getUTCHours() + now.getUTCMinutes() / 60 + lon / 15;
const hourAngle = (hours - 12) * 15;
const declination = 23.45 *
Math.sin(Cesium.Math.toRadians(
(360 / 365) *
(now.getUTCDate() + 30 * now.getUTCMonth() - 81)
));
const latRad = Cesium.Math.toRadians(lat);
const decRad = Cesium.Math.toRadians(declination);
const haRad = Cesium.Math.toRadians(hourAngle);
const sinEl = Math.sin(latRad) * Math.sin(decRad) +
Math.cos(latRad) * Math.cos(decRad) * Math.cos(haRad);
// Clamp to avoid NaN from rounding errors
const clamped = Math.max(-1, Math.min(1, sinEl));
return Cesium.Math.toDegrees(Math.asin(clamped));
}
// Run the example
sunElevationNYC();
Alternative: Using Cesium's Built-in Sun Position
For applications requiring higher astronomical precision, Cesium provides native solar position calculations. This approach uses Cesium.Sun.getPositionInWorldSpace to determine the sun's location in world coordinates, then calculates elevation from the direction vector:
function sunElevationCesium(viewer, lat, lon) {
const now = Cesium.JulianDate.now();
const sunPos = Cesium.Sun.getPositionInWorldSpace(viewer.scene, now);
const observer = Cesium.Cartesian3.fromDegrees(lon, lat);
const direction = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.subtract(sunPos, observer, new Cesium.Cartesian3()),
new Cesium.Cartesian3()
);
// Elevation = arcsin(z component) because Cesium's world frame Z points up
const elevationRad = Math.asin(direction.z);
return Cesium.Math.toDegrees(elevationRad);
}
Comparison of approaches:
- Astronomical model (
src/hud.js): Zero dependencies, extremely fast, sufficient for UI-level visual cues and HUD displays - Native Cesium.Sun: Higher accuracy using planetary ephemeris data, ideal for scientific visualization but requires access to the Cesium viewer instance
Related Files in God's Eye View
The repository organizes solar calculations across several modules:
src/hud.js: Contains the_estimateSunElevationfunction powering the HUD's sun-elevation readoutsrc/celestialRing.js: Handles visual sun/moon markers using Cesium's planetary position utilities for accurate screen placementsrc/cockpitCloudEffects.js: Derives thesunDirectionvector for lighting cloud shaders based on solar position
Summary
- Calculate sun elevation in CesiumJS using the classical formula
sin(el) = sin(φ)sin(δ) + cos(φ)cos(δ)cos(H)implemented insrc/hud.js - Compute solar declination with a sinusoidal approximation using day-of-year calculations and
Cesium.Math.toRadians - Prevent floating-point errors by clamping the sine of elevation to
[-1, 1]before callingMath.asin - Convert results to degrees using
Cesium.Math.toDegreesto obtain signed elevation values (negative indicates sun below horizon) - Choose between the lightweight astronomical model for HUD elements or
Cesium.Sun.getPositionInWorldSpacefor research-grade accuracy
Frequently Asked Questions
What file contains the sun elevation calculation in God's Eye View?
The primary implementation lives in src/hud.js within the _estimateSunElevation function. This module computes the solar angle every frame to update the cockpit HUD's "SUN" readout display.
Why clamp the sine of elevation to [-1, 1]?
Floating-point arithmetic in JavaScript can produce values slightly outside the valid domain of [-1, 1] due to rounding errors in trigonometric calculations. Clamping prevents Math.asin from returning NaN and ensures stable elevation readings near solar noon or horizon transitions.
How accurate is the declination approximation?
The sinusoidal model approximates Earth's 23.45° axial tilt with a maximum error of approximately ±0.5 degrees compared to precise astronomical algorithms. This accuracy proves sufficient for visualization purposes in CesiumJS applications while maintaining calculation speeds suitable for real-time rendering.
Can I use Cesium's built-in Sun class instead of the astronomical formula?
Yes. The Cesium.Sun class provides getPositionInWorldSpace for high-precision solar positioning based on planetary ephemeris data. This approach requires an active Cesium viewer instance and incurs higher computational cost than the src/hud.js implementation, but delivers research-grade accuracy for scientific applications.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →