// Maidenhead grid square overlay shared between the main propagation map // and the rover planner map. Draws red field/square rectangles with labels. export class GridSquare { constructor(lat, lon) { this.lat = lat this.lon = ((lon % 360) + 540) % 360 - 180 } encode(precision = 4) { const adjLon = this.lon + 180 const adjLat = this.lat + 90 let g = "" g += String.fromCharCode(65 + Math.floor(adjLon / 20)) g += String.fromCharCode(65 + Math.floor(adjLat / 10)) g += Math.floor((adjLon % 20) / 2) g += Math.floor(adjLat % 10) if (precision > 4) { g += String.fromCharCode(97 + Math.floor(((adjLon % 2) * 60) / 5)) g += String.fromCharCode(97 + Math.floor(((adjLat % 1) * 60) / 2.5)) } return g } static decode(grid) { const f1 = grid.charCodeAt(0) - 65 const f2 = grid.charCodeAt(1) - 65 let west = f1 * 20 - 180 let south = f2 * 10 - 90 let w = 20, h = 10 if (grid.length >= 4) { west += parseInt(grid[2]) * 2 south += parseInt(grid[3]) w = 2; h = 1 } if (grid.length >= 6) { west += (grid.charCodeAt(4) - 97) * 5 / 60 south += (grid.charCodeAt(5) - 97) * 2.5 / 60 w = 5 / 60; h = 2.5 / 60 } return { west, east: west + w, south, north: south + h, center: { lat: south + h / 2, lon: west + w / 2 } } } } function drawGridSquare(grid, precision, bounds, layerGroup, drawnSet, map) { if (grid.length < 2 || drawnSet.has(grid)) return drawnSet.add(grid) const c = GridSquare.decode(grid) if (c.west > bounds.getEast() || c.east < bounds.getWest() || c.south > bounds.getNorth() || c.north < bounds.getSouth()) return const field = precision <= 2 layerGroup.addLayer(L.rectangle( [[c.south, c.west], [c.north, c.east]], { color: "#E63946", weight: field ? 2.5 : 2, opacity: 0.8, fillOpacity: 0, interactive: false } )) const sw = map.latLngToContainerPoint([c.south, c.west]) const ne = map.latLngToContainerPoint([c.north, c.east]) const px = Math.abs(ne.x - sw.x) const minW = field ? 30 : 40 if (px > minW) { const len = field ? 2 : 4 const text = grid.substring(0, len) const fs = Math.max(10, Math.min(14, Math.round(px / (len * 1.2)))) layerGroup.addLayer(L.marker([c.center.lat, c.center.lon], { interactive: false, icon: L.divIcon({ className: "grid-label", html: `