How to Display MGRS Grid Reference on a CesiumJS Globe

The Gods-Eye-View application displays live Military Grid Reference System coordinates by converting the Cesium camera's Cartographic position using the mgrs npm package and rendering the formatted result to HUD DOM elements every 250 milliseconds.

To display MGRS grid reference on a CesiumJS globe, you must convert the camera's geographic coordinates into the Military Grid Reference System format and inject the result into your user interface. The open-source bilawalsidhu/gods-eye-view repository demonstrates this implementation in src/hud.js, combining the mgrs library with Cesium's Camera API to provide real-time coordinate readouts.

Implementation Overview

The implementation follows a six-step pipeline: import the conversion utility, extract latitude and longitude from the Cesium camera, transform the coordinates to an MGRS string, format the string for human readability, update the DOM elements, and refresh the display at a regular interval.

Step-by-Step Implementation

1. Import the MGRS Conversion Utility

The project relies on the lightweight mgrs npm package to handle coordinate conversion. In src/hud.js (lines 16–18), the forward function is imported and aliased to toMGRS for clarity:

import { forward as toMGRS } from 'mgrs';

This function accepts a longitude-latitude array and a precision integer, returning a raw MGRS string.

2. Capture the Camera Position from Cesium

Each update tick retrieves the camera's current position in Cartographic coordinates (radians) and converts them to degrees. According to the source in src/hud.js:

const camera = this.viewer.camera;
const cartographic = camera.positionCartographic;
const lonDeg = Cesium.Math.toDegrees(cartographic.longitude);
const latDeg = Cesium.Math.toDegrees(cartographic.latitude);

These degree values serve as the input for the MGRS conversion.

3. Convert Coordinates to MGRS String

With geographic coordinates in hand, call toMGRS with a precision argument of 4 to achieve 10-meter accuracy (4 digits per axis). This logic appears at lines 303–305 in src/hud.js:

const mgrsStr = toMGRS([lonDeg, latDeg], 4);

The resulting string follows the pattern 18SUJ23370716 (zone, square identifier, easting, and northing concatenated).

4. Format the MGRS String for Readability

Raw MGRS strings are difficult to read. The HUD implements a _formatMGRS helper (lines 403–413 in src/hud.js) that uses a regular expression to insert spaces between components:

_formatMGRS(mgrs) {
  const match = mgrs.match(/^(\d{1,2}[A-Z])\s*([A-Z]{2})\s*(\d+)$/);
  if (!match) return mgrs;
  const [, zone, square, coords] = match;
  const half = coords.length / 2;
  const easting = coords.slice(0, half);
  const northing = coords.slice(half);
  return `${zone} ${square} ${easting} ${northing}`;
}

This transforms 18SUJ23370716 into the readable format 18S UJ 2337 0716.

5. Inject the Result into the UI

The formatted string updates two HUD elements. Lines 308–312 and 318–321 in src/hud.js show the DOM manipulation:

const el = document.getElementById('hud-mgrs');
if (el) el.textContent = `MGRS: ${formatted}`;
// Bottom-line update
bottomEl.textContent = `MGRS: ${mgrsLabel}  LAT: ${latDMS}  LON: ${lonDMS}`;

If conversion fails, the display falls back to --- to indicate invalid coordinates.

6. Schedule Continuous Updates

To keep the readout synchronized with camera movement, the HUD uses a 250-millisecond interval (4 Hz). Lines 28–33 in src/hud.js establish this timer:

this._updateInterval = setInterval(() => {
  if (!this._visible) return;
  this._updateCameraData();
}, 250);

Each tick recomputes the MGRS grid reference based on the current camera position.

Standalone Integration Example

For projects outside the Gods-Eye-View codebase, you can integrate MGRS display functionality using this self-contained module:

import { forward as toMGRS } from 'mgrs';
import * as Cesium from 'cesium';

