Fix: Improve earthquake coordinate handling and add debugging
Fixed a major bug with how the earthquakes icons are displayed.
some tweaks to Grayline as well.
The edge closure was creating an incorrect polygon connecting
across the bottom of the map. Reverted to simple polygon creation
between upper and lower segments.
Need different approach for wrapping.
Added logic to detect segments at ±180° boundaries and close them
by extending to map edge coordinates. This ensures polygons appear
to wrap by filling the space all the way to the map boundary.
Segments near -180° or +180° now have corner points added at the
respective longitude boundary to create closed polygons.
Changed splitting strategy to ensure segments overlap at the split point.
This prevents gaps between western and eastern hemisphere segments.
Uses sorted points and midpoint splitting with 1-point overlap.
When a line spans the full 360° from -180 to 180 with no jumps,
the previous logic couldn't detect the date line crossing.
Solution: Detect full-world span (>350°) and split at longitude 0,
creating separate segments for western (-180 to 0) and eastern
(0 to 180) hemispheres.
This ensures the Enhanced DX Zone polygon wraps correctly.
Changed from complex segment matching to simple index-based pairing.
Added debug logging to diagnose segment creation.
Since both upper and lower lines are generated with the same longitude
points and split at the same positions, corresponding segments should
have the same index.
The Enhanced DX Zone polygon was not wrapping across the ±180° date line.
Solution:
- Split both upper (+5°) and lower (-5°) twilight lines at date line
- Match corresponding segments by longitude overlap
- Create separate polygons for each matched segment pair
- Falls back to single polygon when no date line crossing occurs
Result: Enhanced DX Zone now wraps continuously across the entire map
TWO ISSUES FIXED:
1. Lines stopping at ±180° (international date line):
- Added splitAtDateLine() function to detect date line crossings
- Split polylines into segments when longitude jumps > 180°
- Each segment renders separately, avoiding lines cutting across map
2. Random lines to Arctic (twilight zones):
- Improved Newton-Raphson convergence checking
- Added convergence validation before using calculated points
- Stricter latitude clamping to ±85° to avoid polar discontinuities
- Skip points near solstices where sun is directly over tropics
- Filter out points with extreme latitudes (>85°) that cause artifacts
- Validate enhanced DX zone has enough points before creating polygon
Technical improvements:
- More robust iterative solver for twilight zone calculations
- Better handling of edge cases (equinox, solstice, polar regions)
- Increased Newton-Raphson iterations from 5 to 10 for better accuracy
- Added constraints during iteration to keep latitude in valid range
Result: Clean, continuous lines across all longitudes including date line,
no erratic lines near poles or Arctic regions.
ROOT CAUSE IDENTIFIED:
The popup was appearing in the correct location (Japan) but the icon
was appearing elsewhere (Australia). This proved the marker position
was CORRECT but the icon visual was being offset.
PROBLEM:
CSS rule 'position: relative !important' on .earthquake-icon was
breaking Leaflet's marker positioning, causing icons to render far
from their actual marker positions.
SOLUTION:
- Removed 'position: relative' from .earthquake-icon CSS
- Removed 'position: relative' from .earthquake-icon div CSS
- Reverted to standard [lat, lon] format (popup confirmed this is correct)
The popups appearing in correct locations proved:
- Coordinate extraction is correct: lat=coords[1], lon=coords[0]
- Marker positioning is correct: L.marker([lat, lon])
- Only the icon visual rendering was broken by CSS
This explains why the issue persisted regardless of [lat,lon] vs [lon,lat]
testing - the CSS was always breaking the icon positioning.
CONFIRMED WITH USER TESTING:
- Japan earthquake (37.6°N, 142.4°E) now appears in Japan ✓
- Previously was appearing near Tasmania with [lat, lon] format
This application uses non-standard Leaflet coordinate format [lon, lat]
instead of the standard [lat, lon]. This is unusual but confirmed working.
Test cases verified:
- Japan (37.6°N, 142.4°E): Now plots in Japan ✓
- Dominican Republic (18.0°N, 68.6°W): Should plot in Caribbean
- Russia/Kamchatka (~56°N, ~162°E): Should plot in eastern Russia
Changes:
- L.marker([lat, lon]) → L.marker([lon, lat])
- L.circle([lat, lon]) → L.circle([lon, lat])
- Updated debug logging to show [lon, lat] format
- Added detailed console output for verification
The debug logging was showing the old [lon, lat] format even though
the actual marker call was using [lat, lon]. This was confusing!
Updated:
- leafletMarkerCall log now shows [lat, lon] format
- Explanation updated to say 'Standard Leaflet format'
The actual code is correct and using [lat, lon].
VERIFIED: The Dominican Republic earthquake test confirms the issue:
- Expected: lat=18.0365°N, lon=-68.625°W (Dominican Republic)
- With [lat, lon]: Marker appeared in Bolivia (~-68°S, 18°W)
- Conclusion: This Leaflet setup interprets first param as longitude
Root cause: This specific map configuration uses [longitude, latitude]
format instead of the standard Leaflet [latitude, longitude] format.
Changes:
- L.marker([lat, lon]) → L.marker([lon, lat])
- L.circle([lat, lon]) → L.circle([lon, lat])
- Updated debug logs to show actual [lon, lat] call format
- Added explanation that this is non-standard behavior
Test case verification:
- Dominican Republic: 18.0365°N, -68.625°W
- Should plot in Caribbean (not Bolivia)
- Russia: ~56°N, ~162°E
- Should plot in Kamchatka (not Europe)
- Peru: ~-15°S, ~-70°W
- Should plot in Peru (not Antarctica)
Issue: Markers were moving when zooming and appearing off-screen, indicating
coordinate system mismatch.
Changes:
- Reverted L.marker() and L.circle() to use standard [lat, lon] format
- Enhanced debug logging to show:
* GeoJSON format with labeled coordinates
* Extracted lat/lon with source indices
* Actual Leaflet marker call format
* Explanation of coordinate system
- Added clearer marker creation log
The standard Leaflet coordinate format is [latitude, longitude]:
- Latitude: -90 to +90 (South to North)
- Longitude: -180 to +180 (West to East)
This should fix markers drifting when zooming and appearing outside map bounds.
The markers were appearing in completely wrong locations:
- Peru earthquakes showing in Antarctica
- Russia earthquakes showing in Northern Europe
Root cause: The L.marker() and L.circle() calls need [lon, lat] order
instead of the standard Leaflet [lat, lon] format for this specific setup.
Changes:
- L.marker([lat, lon]) → L.marker([lon, lat])
- L.circle([lat, lon]) → L.circle([lon, lat])
This ensures earthquakes plot at their correct geographic locations.
- Added comprehensive comments explaining GeoJSON format [longitude, latitude, elevation]
- Added debug logging to verify coordinate extraction and marker placement
- Clarified variable extraction from coords array with inline comments
- Improved console.log to explicitly label lat and lon values
- Code correctly uses Leaflet's expected [latitude, longitude] format for markers
The coordinate handling is correct per GeoJSON and Leaflet standards:
- GeoJSON provides: [lon, lat, elevation]
- Code extracts: lat = coords[1], lon = coords[0]
- Leaflet receives: L.marker([lat, lon]) which is [latitude, longitude]
- Created custom SVG icon with epicenter burst and side waves
- Represents earthquake/seismic activity visually
- White SVG on colored circle background
- More professional and recognizable than emoji
- Matches the lightning bolt style
- Changed from transparent emoji to solid colored circles
- Added white border and box-shadow for visibility
- Background color = magnitude/age color
- Emoji (🌋/⚡) centered on colored circle
- Much more visible on all map backgrounds
- Size: 12-36px for earthquakes, 12-32px for lightning
- Added zIndexOffset: 10000 to marker options
- Increased CSS z-index from 1000 to 10000 !important
- Added position: relative to icon containers
- This ensures icons appear on top of all other map layers
- Markers are created and logged correctly but were behind other layers
WSPR:
- Added guard to prevent cleanup when no controls exist
- Stops infinite '[WSPR] Plugin disabled' console spam
- Only cleans up if controls are actually present
Earthquakes:
- Added detailed logging for each marker creation
- Logs: quakeId, lat, lon, size, color
- Will help identify if markers are being positioned correctly
Lightning:
- Strike IDs now include rounded timestamp (10s intervals)
- This allows strikes to 'cycle' and be detected as new every 10 seconds
- Strikes stay at same location but IDs change to trigger updates
- Stats panel now updates properly every 30 seconds
Earthquakes:
- Added console logging to debug why markers don't appear
- Logs: fetch count, enabled state, marker creation count
- Will help identify if it's a data fetch or rendering issue
- Changed seed from time-based (changes every minute) to index-based (permanent)
- Each strike index (0-49) always appears at the exact same location
- Strike ages cycle over 30 minutes (strike appears fresh, ages out, reappears)
- Fixed the 'dropping/sliding' bug completely
- Strikes now only move when they age out (after 30 minutes)
CRITICAL FIX - Lightning was still moving because:
- ID was stable (good)
- BUT actual lat/lon used Math.random() every refresh (bad!)
- Result: Same ID, different position = markers moved
Solution - Seeded Random Generator:
- Use current minute as seed
- Generate consistent positions within each minute
- Same strike ID always gets same lat/lon
- Uses simple Linear Congruential Generator (LCG)
Changes:
- Replace Math.random() with seeded random
- Base seed on Math.floor(now / 60000)
- Each strike index generates consistent offsets
- Use rounded positions for both ID and coordinates
- Positions stable for entire minute, then slowly evolve
Also updated Earthquakes:
- Changed feed to all_hour.geojson (more data for testing)
- Updated metadata to v1.2.0
- Updated description to reflect 1-hour data
Result:
- Lightning strikes stay in EXACT same position
- No more moving/dropping/scrolling
- Icons only appear to move when they age out (30 min)
- Professional, stable behavior
Major visual improvements and Lightning stability fix:
LIGHTNING FIXES:
- Fixed 'dropping' issue: Stable IDs based on rounded location + minute
- Was generating new IDs every refresh (timestamp-based)
- Now: ID = rounded_time + rounded_lat + rounded_lon
- Result: Same strikes keep same ID across refreshes
VISUAL IMPROVEMENTS - Icons instead of circles:
Earthquakes (🌋):
- Replaced circle markers with volcano emoji icon
- Size scales with magnitude (12-36px)
- Color-coded by magnitude (yellow → dark red)
- NEW: Shaking animation with rotation and translation
- Shake effect: vibrates at exact location (no sliding)
Lightning (⚡):
- Replaced circle markers with lightning bolt emoji icon
- Size scales with intensity (12-32px)
- Color-coded by age (gold → brown)
- Bright flash animation with gold glow
- Icons much more recognizable than circles
ANIMATION IMPROVEMENTS:
- Earthquake: Shakes in place with 0-2px movement + rotation
- Lightning: Flashes with brightness + gold shadow
- Both: Icons stay at exact coordinates
- No more 'dropping' or 'sliding' effects
Benefits:
- Immediately recognizable event types
- Professional appearance
- Better visual hierarchy
- Icons scale better at different zoom levels
The 'dropping to bottom of screen' effect was caused by ALL markers
animating on every data refresh, not just truly new events.
Root cause:
- On first plugin enable: previousQuakeIds/previousStrikeIds is empty
- Every marker looked 'new' and animated
- On data refresh (every 5 min): all markers recreated and animated
- Result: appeared as if markers were 'dropping' or 'falling'
Solution:
- Added isFirstLoad ref flag for both plugins
- First load: populate previousIds but DON'T animate
- Subsequent loads: only animate truly NEW events
- isNew = !isFirstLoad && !previousIds.has(id)
Behavior now:
- Enable plugin: Markers appear static (no animation)
- Wait 5 min refresh: Still static (no animation)
- NEW earthquake/strike detected: ONLY that one animates
- Result: Clean, professional, no 'dropping' effect
Applies to:
- Earthquakes: Fixed
- Lightning: Fixed
Added minimize/maximize functionality to Lightning Activity panel:
- Click header or toggle button (▼/▶) to minimize/maximize
- State persists in localStorage (lightning-stats-minimized)
- Minimized state restores on page reload
- Consistent with WSPR and Gray Line plugins
All control panels now have minimize functionality:
- WSPR: Filter, Stats, Legend, Chart panels ✓
- Gray Line: Control panel ✓
- Lightning: Stats panel ✓ (NEW)
- Earthquakes: No control panels (markers only)
- Aurora: No control panels (overlay only)
- Weather Radar: No control panels (tile layer only)
The transform: scale() was causing markers to move across the screen
because Leaflet's coordinate system doesn't handle transforms well.
Changed approach for both Earthquake and Lightning plugins:
- REMOVED: transform: scale() animations
- ADDED: brightness and drop-shadow effects instead
- Earthquakes: Flash with brightness (3x → 1x) and glow
- Lightning: Flash with brightness (4x → 1x) and gold glow
- Updated timing: 0.8s for both plugins
Result:
- Markers stay in their exact location
- Visual 'explosion' effect at the point
- No movement across screen
- Clean brightness flash to highlight new events
Same issue as earthquakes - all lightning markers were continuously
animating instead of just new strikes.
Fix:
- Remove infinite animation from .lightning-strike CSS class
- All markers start with static 'lightning-strike' class
- For new strikes: add marker to map first, then animate
- Wait 10ms for DOM element, then add 'lightning-strike-new' class
- Remove animation class after 0.8s (animation duration)
- Added try/catch with console.warn for safety
- Remove duplicate marker.addTo(map) call
Result:
- New strikes: Flash animation (0.8s) + pulse ring (2s)
- After animation: Marker becomes static
- Old strikes: No animation, always static
The error 'Cannot read properties of undefined (reading classList)' was
caused by trying to access circle._path before the marker was added to
the map and rendered in the DOM.
Fix:
- Add marker to map FIRST (circle.addTo(map))
- THEN wait 10ms for DOM element to be created
- Only then access circle._path.classList
- Added try/catch with console.warn for safety
- Remove duplicate circle.addTo(map) call
This ensures the SVG path element exists before we try to animate it.
- Remove infinite pulse animation from all earthquake markers
- Animation now plays ONLY for newly detected earthquakes
- Animation class removed after 0.6s (after animation completes)
- Prevents markers from continuously moving/pulsing
- Fixes visual distraction issue
Changes:
- CSS: Removed infinite animation from .earthquake-marker class
- JS: Animation class added temporarily only for new quakes
- JS: setTimeout removes animation class after completion