Make PlaneObject a class.

Rearrange internal storage of positions.
Maintain sitedist within PlaneObject, not externally.
Clean up speed/dist/etc formatting.
Show both metric & imperial values in the plane detail infobox.
This commit is contained in:
Oliver Jowett 2015-01-07 17:18:33 +00:00
parent 58e5485c2a
commit 29509d9633
3 changed files with 419 additions and 413 deletions

View file

@ -117,7 +117,7 @@
</tr> </tr>
<tr class="infoblock_body"> <tr class="infoblock_body">
<td colspan="2">Lat/Long: <span id="selected_position">n/a</span></td> <td colspan="2">Position: <span id="selected_position">n/a</span></td>
</tr> </tr>
<tr class="infoblock_body"> <tr class="infoblock_body">

View file

@ -28,56 +28,54 @@ var PlaneSvg = "M 0,0 " +
"-2.858644 -0.145909,-5.208974 -0.209316,-5.222958 -0.06341,-0.01399 -0.974464," + "-2.858644 -0.145909,-5.208974 -0.209316,-5.222958 -0.06341,-0.01399 -0.974464," +
"-0.0493 -2.024551,-0.07845 L 23.247235,38.61921 18.831373,39.8906 C 4.9432155," + "-0.0493 -2.024551,-0.07845 L 23.247235,38.61921 18.831373,39.8906 C 4.9432155," +
"43.88916 4.2929558,44.057819 3.4954426,43.86823 2.7487826,43.690732 2.2007966," + "43.88916 4.2929558,44.057819 3.4954426,43.86823 2.7487826,43.690732 2.2007966," +
"42.916622 1.9565564,41.694305 z" "42.916622 1.9565564,41.694305 z";
var planeObject = {
// Basic location information
altitude : null,
speed : null,
track : null,
latitude : null,
longitude : null,
function PlaneObject(icao) {
// Info about the plane // Info about the plane
flight : null, this.icao = icao;
squawk : null, this.flight = null;
icao : null, this.squawk = null;
is_selected : false, this.selected = false;
// Basic location information
this.altitude = null;
this.speed = null;
this.track = null;
this.position = null;
this.sitedist = null;
// Data packet numbers // Data packet numbers
messages : null, this.messages = null;
// Track history as a series of line segments // Track history as a series of line segments
track_linesegs : [], this.track_linesegs = [];
this.history_size = 0;
// When was this last updated (receiver timestamp) // When was this last updated (receiver timestamp)
last_message_time : null, this.last_message_time = null;
last_position_time : null, this.last_position_time = null;
// When was this last updated (seconds before last update) // When was this last updated (seconds before last update)
seen : null, this.seen = null;
seen_pos : null, this.seen_pos = null;
history_size : 0, // Display info
visible : true, this.visible = true;
this.marker = null;
// GMap Details this.icon = { strokeWeight: 1,
marker : null,
icon : {
strokeWeight: 1,
path: PlaneSvg, path: PlaneSvg,
scale: 0.4, scale: 0.4,
fillColor: MarkerColor, fillColor: MarkerColor,
fillOpacity: 0.9, fillOpacity: 0.9,
anchor: new google.maps.Point(32, 32), // Set anchor to middle of plane. anchor: new google.maps.Point(32, 32), // Set anchor to middle of plane.
rotation: 0 rotation: 0 };
}, }
// Appends data to the running track so we can get a visual tail on the plane // Appends data to the running track so we can get a visual tail on the plane
// Only useful for a long running browser session. // Only useful for a long running browser session.
updateTrack : function() { PlaneObject.prototype.updateTrack = function() {
var here = new google.maps.LatLng(this.latitude, this.longitude); var here = this.position;
if (this.track_linesegs.length == 0) { if (this.track_linesegs.length == 0) {
// Brand new track // Brand new track
//console.log(this.icao + " new track"); //console.log(this.icao + " new track");
@ -169,10 +167,10 @@ var planeObject = {
} }
lastseg.head_update = this.last_position_time; lastseg.head_update = this.last_position_time;
return true; return true;
}, };
// This is to remove the line from the screen if we deselect the plane // This is to remove the line from the screen if we deselect the plane
clearLines : function() { PlaneObject.prototype.clearLines = function() {
for (var i = 0; i < this.track_linesegs.length; ++i) { for (var i = 0; i < this.track_linesegs.length; ++i) {
var seg = this.track_linesegs[i]; var seg = this.track_linesegs[i];
if (seg.line !== null) { if (seg.line !== null) {
@ -180,9 +178,9 @@ var planeObject = {
seg.line = null; seg.line = null;
} }
} }
}, };
updateIcon : function() { PlaneObject.prototype.updateIcon = function() {
var col = MarkerColor; var col = MarkerColor;
// If this marker is selected we should make it lighter than the rest. // If this marker is selected we should make it lighter than the rest.
@ -211,15 +209,10 @@ var planeObject = {
this.marker.setIcon(this.icon); this.marker.setIcon(this.icon);
return true; return true;
}, };
// TODO: Trigger actions of a selecting a plane
selectPlane : function(){
selectPlaneByHex(this.icao);
},
// Update our data // Update our data
updateData : function(receiver_timestamp, data){ PlaneObject.prototype.updateData = function(receiver_timestamp, data) {
// Update all of our data // Update all of our data
this.icao = data.hex; this.icao = data.hex;
this.messages = data.messages; this.messages = data.messages;
@ -232,17 +225,20 @@ var planeObject = {
if (typeof data.track !== "undefined") if (typeof data.track !== "undefined")
this.track = data.track; this.track = data.track;
if (typeof data.lat !== "undefined") { if (typeof data.lat !== "undefined") {
this.latitude = data.lat; this.position = new google.maps.LatLng(data.lat, data.lon);
this.longitude = data.lon;
this.last_position_time = receiver_timestamp - data.seen_pos; this.last_position_time = receiver_timestamp - data.seen_pos;
if (SitePosition !== null) {
this.sitedist = google.maps.geometry.spherical.computeDistanceBetween (SitePosition, this.position);
}
} }
if (typeof data.flight !== "undefined") if (typeof data.flight !== "undefined")
this.flight = data.flight; this.flight = data.flight;
if (typeof data.squawk !== "undefined") if (typeof data.squawk !== "undefined")
this.squawk = data.squawk; this.squawk = data.squawk;
}, };
updateTick : function(receiver_timestamp) { PlaneObject.prototype.updateTick = function(receiver_timestamp) {
// recompute seen and seen_pos // recompute seen and seen_pos
this.seen = receiver_timestamp - this.last_message_time; this.seen = receiver_timestamp - this.last_message_time;
this.seen_pos = (this.last_position_time === null ? null : receiver_timestamp - this.last_position_time); this.seen_pos = (this.last_position_time === null ? null : receiver_timestamp - this.last_position_time);
@ -258,7 +254,7 @@ var planeObject = {
} }
} else { } else {
this.visible = true; this.visible = true;
if (this.latitude !== null) { if (this.position !== null) {
if (this.updateTrack()) { if (this.updateTrack()) {
this.updateLines(); this.updateLines();
this.updateMarker(true); this.updateMarker(true);
@ -267,17 +263,18 @@ var planeObject = {
} }
} }
} }
}, };
clearMarker: function() { PlaneObject.prototype.clearMarker = function() {
if (this.marker) { if (this.marker) {
this.marker.setMap(null); this.marker.setMap(null);
google.maps.event.clearListeners(this.marker, 'click');
this.marker = null; this.marker = null;
} }
}, };
// Update our marker on the map // Update our marker on the map
updateMarker: function(moved) { PlaneObject.prototype.updateMarker = function(moved) {
if (!this.visible) { if (!this.visible) {
this.clearMarker(); this.clearMarker();
return; return;
@ -285,12 +282,12 @@ var planeObject = {
if (this.marker) { if (this.marker) {
if (moved) if (moved)
this.marker.setPosition(new google.maps.LatLng(this.latitude, this.longitude)); this.marker.setPosition(this.position);
this.updateIcon(); this.updateIcon();
} else { } else {
this.updateIcon(); this.updateIcon();
this.marker = new google.maps.Marker({ this.marker = new google.maps.Marker({
position: new google.maps.LatLng(this.latitude, this.longitude), position: this.position,
map: GoogleMap, map: GoogleMap,
icon: this.icon, icon: this.icon,
visible: true visible: true
@ -300,7 +297,7 @@ var planeObject = {
this.marker.icao = this.icao; this.marker.icao = this.icao;
// Trap clicks for this marker. // Trap clicks for this marker.
google.maps.event.addListener(this.marker, 'click', this.selectPlane); google.maps.event.addListener(this.marker, 'click', selectPlaneByHex.bind(undefined,this.icao));
} }
// Setting the marker title // Setting the marker title
@ -309,10 +306,10 @@ var planeObject = {
} else { } else {
this.marker.setTitle(this.flight+' ('+this.icao+')'); this.marker.setTitle(this.flight+' ('+this.icao+')');
} }
}, };
// Update our planes tail line, // Update our planes tail line,
updateLines: function() { PlaneObject.prototype.updateLines = function() {
if (!this.is_selected) if (!this.is_selected)
return; return;
@ -351,10 +348,9 @@ var planeObject = {
} }
} }
} }
}, };
destroy : function() { PlaneObject.prototype.destroy = function() {
this.clearLines(); this.clearLines();
this.clearMarker(); this.clearMarker();
}
}; };

View file

@ -39,12 +39,10 @@ function fetchData() {
if (Planes[hex]) { if (Planes[hex]) {
plane = Planes[hex]; plane = Planes[hex];
} else { } else {
plane = jQuery.extend(true, {}, planeObject); plane = new PlaneObject(hex);
plane.tr = PlaneRowTemplate.cloneNode(true); plane.tr = PlaneRowTemplate.cloneNode(true);
plane.tr.cells[0].textContent = hex; // this won't change plane.tr.cells[0].textContent = hex; // this won't change
plane.tr.addEventListener('click', $.proxy(plane.selectPlane, plane)); plane.tr.addEventListener('click', selectPlaneByHex.bind(undefined,hex));
plane.sitedist = null;
Planes[hex] = plane; Planes[hex] = plane;
PlanesOrdered.push(plane); PlanesOrdered.push(plane);
@ -282,6 +280,98 @@ function reaper() {
refreshSelected(); refreshSelected();
} }
//
// formatting helpers
//
var TrackDirections = ["North","Northeast","East","Southeast","South","Southwest","West","Northwest"];
// track in degrees (0..359)
function format_track_brief(track) {
return Math.round(track);
}
// track in degrees (0..359)
function format_track_long(track) {
var trackDir = Math.floor((360 + track % 360 + 22.5) / 45) % 8;
return Math.round(track) + "\u00b0 (" + TrackDirections[trackDir] + ")";
}
// alt in ft
function format_altitude_brief(alt) {
if (alt === null)
return "";
if (alt === "ground")
return "ground";
if (Metric)
return Math.round(alt / 3.2828);
else
return Math.round(alt);
}
// alt in ft
function format_altitude_long(alt) {
if (alt === null)
return "n/a";
if (alt === "ground")
return "on ground";
if (Metric)
return Math.round(alt / 3.2828) + " m / " + Math.round(alt) + " ft";
else
return Math.round(alt) + " ft / " + Math.round(alt / 3.2828) + " m";
}
// speed in kts
function format_speed_brief(speed) {
if (speed === null)
return "";
if (Metric)
return Math.round(speed * 1.852);
else
return Math.round(speed);
}
// speed in kts
function format_speed_long(speed) {
if (speed === null)
return "n/a";
if (Metric)
return Math.round(speed * 1.852) + " km/h / " + Math.round(speed) + " kt";
else
return Math.round(speed) + " kt / " + Math.round(speed * 1.852) + " km/h";
}
// dist in metres
function format_distance_brief(dist) {
if (dist === null)
return "";
if (Metric)
return (dist/1000).toFixed(1);
else
return (dist/1852).toFixed(1);
}
// dist in metres
function format_distance_long(dist) {
if (dist === null)
return "n/a";
if (Metric)
return (dist/1000).toFixed(1) + " km / " + (dist/1852).toFixed(1) + " NM";
else
return (dist/1852).toFixed(1) + " NM / " + (dist/1000).toFixed(1) + " km";
}
// p as a LatLng
function format_latlng(p) {
return p.lat().toFixed(5) + "\u00b0, " + p.lng().toFixed(5) + "\u00b0";
}
// Refresh the detail window about the plane // Refresh the detail window about the plane
function refreshSelected() { function refreshSelected() {
var selected = false; var selected = false;
@ -321,14 +411,7 @@ function refreshSelected() {
emerg.className = 'hidden'; emerg.className = 'hidden';
} }
if (selected.altitude === null) $("#selected_altitude").text(format_altitude_long(selected.altitude));
$("#selected_altitude").text("n/a");
else if (selected.altitude === "ground")
$("#selected_altitude").text("on ground");
else if (Metric)
$("#selected_altitude").text(Math.round(selected.altitude / 3.2828) + ' m');
else
$("#selected_altitude").text(Math.round(selected.altitude) + ' ft');
if (selected.squawk === null || selected.squawk === '0000') { if (selected.squawk === null || selected.squawk === '0000') {
$('#selected_squawk').text('n/a'); $('#selected_squawk').text('n/a');
@ -336,21 +419,9 @@ function refreshSelected() {
$('#selected_squawk').text(selected.squawk); $('#selected_squawk').text(selected.squawk);
} }
if (selected.speed === null) { $('#selected_speed').text(format_speed_long(selected.speed));
$('#selected_speed').text('n/a');
} else if (Metric) {
$('#selected_speed').text(Math.round(selected.speed * 1.852) + ' km/h');
} else {
$('#selected_speed').text(Math.round(selected.speed) + ' kt');
}
$('#selected_icao').text(selected.icao); $('#selected_icao').text(selected.icao);
$('#selected_track').text(format_track_long(selected.track));
if (selected.track === null) {
$('#selected_track').text('n/a');
} else {
$('#selected_track').text(selected.track + '\u00b0' + ' (' + trackLongName(selected.track) + ')');
}
if (selected.seen <= 1) { if (selected.seen <= 1) {
$('#selected_seen').text('now'); $('#selected_seen').text('now');
@ -358,72 +429,20 @@ function refreshSelected() {
$('#selected_seen').text(selected.seen + 's ago'); $('#selected_seen').text(selected.seen + 's ago');
} }
if (selected.latitude === null) { if (selected.position === null) {
$('#selected_position').text('n/a'); $('#selected_position').text('n/a');
} else { } else {
if (selected.seen_pos > 1) { if (selected.seen_pos > 1) {
$('#selected_position').text(selected.latitude + ', ' + selected.longitude + " (" + selected.seen_pos + "s ago)"); $('#selected_position').text(format_latlng(selected.position) + " (" + selected.seen_pos + "s ago)");
} else { } else {
$('#selected_position').text(selected.latitude + ', ' + selected.longitude); $('#selected_position').text(format_latlng(selected.position));
} }
} }
if (selected.sitedist !== null) { $('#selected_sitedist').text(format_distance_long(selected.sitedist));
var dist = selected.sitedist;
if (Metric) {
dist /= 1000;
} else {
dist /= 1852;
}
dist = (Math.round((dist)*10)/10).toFixed(1);
$('#selected_sitedist').text(dist + (Metric ? ' km' : ' NM'));
} else {
$('#selected_sitedist').text("n/a");
}
}
function trackShortName(track) {
var trackIndex = Math.floor((360 + track % 360 + 22.5) / 45) % 8;
return ["N","NE","E","SE","S","SW","W","NW"][trackIndex];
}
function trackLongName(track) {
var trackIndex = Math.floor((360 + track % 360 + 22.5) / 45) % 8;
return ["North","Northeast","East","Southeast","South","Southwest","West","Northwest"][trackIndex];
}
// Refeshes the larger table of all the planes
function format_altitude(alt) {
if (alt === null)
return "";
else if (alt === "ground")
return "ground";
else if (Metric)
return Math.round(alt / 3.2828);
else
return Math.round(alt);
}
function format_speed(speed) {
if (speed === null)
return "";
else if (Metric)
return Math.round(speed * 1.852);
else
return Math.round(speed);
}
function format_distance(dist) {
if (Metric) {
return (Math.round(dist/100) / 10).toFixed(1);
} else {
return (Math.round(dist/185.2) / 10).toFixed(1);
}
} }
// Refreshes the larger table of all the planes
function refreshTableInfo() { function refreshTableInfo() {
var show_squawk_warning = false; var show_squawk_warning = false;
@ -440,7 +459,7 @@ function refreshTableInfo() {
TrackedAircraft++; TrackedAircraft++;
var classes = "plane_table_row"; var classes = "plane_table_row";
if (tableplane.latitude !== null) if (tableplane.position !== null)
classes += " vPosition"; classes += " vPosition";
if (tableplane.icao == SelectedPlane) if (tableplane.icao == SelectedPlane)
classes += " selected"; classes += " selected";
@ -453,23 +472,14 @@ function refreshTableInfo() {
// ICAO doesn't change // ICAO doesn't change
tableplane.tr.cells[1].textContent = (tableplane.flight !== null ? tableplane.flight : ""); tableplane.tr.cells[1].textContent = (tableplane.flight !== null ? tableplane.flight : "");
tableplane.tr.cells[2].textContent = (tableplane.squawk !== null ? tableplane.squawk : ""); tableplane.tr.cells[2].textContent = (tableplane.squawk !== null ? tableplane.squawk : "");
tableplane.tr.cells[3].textContent = format_altitude(tableplane.altitude); tableplane.tr.cells[3].textContent = format_altitude_brief(tableplane.altitude);
tableplane.tr.cells[4].textContent = format_speed(tableplane.speed); tableplane.tr.cells[4].textContent = format_speed_brief(tableplane.speed);
if (tableplane.latitude !== null) if (tableplane.position !== null)
++TrackedAircraftPositions; ++TrackedAircraftPositions;
// Add distance column to table if site coordinates are provided tableplane.tr.cells[5].textContent = format_distance_brief(tableplane.sitedist);
if (SitePosition !== null && tableplane.latitude !== null) { tableplane.tr.cells[6].textContent = format_track_brief(tableplane.track);
var planeLatLon = new google.maps.LatLng(tableplane.latitude, tableplane.longitude);
var dist = google.maps.geometry.spherical.computeDistanceBetween (SitePosition, planeLatLon);
tableplane.tr.cells[5].textContent = format_distance(dist);
tableplane.sitedist = dist;
} else {
tableplane.tr.cells[5].textContent = "";
}
tableplane.tr.cells[6].textContent = (tableplane.track !== null ? tableplane.track : "");
tableplane.tr.cells[7].textContent = tableplane.messages; tableplane.tr.cells[7].textContent = tableplane.messages;
tableplane.tr.cells[8].textContent = tableplane.seen; tableplane.tr.cells[8].textContent = tableplane.seen;