diff --git a/public/index.html b/public/index.html index 47bc726..289a8cf 100644 --- a/public/index.html +++ b/public/index.html @@ -1630,57 +1630,73 @@ // Add new DX paths if enabled if (showDXPaths && dxPaths && dxPaths.length > 0) { dxPaths.forEach((path, index) => { - // Draw great circle line from spotter to DX station - const pathPoints = getGreatCirclePoints( - path.spotterLat, path.spotterLon, - path.dxLat, path.dxLon - ); - - // Use different colors based on band (derived from frequency) - const freq = parseFloat(path.freq); - let color = '#4488ff'; // Default blue - if (freq >= 1.8 && freq < 2) color = '#ff6666'; // 160m - red - else if (freq >= 3.5 && freq < 4) color = '#ff9966'; // 80m - orange - else if (freq >= 7 && freq < 7.5) color = '#ffcc66'; // 40m - yellow - else if (freq >= 10 && freq < 10.5) color = '#99ff66'; // 30m - lime - else if (freq >= 14 && freq < 14.5) color = '#66ff99'; // 20m - green - else if (freq >= 18 && freq < 18.5) color = '#66ffcc'; // 17m - teal - else if (freq >= 21 && freq < 21.5) color = '#66ccff'; // 15m - cyan - else if (freq >= 24 && freq < 25) color = '#6699ff'; // 12m - blue - else if (freq >= 28 && freq < 30) color = '#9966ff'; // 10m - purple - else if (freq >= 50 && freq < 54) color = '#ff66ff'; // 6m - magenta - - // Handle antimeridian crossing - const segments = Array.isArray(pathPoints[0]) ? pathPoints : [pathPoints]; - segments.forEach(segment => { - const line = L.polyline(segment, { - color: color, - weight: 1.5, - opacity: 0.5 - }).addTo(map); - dxPathsLinesRef.current.push(line); - }); + try { + // Skip if missing or invalid coordinates + if (!path.spotterLat || !path.spotterLon || !path.dxLat || !path.dxLon) return; + if (isNaN(path.spotterLat) || isNaN(path.spotterLon) || isNaN(path.dxLat) || isNaN(path.dxLon)) return; + + // Draw great circle line from spotter to DX station + const pathPoints = getGreatCirclePoints( + path.spotterLat, path.spotterLon, + path.dxLat, path.dxLon + ); + + // Skip if no valid path points + if (!pathPoints || !Array.isArray(pathPoints) || pathPoints.length === 0) return; + + // Use different colors based on band (derived from frequency) + const freq = parseFloat(path.freq); + let color = '#4488ff'; // Default blue + if (freq >= 1.8 && freq < 2) color = '#ff6666'; // 160m - red + else if (freq >= 3.5 && freq < 4) color = '#ff9966'; // 80m - orange + else if (freq >= 7 && freq < 7.5) color = '#ffcc66'; // 40m - yellow + else if (freq >= 10 && freq < 10.5) color = '#99ff66'; // 30m - lime + else if (freq >= 14 && freq < 14.5) color = '#66ff99'; // 20m - green + else if (freq >= 18 && freq < 18.5) color = '#66ffcc'; // 17m - teal + else if (freq >= 21 && freq < 21.5) color = '#66ccff'; // 15m - cyan + else if (freq >= 24 && freq < 25) color = '#6699ff'; // 12m - blue + else if (freq >= 28 && freq < 30) color = '#9966ff'; // 10m - purple + else if (freq >= 50 && freq < 54) color = '#ff66ff'; // 6m - magenta + + // Handle antimeridian crossing - pathPoints may be array of segments or single segment + // Check if first element's first element is an array (segment structure) vs just [lat, lon] + const isSegmented = Array.isArray(pathPoints[0]) && pathPoints[0].length > 0 && Array.isArray(pathPoints[0][0]); + const segments = isSegmented ? pathPoints : [pathPoints]; + + segments.forEach(segment => { + if (segment && Array.isArray(segment) && segment.length > 1) { + const line = L.polyline(segment, { + color: color, + weight: 1.5, + opacity: 0.5 + }).addTo(map); + dxPathsLinesRef.current.push(line); + } + }); - // Add small markers at DX station end only (to reduce clutter) - const dxIcon = L.divIcon({ - className: '', - html: `
`, - iconSize: [6, 6], - iconAnchor: [3, 3] - }); - - const marker = L.marker([path.dxLat, path.dxLon], { icon: dxIcon }) - .bindPopup(` -
- ${path.dxCall}
- spotted by ${path.spotter}
- ${path.freq} MHz
- ${path.comment || ''}
- ${path.time} -
- `) - .addTo(map); - dxPathsMarkersRef.current.push(marker); + // Add small markers at DX station end only (to reduce clutter) + const dxIcon = L.divIcon({ + className: '', + html: `
`, + iconSize: [6, 6], + iconAnchor: [3, 3] + }); + + const marker = L.marker([path.dxLat, path.dxLon], { icon: dxIcon }) + .bindPopup(` +
+ ${path.dxCall}
+ spotted by ${path.spotter}
+ ${path.freq} MHz
+ ${path.comment || ''}
+ ${path.time} +
+ `) + .addTo(map); + dxPathsMarkersRef.current.push(marker); + } catch (err) { + console.error('[DX Paths] Error rendering path:', err, path); + } }); } }, [dxPaths, showDXPaths]);