In many defense and simulation applications, it’s useful to display the field of view (FOV) of a radar system mounted on an aircraft or ship. Using CesiumJS, we can dynamically render a radar sector that updates with the platform’s position and heading.
In this post, we’ll walk through how to:
- Display an ownship entity (the platform carrying the radar).
- Render a radar scanning sector that rotates as the ownship heading changes.
1. Adding the Ownship Entity
We start by creating (or updating) our ownship marker with a billboard and label.
function updateOwnship(data) {
const id = "Ownship";
const position = Cesium.Cartesian3.fromDegrees(data.lon, data.lat, data.alt || 1000);
const heading = Cesium.Math.toRadians(data.heading || 0);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
new Cesium.HeadingPitchRoll(heading, 0, 0)
);
let entity = viewer.entities.getById(id);
if (!entity) {
entity = viewer.entities.add({
id: id,
position: position,
orientation: orientation,
billboard: {
image: "./images/ownship.png",
width: 32,
height: 32,
rotation: -heading,
alignedAxis: Cesium.Cartesian3.ZERO
},
label: {
text: "Ownship",
font: "bold 14px sans-serif",
fillColor: Cesium.Color.YELLOW,
outlineColor: Cesium.Color.BLACK,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
pixelOffset: new Cesium.Cartesian2(0, -30),
showBackground: true
}
});
} else {
entity.position = position;
entity.orientation = orientation;
entity.billboard.rotation = -heading;
}
drawRadarSector(data); // update radar FOV
}
2. Drawing the Radar Sector
We generate a polygon shaped like a sector (fan arc) originating from the ownship’s position. This represents the radar’s scan coverage.
function drawRadarSector(data) {
const id = "RadarSector";
const { lat, lon, alt = 1000, heading = 0 } = data;
const range = 500000; // 500 km range
const sectorStart = -45; // -45° left of heading
const sectorEnd = 45; // +45° right of heading
const steps = 30;
const positions = [Cesium.Cartesian3.fromDegrees(lon, lat, alt)];
for (let i = 0; i <= steps; i++) {
const azimuth = sectorStart + (sectorEnd - sectorStart) * (i / steps);
const angle = Cesium.Math.toRadians(heading + azimuth);
const dx = range * Math.sin(angle);
const dy = range * Math.cos(angle);
const pLon = lon + dx / (111000 * Math.cos(Cesium.Math.toRadians(lat)));
const pLat = lat + dy / 111000;
positions.push(Cesium.Cartesian3.fromDegrees(pLon, pLat, alt));
}
// Remove old sector
const existing = viewer.entities.getById(id);
if (existing) viewer.entities.remove(existing);
// Add new sector
viewer.entities.add({
id: id,
polygon: {
hierarchy: positions,
material: Cesium.Color.CYAN.withAlpha(0.3),
outline: true,
outlineColor: Cesium.Color.YELLOW,
perPositionHeight: true
}
});
}
3. Updating in Real-Time
If the ownship receives live updates (from simulation or real sensors), simply call:
updateOwnship({
id: "AC1",
lat: 12.97,
lon: 77.59,
alt: 8000,
heading: 60
});
The radar sector will always be re-drawn based on the new position and heading.
Final Output
- The ownship is represented by a billboard and label.
- A cyan radar sector appears ahead of the ownship, dynamically aligned with its heading.
- Each update redraws the sector, making it suitable for real-time simulations.
👉 With this approach, you can easily extend the visualization by:
- Adding multiple radars with different IDs.
- Varying range and FOV per radar.
- Coloring by detection probability or threat level.
At Manya Technologies, we specialize in building custom GIS solutions, real-time visualization tools, and simulation applications using CesiumJS, QGIS, and PostGIS. If your organization is looking to integrate raster, vector, or 3D data into an interactive web-based platform, we can help.
📩 Contact us today at Manya Technologies to discuss your project requirements.

