From 74aae70af2fa995945cf89402147d52f7f03d6a2 Mon Sep 17 00:00:00 2001 From: accius Date: Mon, 2 Feb 2026 18:38:36 -0500 Subject: [PATCH] stab at fixing antimeridian issues --- src/components/WorldMap.jsx | 26 ++++++++++++++++++-------- src/utils/geo.js | 17 ++++++++++++++--- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/components/WorldMap.jsx b/src/components/WorldMap.jsx index b7043e6..0f0cf63 100644 --- a/src/components/WorldMap.jsx +++ b/src/components/WorldMap.jsx @@ -538,14 +538,24 @@ export const WorldMap = ({ ); // Validate points before creating polyline - if (points && points.length > 1 && points.every(p => Array.isArray(p) && !isNaN(p[0]) && !isNaN(p[1]))) { - const line = L.polyline(points, { - color: bandColor, - weight: 1.5, - opacity: 0.5, - dashArray: '4, 4' - }).addTo(map); - pskMarkersRef.current.push(line); + // getGreatCirclePoints returns array of segments (each segment is array of [lat,lon]) + if (points && Array.isArray(points) && points.length > 0) { + // Check if it's segmented (array of arrays of points) or flat (single segment) + const isSegmented = Array.isArray(points[0]) && points[0].length > 0 && Array.isArray(points[0][0]); + const segments = isSegmented ? points : [points]; + + segments.forEach(segment => { + if (segment && Array.isArray(segment) && segment.length > 1 && + segment.every(p => Array.isArray(p) && !isNaN(p[0]) && !isNaN(p[1]))) { + const line = L.polyline(segment, { + color: bandColor, + weight: 1.5, + opacity: 0.5, + dashArray: '4, 4' + }).addTo(map); + pskMarkersRef.current.push(line); + } + }); } // Add small dot marker at spot location diff --git a/src/utils/geo.js b/src/utils/geo.js index 86e4f01..5b46e7d 100644 --- a/src/utils/geo.js +++ b/src/utils/geo.js @@ -210,15 +210,26 @@ export const getGreatCirclePoints = (lat1, lon1, lat2, lon2, n = 100) => { let currentSegment = [rawPoints[0]]; for (let i = 1; i < rawPoints.length; i++) { + const prevLat = rawPoints[i-1][0]; const prevLon = rawPoints[i-1][1]; + const currLat = rawPoints[i][0]; const currLon = rawPoints[i][1]; // Check if we crossed the antimeridian (lon jumps more than 180°) if (Math.abs(currLon - prevLon) > 180) { - // Finish current segment + // Interpolate the crossing point + // Normalize longitudes so the crossing is smooth + const prevLonAdj = prevLon; + const currLonAdj = currLon > prevLon ? currLon - 360 : currLon + 360; + const frac = (prevLon > 0 ? 180 - prevLon : -180 - prevLon) / (currLonAdj - prevLonAdj); + const crossLat = prevLat + frac * (currLat - prevLat); + + // End current segment at the map edge + currentSegment.push([crossLat, prevLon > 0 ? 180 : -180]); segments.push(currentSegment); - // Start new segment - currentSegment = []; + + // Start new segment from the opposite edge + currentSegment = [[crossLat, prevLon > 0 ? -180 : 180]]; } currentSegment.push(rawPoints[i]); }