diff --git a/static/js/geo.js b/static/js/geo.js index d977f6d..c22ce4d 100644 --- a/static/js/geo.js +++ b/static/js/geo.js @@ -20,6 +20,20 @@ function calcBearing(lat1, lon1, lat2, lon2) { return bearing; } +function calcDistanceKm(lat1, lon1, lat2, lon2) { + const EARTH_RADIUS_KM = 6371; + lat1 *= Math.PI / 180; + lon1 *= Math.PI / 180; + lat2 *= Math.PI / 180; + lon2 *= Math.PI / 180; + const latDelta = lat2 - lat1; + const lonDelta = lon2 - lon1; + const a = Math.sin(latDelta / 2) ** 2 + + Math.cos(lat1) * Math.cos(lat2) * Math.sin(lonDelta / 2) ** 2; + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return EARTH_RADIUS_KM * c; +} + // Convert a Maidenhead grid reference of arbitrary precision to the lat/long of the centre point of the square. // Returns null if the grid format is invalid. function latLonForGridCentre(grid) { diff --git a/static/js/spots.js b/static/js/spots.js index 4524f55..98d6d3b 100644 --- a/static/js/spots.js +++ b/static/js/spots.js @@ -115,6 +115,7 @@ function updateTable() { const showMode = $("#tableShowMode")[0].checked; const showComment = $("#tableShowComment")[0].checked; const showBearing = $("#tableShowBearing")[0].checked && userPos != null; + const showDistance = $("#tableShowDistance")[0].checked && userPos != null; const showType = $("#tableShowType")[0].checked; const showRef = $("#tableShowRef")[0].checked; const showDE = $("#tableShowDE")[0].checked; @@ -141,6 +142,9 @@ function updateTable() { if (showBearing) { table.find('thead tr').append(`
`); } + if (showDistance) { + table.find('thead tr').append(``); + } if (showType) { table.find('thead tr').append(``); } @@ -191,6 +195,7 @@ function createNewTableRowsForSpot(s, highlightNew) { const showMode = $("#tableShowMode")[0].checked; const showComment = $("#tableShowComment")[0].checked; const showBearing = $("#tableShowBearing")[0].checked && userPos != null; + const showDistance = $("#tableShowDistance")[0].checked && userPos != null; const showType = $("#tableShowType")[0].checked; const showRef = $("#tableShowRef")[0].checked; const showDE = $("#tableShowDE")[0].checked; @@ -280,13 +285,27 @@ function createNewTableRowsForSpot(s, highlightNew) { bearingText = bearing.toFixed(0).padStart(3, '0') + "°"; if (s["dx_location_good"] == null || s["dx_location_good"] === false) { if (s["dx_location_source"] === "HOME QTH") { - bearingText = bearingText + ""; + bearingText = bearingText + ""; } else { bearingText = bearingText + ""; } } } + // Format distance text + let distanceText = "---"; + if (userPos != null && s["dx_latitude"] != null && s["dx_longitude"] != null) { + const distance = calcDistanceKm(userPos[0], userPos[1], s["dx_latitude"], s["dx_longitude"]); + distanceText = distance.toFixed(0) + " km"; + if (s["dx_location_good"] == null || s["dx_location_good"] === false) { + if (s["dx_location_source"] === "HOME QTH") { + distanceText = distanceText + ""; + } else { + distanceText = distanceText + ""; + } + } + } + // Format "type" (Sig or fallback to source) let typeText = s["source"]; if (s["sig"]) { @@ -354,6 +373,9 @@ function createNewTableRowsForSpot(s, highlightNew) { if (showBearing) { $tr.append(``); } + if (showDistance) { + $tr.append(``); + } if (showType) { $tr.append(``); } @@ -394,6 +416,9 @@ function createNewTableRowsForSpot(s, highlightNew) { if (showBearing) { $td2floatright.append(`${bearingText} `); } + if (showDistance) { + $td2floatright.append(`${distanceText} `); + } if (showDE) { $td2floatright.append(` de ${de_call} `); } @@ -443,12 +468,14 @@ function loadOptions() { // Load settings from settings storage now all the controls are available loadSettings(); - // Extra setting - the toggle for the "bearing" column is disabled if the user has not entered a valid grid, and - // normally this logic is handled on user input to the grid field, but we might have just loaded a value direct - // into the field, so apply the same logic here. + // Extra setting - the toggle for the "bearing" & "distance" columns are disabled if the user has not entered a + // valid grid, and normally this logic is handled on user input to the grid field, but we might have just loaded + // a value direct into the field, so apply the same logic here. $("#tableShowBearing").prop('disabled', !isUserGridValid()); + $("#tableShowDistance").prop('disabled', !isUserGridValid()); if (!isUserGridValid()) { $("#tableShowBearing").prop('checked', false); + $("#tableShowDistance").prop('checked', false); } // Load spots (this will also set up the SSE connection to update them too) @@ -470,8 +497,10 @@ function userGridUpdated() { } // Enable/disable bearing column depending on grid validity $("#tableShowBearing").prop('disabled', !userGridValid); + $("#tableShowDistance").prop('disabled', !userGridValid); if (!userGridValid) { $("#tableShowBearing").prop('checked', false); + $("#tableShowDistance").prop('checked', false); } // Save settings even if not a valid grid, this allows the user to clear their grid and have it save. saveSettings(); diff --git a/templates/add_spot.html b/templates/add_spot.html index 8163620..424da73 100644 --- a/templates/add_spot.html +++ b/templates/add_spot.html @@ -76,7 +76,7 @@ - + diff --git a/templates/alerts.html b/templates/alerts.html index 3c00668..1f0369c 100644 --- a/templates/alerts.html +++ b/templates/alerts.html @@ -82,7 +82,7 @@ - + diff --git a/templates/bands.html b/templates/bands.html index 8286586..dae3fff 100644 --- a/templates/bands.html +++ b/templates/bands.html @@ -79,8 +79,8 @@ - - + + diff --git a/templates/base.html b/templates/base.html index 5d18d8a..96b3efc 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,6 +1,6 @@ {% extends "skeleton.html" %} {% block head_extra %} - + @@ -10,10 +10,10 @@ - - - - + + + + {% end %} {% block body %}