diff --git a/public_html/formatter.js b/public_html/formatter.js
index 3ae74205c..7d6cddb98 100644
--- a/public_html/formatter.js
+++ b/public_html/formatter.js
@@ -18,6 +18,48 @@ var UnitLabels = {
// formatting helpers
+
+////
+function format_elevation(siteAltFeet, siteDistMetres, altitudeFeet) {
+
+ var ftHeight = 'ground' == altitudeFeet ? 0 : altitudeFeet;
+
+ if( ftHeight < 0 ) {
+
+ return 93; // it happens
+ }
+
+ if( null == siteDistMetres) {
+
+ return 92; // invalid angle
+ }
+
+ if( null == altitudeFeet ) {
+
+ return 91; // invalid angle
+ }
+
+ if( 0 == siteDistMetres ) { // craft overhead
+
+ return 90;
+ }
+
+ var ftDistance = siteDistMetres*3.28084;
+ var ftDiff = ftHeight - siteAltFeet;
+
+ // make approximation for 2 * Earth radius in ft
+
+ var radiansAngularDrop = ftDistance / 41784593;
+ var radians = ftDiff / ftDistance;
+ var elevAngleRadians = Math.atan( radians - radiansAngularDrop);
+ var elevAngleDegrees = 57.29577951308232 * elevAngleRadians;
+ var result = Math.round( 1000*elevAngleDegrees) / 1000;
+ var result3dp = Number.parseFloat(result).toFixed(3);
+ return result3dp;
+}
+////
+
+
function get_unit_label(quantity, systemOfMeasurement) {
var labels = UnitLabels[quantity];
if (labels !== undefined && labels[systemOfMeasurement] !== undefined) {
diff --git a/public_html/index.html b/public_html/index.html
index 422f0013a..d090e8f9c 100644
--- a/public_html/index.html
+++ b/public_html/index.html
@@ -99,13 +99,39 @@
-
-
-
+
+
+
+
+
+
+
+
@@ -157,6 +183,8 @@
Show Aircraft Labels
+
+
+
+
+
+
+
+
+
@@ -388,6 +429,9 @@
Airframes.org |
FlightAware |
Photos |
+
+ Elevation |
+
@@ -412,6 +456,9 @@
AIRFRAMES_MODE_S_LINK |
FLIGHTAWARE_MODE_S_LINK |
FLIGHTAWARE_PHOTO_LINK |
+
+ ELEVATION |
+
diff --git a/public_html/planeObject.js b/public_html/planeObject.js
index 5e0c5d64f..7f13c8ec9 100644
--- a/public_html/planeObject.js
+++ b/public_html/planeObject.js
@@ -2,6 +2,9 @@
function PlaneObject(icao) {
// Info about the plane
+
+ this.count = 0; ////
+
this.icao = icao;
this.icaorange = findICAORange(icao);
this.flight = null;
@@ -348,6 +351,25 @@ PlaneObject.prototype.getMarkerColor = function() {
if (this.squawk in SpecialSquawks)
return SpecialSquawks[this.squawk].markerColor;
+ ////
+ this.count ++;
+
+ if( this.elevation < SiteNegativeAngle ) {
+
+ for( let index=0; index < SpecialElevations.length; index++) {
+
+ if( this.elevation < SpecialElevations[index].exceptional ) {
+
+ if( 0 == parseInt(this.count)%2 ) {
+
+ return SpecialElevations[index].markerColor;
+ }
+ break;
+ }
+ }
+ }
+ ////
+
var h, s, l;
var colorArr = this.getAltitudeColor();
diff --git a/public_html/script.js b/public_html/script.js
index d9812dc8e..e958cc4cd 100644
--- a/public_html/script.js
+++ b/public_html/script.js
@@ -2,6 +2,16 @@
"use strict";
// Define our global variables
+
+var DefaultSiteElevationAsl =0; ////
+var DefaultSiteNegativeAngle= -0.5 ////
+var SiteElevationAsl //// will be set from LocalStorage
+var SiteNegativeAngle //// will be set from LocalStorage
+
+var SpecialElevations = [ { exceptional: -0.0, markerColor: 'rgb(255, 0, 0)'},
+ { exceptional: -1.0, markerColor: 'rgb(0, 255, 0)'},
+ { exceptional: -1.5, markerColor: 'rgb(0, 0, 255)'} ] ; ////
+
var OLMap = null;
var StaticFeatures = new ol.Collection();
var SiteCircleFeatures = new ol.Collection();
@@ -88,7 +98,7 @@ var checkbox_div_map = new Map ([
['#airframes_col_checkbox', '#airframes_mode_s_link'],
['#fa_modes_link_checkbox', '#flightaware_mode_s_link'],
['#fa_photo_link_checkbox', '#flightaware_photo_link'],
-
+ ['#elevation_col_checkbox', '#elevation'], ////
]);
var DefaultMinMaxFilters = {
@@ -469,6 +479,9 @@ function initialize() {
});
// Initialize settings from local storage
+ setElevation(); ////
+ setAngle();////
+
filterGroundVehicles(false);
filterBlockedMLAT(false);
toggleAltitudeChart(false);
@@ -856,6 +869,10 @@ function applyUrlQueryStrings() {
if (params.get('ringInterval')) {
setRingInterval(params.get('ringInterval'));
}
+
+ if (params.get('siteElevation')) {
+ setSiteElevation(params.get('siteElevation'));
+ }
}
// Make a LineString with 'points'-number points
@@ -1101,6 +1118,11 @@ function initialize_map() {
toggleLayer('#acpositions_checkbox', 'ac_positions');
});
+ ////
+ $('#elevation_asl_button').click(onSetElevationAsl);
+ $('#negative_angle_button').click(onSetNegativeAngle);
+ ////
+
// Add home marker if requested
if (SitePosition) {
var markerStyle = new ol.style.Style({
@@ -1432,6 +1454,9 @@ function refreshSelected() {
$('#selected_rssi').text(selected.rssi.toFixed(1) + ' dBFS');
$('#selected_message_count').text(selected.messages);
$('#selected_photo_link').html(getFlightAwarePhotoLink(selected.registration));
+
+ $('#selected_elevation').text(selected.elevation); ////
+
$('#selected_altitude_geom').text(format_altitude_long(selected.alt_geom, selected.geom_rate, DisplayUnits));
$('#selected_mag_heading').text(format_track_long(selected.mag_heading));
$('#selected_true_heading').text(format_track_long(selected.true_heading));
@@ -1717,25 +1742,41 @@ function refreshTableInfo() {
tableplane.tr.cells[2].className = "";
}
- tableplane.tr.cells[3].textContent = (tableplane.registration !== null ? tableplane.registration : "");
- tableplane.tr.cells[4].textContent = (tableplane.icaotype !== null ? tableplane.icaotype : "");
- tableplane.tr.cells[5].textContent = (tableplane.squawk !== null ? tableplane.squawk : "");
- tableplane.tr.cells[6].innerHTML = format_altitude_brief(tableplane.altitude, tableplane.vert_rate, DisplayUnits);
- tableplane.tr.cells[7].textContent = format_speed_brief(tableplane.gs, DisplayUnits);
- tableplane.tr.cells[8].textContent = format_vert_rate_brief(tableplane.vert_rate, DisplayUnits);
- tableplane.tr.cells[9].textContent = format_distance_brief(tableplane.sitedist, DisplayUnits);
- tableplane.tr.cells[10].textContent = format_track_brief(tableplane.track);
- tableplane.tr.cells[11].textContent = tableplane.messages;
- tableplane.tr.cells[12].textContent = tableplane.seen.toFixed(0);
- tableplane.tr.cells[13].textContent = (tableplane.rssi !== null ? tableplane.rssi : "");
- tableplane.tr.cells[14].textContent = (tableplane.position !== null ? tableplane.position[1].toFixed(4) : "");
- tableplane.tr.cells[15].textContent = (tableplane.position !== null ? tableplane.position[0].toFixed(4) : "");
- tableplane.tr.cells[16].textContent = format_data_source(tableplane.getDataSource());
- tableplane.tr.cells[17].innerHTML = getAirframesModeSLink(tableplane.icao);
- tableplane.tr.cells[18].innerHTML = getFlightAwareModeSLink(tableplane.icao, tableplane.flight);
- tableplane.tr.cells[19].innerHTML = getFlightAwarePhotoLink(tableplane.registration);
- tableplane.tr.className = classes;
- }
+ tableplane.tr.cells[3].textContent = (tableplane.registration !== null ? tableplane.registration : "");
+ tableplane.tr.cells[4].textContent = (tableplane.icaotype !== null ? tableplane.icaotype : "");
+ tableplane.tr.cells[5].textContent = (tableplane.squawk !== null ? tableplane.squawk : "");
+ tableplane.tr.cells[6].innerHTML = format_altitude_brief(tableplane.altitude, tableplane.vert_rate, DisplayUnits);
+ tableplane.tr.cells[7].textContent = format_speed_brief(tableplane.gs, DisplayUnits);
+ tableplane.tr.cells[8].textContent = format_vert_rate_brief(tableplane.vert_rate, DisplayUnits);
+ tableplane.tr.cells[9].textContent = format_distance_brief(tableplane.sitedist, DisplayUnits);
+ tableplane.tr.cells[10].textContent = format_track_brief(tableplane.track);
+ tableplane.tr.cells[11].textContent = tableplane.messages;
+ tableplane.tr.cells[12].textContent = tableplane.seen.toFixed(0);
+ tableplane.tr.cells[13].textContent = (tableplane.rssi !== null ? tableplane.rssi : "");
+ tableplane.tr.cells[14].textContent = (tableplane.position !== null ? tableplane.position[1].toFixed(4) : "");
+ tableplane.tr.cells[15].textContent = (tableplane.position !== null ? tableplane.position[0].toFixed(4) : "");
+ tableplane.tr.cells[16].textContent = format_data_source(tableplane.getDataSource());
+ tableplane.tr.cells[17].innerHTML = getAirframesModeSLink(tableplane.icao);
+ tableplane.tr.cells[18].innerHTML = getFlightAwareModeSLink(tableplane.icao, tableplane.flight);
+ tableplane.tr.cells[19].innerHTML = getFlightAwarePhotoLink(tableplane.registration);
+
+
+ ////
+ var elevationAngle = format_elevation(SiteElevationAsl, tableplane.sitedist, tableplane.altitude, tableplane.gs);
+ tableplane.elevation = elevationAngle;
+
+ if( elevationAngle > 90 ) {
+
+ tableplane.tr.cells[20].textContent = '';
+ }
+ else {
+
+ tableplane.tr.cells[20].textContent = tableplane.elevation+'\u00b0';
+ }
+ ////
+
+ tableplane.tr.className = classes;
+ }
}
if (show_squawk_warning) {
@@ -1784,6 +1825,8 @@ function sortByLatitude() { sortBy('lat', compareNumeric, function(x) { retu
function sortByLongitude() { sortBy('lon', compareNumeric, function(x) { return (x.position !== null ? x.position[0] : null) }); }
function sortByDataSource() { sortBy('data_source', compareAlpha, function(x) { return x.getDataSource() } ); }
+function sortByElevation() { sortBy('elevation', compareNumeric, function(x) { return x.elevation; }); } ////
+
var sortId = '';
var sortCompare = null;
var sortExtract = null;
@@ -2037,15 +2080,19 @@ function resetMap() {
localStorage['ZoomLvl'] = ZoomLvl = DefaultZoomLvl;
// Reset to default range rings
+//// localStorage['SiteCirclesElevation'] = SiteCirclesElevation = DefaultSiteCirclesElevation;
localStorage['SiteCirclesCount'] = SiteCirclesCount = DefaultSiteCirclesCount;
localStorage['SiteCirclesBaseDistance'] = SiteCirclesBaseDistance = DefaultSiteCirclesBaseDistance;
localStorage['SiteCirclesInterval'] = SiteCirclesInterval = DefaultSiteCirclesInterval;
setRangeRings();
createSiteCircleFeatures();
+
+ localStorage['SiteElevationAsl'] = SiteElevationAsl = DefaultSiteElevationAsl; ////
+ localStorage['SiteNegativeAngle'] = SiteNegativeAngle = DefaultSiteNegativeAngle; ////
// Set and refresh
OLMap.getView().setZoom(ZoomLvl);
- OLMap.getView().setCenter(ol.proj.fromLonLat([CenterLon, CenterLat]));
+ OLMap.getView().setCenter(ol.proj.fromLonLat([CenterLon, CenterLat]));
selectPlaneByHex(null,false);
}
@@ -2122,6 +2169,7 @@ function setColumnVisibility() {
]
// Show default columns if checkboxes have not been set
+
for (var i=0; i < defaultCheckBoxes.length; i++) {
var checkBoxdiv = defaultCheckBoxes[i];
var columnDiv = checkbox_div_map.get(checkBoxdiv)
@@ -2132,6 +2180,7 @@ function setColumnVisibility() {
showColumn(infoTable, columnDiv, true);
}
}
+
// Now check local storage checkbox status
checkbox_div_map.forEach(function (div, checkbox) {
@@ -2641,6 +2690,7 @@ function setRangeRingVisibility (showhide) {
});
}
+
// simple function to set range ring count
function setRingCount(val) {
localStorage['SiteCirclesCount'] = val;
@@ -2664,11 +2714,13 @@ function setRingInterval(val) {
// Set range ring globals and populate form values
function setRangeRings() {
+
SiteCirclesCount = Number(localStorage['SiteCirclesCount']) || DefaultSiteCirclesCount;
SiteCirclesBaseDistance = Number(localStorage['SiteCirclesBaseDistance']) || DefaultSiteCirclesBaseDistance;
SiteCirclesInterval = Number(localStorage['SiteCirclesInterval']) || DefaultSiteCirclesInterval;
// Populate text fields with current values
+
$('#range_ring_count').val(SiteCirclesCount);
$('#range_ring_base').val(SiteCirclesBaseDistance);
$('#range_ring_interval').val(SiteCirclesInterval);
@@ -2677,6 +2729,7 @@ function setRangeRings() {
// redraw range rings with form values
function onSetRangeRings() {
// Save state to localStorage
+
localStorage.setItem('SiteCirclesCount', parseFloat($("#range_ring_count").val().trim()));
localStorage.setItem('SiteCirclesBaseDistance', parseFloat($("#range_ring_base").val().trim()));
localStorage.setItem('SiteCirclesInterval', parseFloat($("#range_ring_interval").val().trim()));
@@ -2686,6 +2739,54 @@ function onSetRangeRings() {
createSiteCircleFeatures();
}
+//// functions to support configuration of global SiteElevationAsl & SiteNegativeAngle
+
+function setElevationAsl(val) {
+ localStorage['SiteElevationAsl'] = val;
+ setElevation();
+}
+
+function setElevation() {
+
+ SiteElevationAsl = Number(localStorage['SiteElevationAsl']) || DefaultSiteElevationAsl;
+
+ // Populate text field with current value
+
+ $('#elevation_asl').val(SiteElevationAsl);
+}
+
+function onSetElevationAsl() {
+ // Save state to localStorage
+
+ localStorage.setItem('SiteElevationAsl', parseFloat($("#elevation_asl").val().trim()));
+
+ setElevation();
+}
+
+function setNegativeAngle(val) {
+ localStorage['SiteNegativeAngle'] = val;
+ setAngle();
+}
+
+function setAngle() {
+
+ SiteNegativeAngle = Number(localStorage['SiteNegativeAngle']) || DefaultSiteNegativeAngle;
+
+ // Populate text field with current value
+
+ $('#negative_angle').val(SiteNegativeAngle);
+}
+
+function onSetNegativeAngle() {
+ // Save state to localStorage
+
+ var desiredNegativeAngle = parseFloat($("#negative_angle").val().trim());
+ localStorage.setItem('SiteNegativeAngle', desiredNegativeAngle < 0 ? desiredNegativeAngle : DefaultSiteNegativeAngle);
+
+ setAngle();
+}
+////
+
function toggleColumn(div, checkbox, toggled) {
if (typeof localStorage[checkbox] === 'undefined') {
localStorage.setItem(checkbox, 'deselected');