From c6aab821a39e280578cfef9f1d044d135277b133 Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 1 Sep 2025 21:08:43 +0200 Subject: [PATCH] feat: Enhance flight trails with historical altitude data and fix label display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Extend PositionPoint struct to include altitude field in position history - Update position history population to store altitude with each position - Fix 3D aircraft labels to show GroundSpeed instead of undefined Speed field - Enable true 3D flight trails with proper altitude visualization - Improve trail accuracy by using historical altitude data per position Resolves trails showing flat paths and labels showing N/A for speed. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- assets/static/js/app.js | 18 +++++++++--------- internal/merger/merger.go | 10 ++++++---- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/assets/static/js/app.js b/assets/static/js/app.js index 246d905..8134dd2 100644 --- a/assets/static/js/app.js +++ b/assets/static/js/app.js @@ -927,7 +927,7 @@ class SkyView { update3DAircraftLabelContent(label, aircraft) { const callsign = aircraft.Callsign || aircraft.Icao || 'N/A'; const altitude = aircraft.Altitude ? `${Math.round(aircraft.Altitude)}ft` : 'N/A'; - const speed = aircraft.Speed ? `${Math.round(aircraft.Speed)}kts` : 'N/A'; + const speed = aircraft.GroundSpeed ? `${Math.round(aircraft.GroundSpeed)}kts` : 'N/A'; label.innerHTML = `
${callsign}
@@ -1084,10 +1084,10 @@ class SkyView { // Convert position history to 3D world coordinates aircraft.position_history.forEach(pos => { - if (pos.latitude && pos.longitude) { - const x = (pos.longitude - originLon) * 111320 * Math.cos(pos.latitude * Math.PI / 180) / 1000; - const z = -(pos.latitude - originLat) * 111320 / 1000; - const y = (pos.altitude || 0) / 1000; // Convert feet to km + if (pos.lat && pos.lon) { + const x = (pos.lon - originLon) * 111320 * Math.cos(pos.lat * Math.PI / 180) / 1000; + const z = -(pos.lat - originLat) * 111320 / 1000; + const y = (pos.altitude || 0) / 1000; // Use historical altitude from position history points.push(new THREE.Vector3(x, y, z)); } }); @@ -1136,10 +1136,10 @@ class SkyView { // Convert position history to 3D world coordinates aircraft.position_history.forEach(pos => { - if (pos.latitude && pos.longitude) { - const x = (pos.longitude - originLon) * 111320 * Math.cos(pos.latitude * Math.PI / 180) / 1000; - const z = -(pos.latitude - originLat) * 111320 / 1000; - const y = (pos.altitude || 0) / 1000; // Convert feet to km + if (pos.lat && pos.lon) { + const x = (pos.lon - originLon) * 111320 * Math.cos(pos.lat * Math.PI / 180) / 1000; + const z = -(pos.lat - originLat) * 111320 / 1000; + const y = (pos.altitude || 0) / 1000; // Use historical altitude from position history points.push(new THREE.Vector3(x, y, z)); } }); diff --git a/internal/merger/merger.go b/internal/merger/merger.go index 0d907ce..f2dfb07 100644 --- a/internal/merger/merger.go +++ b/internal/merger/merger.go @@ -227,10 +227,11 @@ type SourceData struct { // PositionPoint represents a timestamped position update in aircraft history. // Used to build position trails for visualization and track analysis. type PositionPoint struct { - Time time.Time `json:"time"` // Timestamp when position was received - Latitude float64 `json:"lat"` // Latitude in decimal degrees - Longitude float64 `json:"lon"` // Longitude in decimal degrees - Source string `json:"source"` // Source that provided this position + Time time.Time `json:"time"` // Timestamp when position was received + Latitude float64 `json:"lat"` // Latitude in decimal degrees + Longitude float64 `json:"lon"` // Longitude in decimal degrees + Altitude int `json:"altitude"` // Altitude in feet (0 if unknown) + Source string `json:"source"` // Source that provided this position } // SignalPoint represents a timestamped signal strength measurement. @@ -655,6 +656,7 @@ func (m *Merger) updateHistories(state *AircraftState, aircraft *modes.Aircraft, Time: timestamp, Latitude: aircraft.Latitude, Longitude: aircraft.Longitude, + Altitude: aircraft.Altitude, // Include altitude in position history Source: sourceID, }) }