aprs.me/docs/plans/2026-02-27-callsign-trail-line-design.md
Graham McIntire a939913114
docs: clarify trail line should connect all points regardless of distance
- Continuous path connection for long-distance travel
- No distance-based filtering or gap detection
- Important for aircraft, vehicles, intermittent coverage scenarios
2026-03-01 15:01:08 -06:00

6.1 KiB

Trail Line Display for Tracked Callsigns at Low Zoom

Problem Statement

When tracking a specific callsign (e.g., W5ISP-9), the map currently displays aggregated heat map data at zoom levels ≤ 8. This makes it impossible to see the individual path points and trajectory of the tracked station when zoomed out. Users need to see the complete path of a tracked callsign regardless of zoom level.

Solution Overview

Implement a trail line visualization that displays when tracking a specific callsign at low zoom levels (≤ 8). Instead of showing a heat map, the system will draw a polyline connecting all the station's position points in chronological order, clearly showing the path traveled.

Behavior Specification

When Tracking a Callsign

  • Zoom ≤ 8: Display trail line (polyline) connecting all positions chronologically

    • Clear any existing heat map
    • Fetch all packets for tracked callsign within time threshold
    • Sort by timestamp (chronological order)
    • Draw polyline on map
  • Zoom > 8: Display individual markers (current behavior)

    • Show APRS symbols at each position
    • Enable popup interactions

When NOT Tracking a Callsign

  • Zoom ≤ 8: Display heat map (current behavior)
  • Zoom > 8: Display individual markers (current behavior)

Technical Design

Backend Changes (Elixir)

File: lib/aprsme_web/live/map_live/display_manager.ex

  1. Modify handle_zoom_threshold_crossing/2:

    • Check if socket.assigns.tracked_callsign != ""
    • If tracking and zoom ≤ 8: call new function to send trail line
    • If tracking and zoom > 8: show markers as normal
    • If not tracking: use existing heat map/marker logic
  2. Add new function send_trail_line_for_tracked_callsign/1:

    • Query all packets for tracked callsign within time threshold
    • Sort packets by received_at (chronological order)
    • Extract coordinates (lat, lng, timestamp)
    • Push event show_trail_line with trail data

File: lib/aprsme_web/live/map_live/index.ex

  1. Update bounds update logic:
    • When processing bounds updates at zoom ≤ 8 with tracked callsign
    • Send trail line instead of heat map

Frontend Changes (TypeScript)

File: assets/js/map.ts

  1. Add state tracking:

    • currentTrailLine: Polyline | null - store reference to current trail line
  2. Add event handler show_trail_line:

    • Clear existing trail line if present
    • Create Leaflet Polyline from coordinates
    • Style the polyline (color, weight, opacity)
    • Add to map
    • Store reference in state
  3. Add event handler clear_trail_line:

    • Remove trail line from map
    • Clear state reference
  4. Update existing handlers:

    • show_heat_map: Clear trail line before showing heat map
    • show_markers: Clear trail line before showing markers
    • clear_all_markers: Also clear trail line

Data Structure

Trail Line Event Payload:

{
  callsign: string,
  points: Array<{
    lat: number,
    lng: number,
    timestamp: string
  }>
}

Visual Styling

Trail Line Appearance:

  • Color: #3B82F6 (blue-500) - distinct from other map elements
  • Weight: 3 pixels - visible but not overwhelming
  • Opacity: 0.8 - allows seeing map features underneath
  • Line Cap: round - smoother appearance at endpoints
  • Line Join: round - smoother corners
  • Interactive: true - allow clicking for info
  • Dash Pattern: none (solid line)

Optional Enhancement (Future):

  • Direction arrows along the line
  • Gradient color showing time progression
  • Click on line to show timestamp at that point

Implementation Notes

Continuous Path Connection

  • Connect all points regardless of distance: The trail line should connect all position points in chronological order, even if there are large gaps between positions
  • This is important for tracking stations that:
    • Travel long distances (aircraft, vehicles on highways)
    • Have intermittent coverage (gaps in digipeater/igate range)
    • Cross large geographic areas
  • Do NOT apply distance-based filtering or gap detection
  • The continuous line shows the complete journey path for the tracked callsign

Time Threshold Handling

  • Use existing socket.assigns.packet_age_threshold for filtering
  • Trail line respects the "Trail Duration" setting (1 hour, 6 hours, etc.)
  • When trail duration changes, regenerate trail line

Performance Considerations

  • Trail lines are only generated for tracked callsigns (not all stations)
  • Polylines are efficient for rendering many points
  • Clear trail line when switching away from tracked callsign
  • Debounce trail line updates during rapid zoom changes

Edge Cases

  • Empty trail (no packets): Don't draw anything
  • Single point: Don't draw line (show marker instead)
  • Zoom threshold crossing: Smoothly transition between trail and markers
  • Callsign tracking cleared: Remove trail line immediately
  • International date line crossing: Trail line should wrap correctly around the date line (Leaflet handles this automatically with proper coordinate ordering)
  • Large distance gaps: Continue drawing line even with large geographic gaps between consecutive points

Testing Strategy

  1. Manual Testing:

    • Track a callsign and zoom out to ≤ 8: verify trail line appears
    • Zoom in to > 8: verify markers appear
    • Clear tracking: verify trail line disappears
    • Change trail duration: verify trail line updates
  2. Visual Testing:

    • Verify trail line color and styling
    • Check line smoothness and appearance
    • Ensure map features remain visible underneath
  3. Edge Cases:

    • Callsign with no packets
    • Callsign with single packet
    • Callsign with very long trail (performance)
    • International date line crossing

Future Enhancements

  1. Direction Indicators: Add small arrows along the trail to show direction of travel
  2. Time-based Coloring: Gradient color from old (gray) to new (bright blue)
  3. Interactive Points: Click on trail to see packet details at that position
  4. Trail Simplification: Use line simplification algorithm (Douglas-Peucker) for very long trails
  5. Multiple Callsigns: Support tracking multiple callsigns with different colored trails