4.5 KiB
Design Spec: Smart GPX-Marker Connector Logic
Date: 2026-06-20 Status: Approved
Problem
The map currently draws a straight connector line between every adjacent pair of journal/story entry markers in chronological order. When GPX track files are also present, this creates two overlapping representations of the same movement — the accurate GPX track line and a redundant straight-line connector. For segments with no GPX coverage (e.g. a train journey), the straight connector is useful and should remain.
Goal
Suppress connector lines between adjacent markers only when a single GPX file demonstrably covers both endpoints. Keep connectors for gaps that have no GPX coverage. Provide a per-entry override (force_connect) for cases where the algorithm suppresses a connector the author wants to show.
Behaviour Modes
No GPX files present
Existing behaviour unchanged. All adjacent markers are connected by a line in chronological order.
GPX files present
Auto-connectors off by default. For each adjacent pair of markers (M1 → M2):
- If
force_connect: trueon M2 → draw connector (override wins) - Otherwise run the spatial algorithm (see below)
- If the algorithm finds coverage → suppress connector
- If the algorithm finds no coverage → draw connector
Spatial Algorithm
Proximity threshold: 10 km
For each adjacent pair (M1, M2):
- For each loaded GPX file F: a. Pre-filter: if M1 or M2 lies outside F's bounding box expanded by 10 km → skip F cheaply b. Sample every 10th trackpoint in F; compute haversine distance to M1 and to M2 c. If both M1 and M2 have at least one sampled point within 10 km → suppress connector for this pair; stop checking further files
- If no file F covered both M1 and M2 → draw connector
Rationale for 10 km: entries are often posted from a hotel, village, or café near (but not on) a trail. 10 km accommodates varied terrain — coastal routes, hilly detours — without false-positives across genuinely separate segments.
Rationale for same-file requirement: two markers each near different GPX files (e.g. an inland hike and a coastal walk) must not suppress the connector between them — that gap (e.g. a train journey) is exactly what should be shown.
Fallback Behaviour
If any GPX file fails to load, treat it as absent for the algorithm. Connectors default to drawing rather than hiding — missing data never creates invisible gaps on the map.
Data Model Changes
Two new fields added to both the journal entry and story entry Grav blueprints:
force_connect
- Type: boolean
- Default: false / null (unset)
- Meaning: "always draw a connector from the previous marker to this entry"
- Only has visible effect when GPX files are present (when no GPX, auto-connectors are already on)
- Editable via Admin2 on any entry
transport_mode
- Type: enum
- Values:
walking,bicycle,bus,train,car - Default: null (unset)
- Meaning: how the author arrived at this location (attached to the arriving entry)
- Not visualised yet — data capture only, for future use (distance-by-mode stats, map icons, filter)
- Editable via Admin2 on any entry
Both fields are exposed in frontmatter. Adding them to the mobile post form is deferred (backlog: blueprint-to-form sync pass).
Client-Side Implementation
Entry JSON
The Twig template that serialises entries into a JS variable (TRACKER_ENTRIES or equivalent) gains two new fields per entry: force_connect (bool) and transport_mode (string or null).
Timing
Connector drawing is deferred until all GPX files have settled (Promise.all on load events). GPX tracks appear immediately as each file loads. Connectors render once all files are resolved or rejected.
Performance
- Bounding box pre-filter eliminates most files for any given pair without distance math
- Sampling every 10th trackpoint keeps the haversine checks cheap even for full-day GPX files (thousands of points → hundreds of checks per file per pair)
Deferred / Out of Scope
- Visualising
transport_modeon the map (icons, line styles by mode) - Distance-by-mode statistics
- Adding
force_connect/transport_modeto the mobile post form - Making the 10 km threshold configurable in
site.yaml
Affected Files (indicative)
user/themes/intotheeast/templates/map.html.twig— entry JSON serialisationuser/themes/intotheeast/js/map.js(or equivalent) — connector drawing logic + algorithm- Blueprint file(s) for journal and story entries — add two new fields