This commit is contained in:
2026-06-20 06:41:40 -04:00
parent 044ce40e69
commit 733e9b426f
9 changed files with 471 additions and 86 deletions
+34 -53
View File
@@ -324,6 +324,7 @@
let requests = [];
let map = null;
let mapLayers = [];
let frzGeometry = null;
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('login-form').addEventListener('submit', handleLogin);
@@ -339,6 +340,18 @@
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
loadFrzGeometry();
}
async function loadFrzGeometry() {
try {
const response = await fetch('/api/v1/drone-requests/frz');
if (!response.ok) throw new Error('Failed to load FRZ geometry');
frzGeometry = await response.json();
renderMap();
} catch (err) {
console.warn('Unable to load FRZ geometry', err);
}
}
function initializeAuth() {
@@ -514,67 +527,35 @@
function renderMap() {
clearMapLayers();
if (!selectedRequest || !map) return;
if (!map) return;
const point = [selectedRequest.location_latitude, selectedRequest.location_longitude];
const overlay = selectedRequest.prototype_overlay || {};
const arp = overlay.airport_reference_point || { lat: 51.6053, lng: -4.0678 };
const radius = overlay.frz_radius_metres || 3704;
if (frzGeometry) {
const frzLayer = L.geoJSON(frzGeometry, {
style: {
color: '#e74c3c',
weight: 2,
fillColor: '#e74c3c',
fillOpacity: 0.10
}
}).addTo(map);
addLayer(frzLayer);
}
addLayer(L.circle([arp.lat, arp.lng], {
radius,
color: '#2c3e50',
weight: 2,
fillColor: '#3498db',
fillOpacity: 0.08
}).addTo(map));
addRunwayProtectionRectangles(arp);
addLayer(L.marker(point).addTo(map).bindPopup(`
<strong>${escapeHtml(selectedRequest.reference_number)}</strong><br>
${escapeHtml(selectedRequest.operator_name)}<br>
${selectedRequest.maximum_elevation_ft_amsl} ft AMSL
`));
if (selectedRequest) {
const point = [selectedRequest.location_latitude, selectedRequest.location_longitude];
addLayer(L.marker(point).addTo(map).bindPopup(`
<strong>${escapeHtml(selectedRequest.reference_number)}</strong><br>
${escapeHtml(selectedRequest.operator_name)}<br>
${selectedRequest.maximum_elevation_ft_amsl} ft AMSL
`));
}
if (!mapLayers.length) return;
const group = L.featureGroup(mapLayers);
map.fitBounds(group.getBounds().pad(0.18));
setTimeout(() => map.invalidateSize(), 50);
}
function addRunwayProtectionRectangles(arp) {
addLayer(L.polygon(rotatedRectangle(arp.lat, arp.lng, 41, 5000, 1000), {
color: '#e67e22',
weight: 1,
fillOpacity: 0.08
}).addTo(map));
addLayer(L.polygon(rotatedRectangle(arp.lat, arp.lng, 95, 5000, 1000), {
color: '#e67e22',
weight: 1,
fillOpacity: 0.08
}).addTo(map));
}
function rotatedRectangle(lat, lng, bearingDeg, lengthM, widthM) {
const halfL = lengthM / 2;
const halfW = widthM / 2;
return [
offsetPoint(lat, lng, bearingDeg, halfL, halfW),
offsetPoint(lat, lng, bearingDeg, halfL, -halfW),
offsetPoint(lat, lng, bearingDeg, -halfL, -halfW),
offsetPoint(lat, lng, bearingDeg, -halfL, halfW)
];
}
function offsetPoint(lat, lng, bearingDeg, forwardM, rightM) {
const bearing = bearingDeg * Math.PI / 180;
const northM = Math.cos(bearing) * forwardM + Math.cos(bearing + Math.PI / 2) * rightM;
const eastM = Math.sin(bearing) * forwardM + Math.sin(bearing + Math.PI / 2) * rightM;
const latOffset = northM / 111320;
const lngOffset = eastM / (111320 * Math.cos(lat * Math.PI / 180));
return [lat + latOffset, lng + lngOffset];
}
function addLayer(layer) {
mapLayers.push(layer);
}