fix: proper beam heading on the map

This commit is contained in:
2026-06-16 20:24:49 +02:00
parent e5c6bddb29
commit 3d15f20c7f
+12 -23
View File
@@ -122,10 +122,8 @@ export function MainMap({ fromGrid, toGrid, fromLabel, toLabel, beamAzimuths, be
if (from && beamAzimuths && beamAzimuths.length) { if (from && beamAzimuths && beamAzimuths.length) {
const half = (beamWidth ?? 30) / 2; const half = (beamWidth ?? 30) / 2;
const D = 5500; // lobe length (km) const D = 5500; // lobe length (km)
// A great circle pointing poleward runs to lat ±90, where Mercator is // Great-circle radial out to distance D, stopping just short of the pole so
// infinite — the line then snaps across the top of the map. Generate the // a poleward line doesn't snap across the top of the Mercator map.
// radial with plenty of points (smooth curve) and STOP it just before the
// pole, so a north/south beam draws a clean line toward the edge instead.
const radial = (b: number): [number, number][] => { const radial = (b: number): [number, number][] => {
const pts: [number, number][] = []; const pts: [number, number][] = [];
const N = 64; const N = 64;
@@ -137,26 +135,17 @@ export function MainMap({ fromGrid, toGrid, fromLabel, toLabel, beamAzimuths, be
return pts; return pts;
}; };
for (const az of beamAzimuths) { for (const az of beamAzimuths) {
const arc: [number, number][] = []; // Draw the lobe as a FAN of translucent great-circle radials, not a
for (let b = az - half; b <= az + half + 0.001; b += 2) { // filled polygon: a polygon breaks badly near the poles on Mercator (its
const d = destinationPoint(from.lat, from.lon, b, D); // edges run off toward ±90° and the fill smears across the map), while
arc.push([d.lat, d.lon]); // each radial LINE stays clean. The overlapping lines read as a lobe —
// solid near the antenna, fanning out toward the front. Works for any
// azimuth, north/south included.
for (let b = az - half; b <= az + half + 0.001; b += 1.5) {
const line = unwrapLon([[from.lat, from.lon], ...radial(b)]);
L.polyline(line as L.LatLngExpression[], { color: '#dc2626', weight: 6, opacity: 0.07 }).addTo(wo);
} }
const ring = unwrapLon([ // Boresight (dashed centre line).
[from.lat, from.lon],
...radial(az - half),
...arc,
...radial(az + half).reverse(),
]);
// Near a pole the lobe's two edges diverge wildly (one runs NW, the
// other NE) and look broken on a Mercator map — so for a poleward beam
// show ONLY the clean boresight (below). Otherwise draw the filled lobe.
if (!ring.some(([la]) => Math.abs(la) > 78)) {
L.polygon(ring as L.LatLngExpression[], {
color: '#dc2626', weight: 1, opacity: 0.5, fillColor: '#dc2626', fillOpacity: 0.14,
}).addTo(wo);
}
// Boresight (dashed centre line) — always; great-circle polyline is safe.
const cl = unwrapLon([[from.lat, from.lon], ...radial(az)]); const cl = unwrapLon([[from.lat, from.lon], ...radial(az)]);
L.polyline(cl as L.LatLngExpression[], { color: '#dc2626', weight: 1.5, opacity: 0.7, dashArray: '5 4' }) L.polyline(cl as L.LatLngExpression[], { color: '#dc2626', weight: 1.5, opacity: 0.7, dashArray: '5 4' })
.bindTooltip(`Beam ${Math.round(az)}°`, { permanent: false, direction: 'top' }).addTo(wo); .bindTooltip(`Beam ${Math.round(az)}°`, { permanent: false, direction: 'top' }).addTo(wo);