up
This commit is contained in:
@@ -68,7 +68,7 @@ import {
|
||||
Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
|
||||
} from '@/components/ui/select';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { pathBetween } from '@/lib/maidenhead';
|
||||
import { pathBetween, pathBetweenLatLon, gridToLatLon } from '@/lib/maidenhead';
|
||||
import { flagURL } from '@/lib/flags';
|
||||
|
||||
type QSO = QSOForm;
|
||||
@@ -1890,7 +1890,14 @@ export default function App() {
|
||||
both directly clickable, plus an always-visible Stop. The
|
||||
old Shift/Ctrl shortcuts were not discoverable enough. */}
|
||||
{(() => {
|
||||
const p = pathBetween(station.my_grid, grid);
|
||||
// Prefer grid-to-grid; fall back to lat/lon when the DX has no
|
||||
// grid but a known location (e.g. cty.dat-only entities like
|
||||
// Svalbard → no QRZ grid, but cty.dat gives coordinates).
|
||||
const myLL = gridToLatLon(station.my_grid);
|
||||
const p = pathBetween(station.my_grid, grid)
|
||||
?? (myLL && details.lat != null && details.lon != null
|
||||
? pathBetweenLatLon(myLL, { lat: details.lat, lon: details.lon })
|
||||
: null);
|
||||
const disabled = !p;
|
||||
const goto = (az: number) => RotatorGoTo(Math.round(az), -1).catch((err) => setError(String(err?.message ?? err)));
|
||||
return (
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
|
||||
} from '@/components/ui/select';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { pathBetween } from '@/lib/maidenhead';
|
||||
import { pathBetween, pathBetweenLatLon, gridToLatLon } from '@/lib/maidenhead';
|
||||
import { BandSlotGrid } from '@/components/BandSlotGrid';
|
||||
import { AwardRefSelector } from '@/components/AwardRefSelector';
|
||||
|
||||
@@ -122,10 +122,17 @@ export function DetailsPanel({ callsign: _cs, prefix, operatorGrid, remoteGrid,
|
||||
const open = tab ?? internalOpen; // controlled when `tab` is provided
|
||||
// Bearing/distance from operator's home grid to the remote station.
|
||||
// Recomputed only when either grid actually changes.
|
||||
const path = useMemo(
|
||||
() => pathBetween(operatorGrid, remoteGrid),
|
||||
[operatorGrid, remoteGrid],
|
||||
);
|
||||
const path = useMemo(() => {
|
||||
const byGrid = pathBetween(operatorGrid, remoteGrid);
|
||||
if (byGrid) return byGrid;
|
||||
// Fall back to lat/lon when the DX has coordinates but no grid (e.g. a
|
||||
// cty.dat-only entity like Svalbard: no QRZ grid, but cty.dat coordinates).
|
||||
const myLL = gridToLatLon(operatorGrid);
|
||||
if (myLL && details.lat != null && details.lon != null) {
|
||||
return pathBetweenLatLon(myLL, { lat: details.lat, lon: details.lon });
|
||||
}
|
||||
return null;
|
||||
}, [operatorGrid, remoteGrid, details.lat, details.lon]);
|
||||
const fmtDeg = (n: number) => `${Math.round(n)}°`;
|
||||
const fmtKm = (n: number) => `${Math.round(n).toLocaleString()} km`;
|
||||
|
||||
|
||||
@@ -77,6 +77,16 @@ export function pathBetween(fromGrid: string, toGrid: string): PathInfo | null {
|
||||
const a = gridToLatLon(fromGrid);
|
||||
const b = gridToLatLon(toGrid);
|
||||
if (!a || !b) return null;
|
||||
return pathBetweenLatLon(a, b);
|
||||
}
|
||||
|
||||
// pathBetweenLatLon computes the great-circle path between two lat/lon points.
|
||||
// Used as a fallback when a station has a known location (e.g. cty.dat entity
|
||||
// coordinates for Svalbard) but no Maidenhead grid.
|
||||
export function pathBetweenLatLon(
|
||||
a: { lat: number; lon: number },
|
||||
b: { lat: number; lon: number },
|
||||
): PathInfo {
|
||||
const φ1 = toRad(a.lat);
|
||||
const φ2 = toRad(b.lat);
|
||||
const Δλ = toRad(b.lon - a.lon);
|
||||
|
||||
Reference in New Issue
Block a user