lolngitude unwrapping

pull/41/head
accius 2 days ago
parent 650e9a4279
commit 0aae5f3177

@ -267,21 +267,16 @@ export const WorldMap = ({
const isHovered = hoveredSpot && hoveredSpot.call === path.dxCall && const isHovered = hoveredSpot && hoveredSpot.call === path.dxCall &&
Math.abs(parseFloat(hoveredSpot.freq) - parseFloat(path.freq)) < 0.01; Math.abs(parseFloat(hoveredSpot.freq) - parseFloat(path.freq)) < 0.01;
// Handle segments // Handle path rendering (single continuous array, unwrapped across antimeridian)
const isSegmented = Array.isArray(pathPoints[0]) && pathPoints[0].length > 0 && Array.isArray(pathPoints[0][0]); if (pathPoints && Array.isArray(pathPoints) && pathPoints.length > 1) {
const segments = isSegmented ? pathPoints : [pathPoints]; const line = L.polyline(pathPoints, {
color: isHovered ? '#ffffff' : color,
segments.forEach(segment => { weight: isHovered ? 4 : 1.5,
if (segment && Array.isArray(segment) && segment.length > 1) { opacity: isHovered ? 1 : 0.5
const line = L.polyline(segment, { }).addTo(map);
color: isHovered ? '#ffffff' : color, if (isHovered) line.bringToFront();
weight: isHovered ? 4 : 1.5, dxPathsLinesRef.current.push(line);
opacity: isHovered ? 1 : 0.5 }
}).addTo(map);
if (isHovered) line.bringToFront();
dxPathsLinesRef.current.push(line);
}
});
// Add DX marker // Add DX marker
const dxCircle = L.circleMarker([path.dxLat, path.dxLon], { const dxCircle = L.circleMarker([path.dxLat, path.dxLon], {
@ -358,34 +353,20 @@ export const WorldMap = ({
// Draw orbit track if available // Draw orbit track if available
if (sat.track && sat.track.length > 1) { if (sat.track && sat.track.length > 1) {
// Split track into segments to handle date line crossing // Unwrap longitudes for continuous rendering across antimeridian
let segments = []; const unwrapped = sat.track.map(p => [...p]);
let currentSegment = [sat.track[0]]; for (let i = 1; i < unwrapped.length; i++) {
while (unwrapped[i][1] - unwrapped[i-1][1] > 180) unwrapped[i][1] -= 360;
for (let i = 1; i < sat.track.length; i++) { while (unwrapped[i][1] - unwrapped[i-1][1] < -180) unwrapped[i][1] += 360;
const prevLon = sat.track[i-1][1];
const currLon = sat.track[i][1];
// If longitude jumps more than 180 degrees, start new segment
if (Math.abs(currLon - prevLon) > 180) {
segments.push(currentSegment);
currentSegment = [];
}
currentSegment.push(sat.track[i]);
} }
segments.push(currentSegment);
// Draw each segment const trackLine = L.polyline(unwrapped, {
segments.forEach(segment => { color: sat.visible ? satColor : satColorDark,
if (segment.length > 1) { weight: 2,
const trackLine = L.polyline(segment, { opacity: sat.visible ? 0.8 : 0.4,
color: sat.visible ? satColor : satColorDark, dashArray: sat.visible ? null : '5, 5'
weight: 2, }).addTo(map);
opacity: sat.visible ? 0.8 : 0.4, satTracksRef.current.push(trackLine);
dashArray: sat.visible ? null : '5, 5'
}).addTo(map);
satTracksRef.current.push(trackLine);
}
});
} }
// Draw footprint circle if available and satellite is visible // Draw footprint circle if available and satellite is visible
@ -537,25 +518,16 @@ export const WorldMap = ({
50 50
); );
// Validate points before creating polyline // Validate points before creating polyline (single continuous array, unwrapped across antimeridian)
// getGreatCirclePoints returns array of segments (each segment is array of [lat,lon]) if (points && Array.isArray(points) && points.length > 1 &&
if (points && Array.isArray(points) && points.length > 0) { points.every(p => Array.isArray(p) && !isNaN(p[0]) && !isNaN(p[1]))) {
// Check if it's segmented (array of arrays of points) or flat (single segment) const line = L.polyline(points, {
const isSegmented = Array.isArray(points[0]) && points[0].length > 0 && Array.isArray(points[0][0]); color: bandColor,
const segments = isSegmented ? points : [points]; weight: 1.5,
opacity: 0.5,
segments.forEach(segment => { dashArray: '4, 4'
if (segment && Array.isArray(segment) && segment.length > 1 && }).addTo(map);
segment.every(p => Array.isArray(p) && !isNaN(p[0]) && !isNaN(p[1]))) { pskMarkersRef.current.push(line);
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 // Add small dot marker at spot location

@ -205,37 +205,14 @@ export const getGreatCirclePoints = (lat1, lon1, lat2, lon2, n = 100) => {
rawPoints.push([toDeg(Math.atan2(z, Math.sqrt(x*x+y*y))), toDeg(Math.atan2(y, x))]); rawPoints.push([toDeg(Math.atan2(z, Math.sqrt(x*x+y*y))), toDeg(Math.atan2(y, x))]);
} }
// Split path at antimeridian crossings for proper Leaflet rendering // Unwrap longitudes to be continuous (no jumps > 180°)
const segments = []; // This lets Leaflet draw smoothly across the antimeridian and world copies
let currentSegment = [rawPoints[0]];
for (let i = 1; i < rawPoints.length; i++) { for (let i = 1; i < rawPoints.length; i++) {
const prevLat = rawPoints[i-1][0]; while (rawPoints[i][1] - rawPoints[i-1][1] > 180) rawPoints[i][1] -= 360;
const prevLon = rawPoints[i-1][1]; while (rawPoints[i][1] - rawPoints[i-1][1] < -180) rawPoints[i][1] += 360;
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) {
// 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 from the opposite edge
currentSegment = [[crossLat, prevLon > 0 ? -180 : 180]];
}
currentSegment.push(rawPoints[i]);
} }
segments.push(currentSegment);
return segments; return rawPoints;
}; };
export default { export default {

Loading…
Cancel
Save

Powered by TurnKey Linux.