diff --git a/docs/plans/2026-02-27-callsign-trail-line-design.md b/docs/plans/2026-02-27-callsign-trail-line-design.md new file mode 100644 index 0000000..c11c9d8 --- /dev/null +++ b/docs/plans/2026-02-27-callsign-trail-line-design.md @@ -0,0 +1,151 @@ +# 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`** + +3. 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:** +```typescript +{ + 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 + +### 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 + +## 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