feat(nav/map): frame the trail, clamp distant waypoints to the edge

While a trail exists the map now fits the recorded route (plus the live
position) and no longer folds waypoints into the bounding box, so a far-off
waypoint can't zoom the view out and squash the trail. Waypoints that
project outside the framed area are clamped to the nearest edge (marker +
label) instead of being lost off-screen. With no trail, the view still
auto-fits to the waypoints as before.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-06-04 12:30:46 +02:00
parent 901c1dcd92
commit a12ff50edd
2 changed files with 11 additions and 3 deletions

View File

@@ -109,7 +109,7 @@ A waypoint is a saved spot — your car, camp, a water source — that you can n
**Dropping a waypoint****Hold Enter → Mark here**. This captures the current GPS fix and opens the on-screen keyboard for a short label (up to 11 characters — e.g. `CAR`, `CAMP`, `H2O`). Leaving it blank auto-names it `WP1`, `WP2`, … Marking works whether or not the trail is being recorded; it needs a GPS fix (otherwise it reports *No GPS fix*).
**On the map** — saved waypoints show on the Trail Map view as a hollow diamond with the label's first two characters beside it (enough to tell nearby waypoints apart). The map's bounding box always includes them, so off-track waypoints stay in frame. Waypoints and your current GPS position are drawn continuously — even with no trail recording in progress — so the Map view doubles as a live "you + your marks" view, not just a recorded-track plot.
**On the map** — saved waypoints show on the Trail Map view as a hollow diamond with the label's first two characters beside it (enough to tell nearby waypoints apart). Waypoints and your current GPS position are drawn continuously — even with no trail recording in progress — so the Map view doubles as a live "you + your marks" view, not just a recorded-track plot. With **no trail**, the view auto-fits to your waypoints and position. **While a trail exists**, the view frames the recorded route instead, and any waypoint that falls outside it is clamped to the nearest map edge — a distant mark can't blow up the scale and squash the trail.
**Navigating****Hold Enter → Waypoints** opens the list (each row shows the label and live distance). The list always begins with a synthetic **Trail start** row whenever a trail exists, so you can backtrack to where you began without having marked it. Select a row and press **Enter** to open the navigation view:

View File

@@ -677,11 +677,15 @@ private:
if (lon < min_lon) min_lon = lon; if (lon > max_lon) max_lon = lon;
}
};
// With a trail, frame the recorded route (and live position) and let far
// waypoints clamp to the map edge — they must not blow up the scale. Only
// when there's no trail do waypoints define the view.
if (have_trail) {
int32_t a, b, c, d; _store->boundingBox(a, b, c, d);
fold(a, b); fold(c, d);
} else {
for (int i = 0; i < nwp; i++) fold(wp.at(i).lat_1e6, wp.at(i).lon_1e6);
}
for (int i = 0; i < nwp; i++) fold(wp.at(i).lat_1e6, wp.at(i).lon_1e6);
if (have_gps) fold(my_lat, my_lon);
// Degenerate: everything at one coordinate — just centre the markers.
@@ -747,10 +751,14 @@ private:
}
// Waypoints, with the first two label characters beside the marker so
// nearby waypoints can be told apart.
// nearby waypoints can be told apart. A waypoint that falls outside the
// (trail-framed) view is clamped to the nearest edge instead of being lost.
const int wp_x_max = area_x + area_w - 1, wp_y_max = area_y + area_h - 1;
for (int i = 0; i < nwp; i++) {
const Waypoint& w = wp.at(i);
int wx, wy; projectLL(w.lat_1e6, w.lon_1e6, wx, wy);
if (wx < area_x) wx = area_x; else if (wx > wp_x_max) wx = wp_x_max;
if (wy < area_y) wy = area_y; else if (wy > wp_y_max) wy = wp_y_max;
drawWaypointMarker(display, wx, wy);
char s[3] = { w.label[0], w.label[0] ? w.label[1] : (char)0, 0 };
drawWaypointLabel(display, s, wx, wy, area_x, area_y, area_w, area_h);