/**
 * Returns a formatted MGRS string for the current Cesium camera position.
 * @param {Cesium.Viewer} viewer
 * @returns {string} e.g. "18S UJ 2337 0716"
 */
function getMGRS(viewer) {
  const cam = viewer.camera;
  const cart = cam.positionCartographic;
  const lon = Cesium.Math.toDegrees(cart.longitude);
  const lat = Cesium.Math.toDegrees(cart.latitude);

  // 10 m precision → 4 digits per axis
  const raw = toMGRS([lon, lat], 4);
  return formatMGRS(raw);
}

/**
 * Human-readable formatting (same logic as HUD._formatMGRS).
 */
function formatMGRS(mgrs) {
  const m = mgrs.match(/^(\d{1,2}[A-Z])\s*([A-Z]{2})\s*(\d+)$/);
  if (!m) return mgrs;
  const [, zone, sq, num] = m;
  const half = num.length / 2;
  return `${zone} ${sq} ${num.slice(0, half)} ${num.slice(half)}`;
}

// Update an HTML element every 250 ms
function updateMGRS(viewer) {
  const el = document.getElementById('my-mgrs');
  if (!el) return;
  try {
    el.textContent = `MGRS: ${getMGRS(viewer)}`;
  } catch (e) {
    el.textContent = 'MGRS: ---';
  }
}

setInterval(() => updateMGRS(myCesiumViewer), 250);

Key Source Files

The MGRS display functionality is distributed across the following files in the bilawalsidhu/gods-eye-view repository:

  • src/hud.js – Contains the main HUD implementation. This file imports the mgrs package, computes coordinates from the Cesium camera, formats the output via _formatMGRS, and writes to the DOM elements #hud-mgrs and #hud-bottom-line.

  • package.json – Declares the mgrs npm package as a project dependency, required for coordinate conversion logic.

  • src/main.js – Instantiates the Cesium Viewer that the HUD receives as a constructor argument, establishing the 3D globe context.

Summary

  • Import the mgrs library (aliased as toMGRS) to handle coordinate conversion in src/hud.js.
  • Extract camera coordinates using viewer.camera.positionCartographic and convert from radians to degrees with Cesium.Math.toDegrees.
  • Convert to MGRS by passing [longitude, latitude] and precision 4 to the toMGRS function for 10-meter accuracy.
  • Format the output using the regex-based _formatMGRS helper to split the zone, square, easting, and northing into readable components.
  • Update DOM elements #hud-mgrs and #hud-bottom-line with the formatted string, or display --- on conversion failure.
  • Refresh at 4 Hz (250 ms) to maintain real-time synchronization with camera movement.

Frequently Asked Questions

How do I install the MGRS library for a CesiumJS project?

Install the mgrs package via npm to enable coordinate conversion in your application:

npm install mgrs

Then import the forward function in your HUD or UI module, aliasing it to toMGRS for readability as shown in src/hud.js lines 16–18.

What precision level should I use for MGRS coordinates in CesiumJS?

Use precision level 4 to achieve 10-meter accuracy, which splits the coordinate into four-digit easting and northing values. Lower numbers decrease precision (e.g., 3 for 100-meter accuracy), while higher numbers increase it. The Gods-Eye-View implementation selects 4 to balance precision with screen real estate.

Why does my MGRS display show "---" instead of coordinates?

The HUD displays --- when the MGRS conversion fails or returns an unparseable string. This typically occurs when the camera is positioned outside valid MGRS zones (near the poles) or when coordinates are undefined. The code handles this gracefully by catching errors and updating the DOM element with the placeholder text rather than crashing the application.

Can I change the update frequency for the MGRS readout?

Yes. The default implementation in src/hud.js uses a 250-millisecond interval (4 Hz) defined at lines 28–33. You can adjust this value to increase or decrease the refresh rate, though frequencies below 100 milliseconds may impact performance, while intervals above 1000 milliseconds will cause noticeable lag between camera movement and coordinate updates.

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 →