From 5ab807a02a084f5db7b817382122c72e06e1287f Mon Sep 17 00:00:00 2001 From: Jakub <106778416+MarekZegare4@users.noreply.github.com> Date: Sun, 31 May 2026 00:19:40 +0200 Subject: [PATCH] fix(trail): map grid no longer silently disappears on elongated trails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A very elongated trail (lat_span << lon_span or vice-versa) shares an isotropic scale, so the visible window in the *short* direction can span many grid_m. The previous code computed lat_n / lon_n once and bailed with `return` if either exceeded 40 — leaving the user with no grid at all on east-west or north-south runs. Now: after picking the initial step via the MIN_GRID_PX and shorter/2 loops, also bump the step up further until both lat_n and lon_n fit within MAX_GRID_LINES (40). Falls back to `return` only if even the largest STEPS[] entry (100 km) can't produce a small-enough grid — which shouldn't happen in practice on terrestrial trails. Also fixed: comment claimed "~4 intervals across shorter dim" while the code divides by 3.0f. Updated to "~3 intervals" to match. Co-Authored-By: Claude Opus 4.7 --- FEATURES.md | 1 + examples/companion_radio/ui-new/TrailScreen.h | 31 +++++++++++++------ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/FEATURES.md b/FEATURES.md index b00d2840..de3c8009 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -413,6 +413,7 @@ Fix status after this pass: - ✅ M4 — `renderDiscoverDetail` skips pub-key line on very narrow displays - ✅ L1 — SNR shown with 0.25 dB precision everywhere - ✅ L4 — fallback `"?"` sender no longer memsets through `strncpy` +- ✅ Trail map grid silent loss — when a very elongated trail makes `lat_n` or `lon_n` exceed 40, the renderer now bumps the step up instead of dropping the grid entirely. Comment fixed to match the `/ 3.0f` divisor ("~3 intervals", not 4). [`TrailScreen.h:505-565`](examples/companion_radio/ui-new/TrailScreen.h#L505-L565) - ❌ M1 — re-checked, not a bug (`default_scope_name[31]`) - 📋 H1 + H2 — still open; need coordinated fix in upstream `BaseChatMesh` (`findChannelIdx` should iterate `num_channels`, not `MAX_GROUP_CHANNELS`; `saveChannels` should stop at the first uninitialised slot) or a local override - 📋 H3 — left as known limitation pending UX call diff --git a/examples/companion_radio/ui-new/TrailScreen.h b/examples/companion_radio/ui-new/TrailScreen.h index 61ede5e9..d217c598 100644 --- a/examples/companion_radio/ui-new/TrailScreen.h +++ b/examples/companion_radio/ui-new/TrailScreen.h @@ -519,7 +519,7 @@ private: }; static const int N_STEPS = (int)(sizeof(STEPS)/sizeof(STEPS[0])); - // Pick largest step ≤ target_m (gives ~4 intervals across shorter dim). + // Pick largest step ≤ target_m (gives ~3 intervals across shorter dim). int sel = 0; for (int si = N_STEPS - 1; si >= 0; si--) { if ((float)STEPS[si] <= target_m) { sel = si; break; } @@ -534,24 +534,37 @@ private: float shorter_px = (float)(area_w < area_h ? area_w : area_h); while (sel > 0 && (float)STEPS[sel] / M_PER_1E6 * scale > shorter_px / 2.0f) sel--; - uint32_t grid_m = STEPS[sel]; - - float gs_lat = (float)grid_m / M_PER_1E6; - float gs_lon = (float)grid_m / (M_PER_1E6 * lon_scale_geo); float vis_lat_max = (float)max_lat + (float)(off_y - area_y) / scale; float vis_lat_min = (float)max_lat - (float)(area_y + area_h - off_y) / scale; float vis_lon_min = (float)min_lon - (float)(off_x - area_x) / (lon_scale_geo * scale); float vis_lon_max = (float)min_lon + (float)(area_x + area_w - off_x) / (lon_scale_geo * scale); + // Final guard: a very elongated trail (lat_span ≪ lon_span or vice-versa) + // shares a single isotropic scale, so the visible window in the *short* + // direction can span many grid_m. Bump the step up until the resulting + // line count fits the static buffers (40×40 = ~1600 intersections, plenty + // for any sane display). + static const int MAX_GRID_LINES = 40; + uint32_t grid_m = STEPS[sel]; + float gs_lat = (float)grid_m / M_PER_1E6; + float gs_lon = (float)grid_m / (M_PER_1E6 * lon_scale_geo); + int lat_n = (int)((vis_lat_max - vis_lat_min) / gs_lat) + 2; + int lon_n = (int)((vis_lon_max - vis_lon_min) / gs_lon) + 2; + while ((lat_n > MAX_GRID_LINES || lon_n > MAX_GRID_LINES) && sel < N_STEPS - 1) { + sel++; + grid_m = STEPS[sel]; + gs_lat = (float)grid_m / M_PER_1E6; + gs_lon = (float)grid_m / (M_PER_1E6 * lon_scale_geo); + lat_n = (int)((vis_lat_max - vis_lat_min) / gs_lat) + 2; + lon_n = (int)((vis_lon_max - vis_lon_min) / gs_lon) + 2; + } + if (lat_n > MAX_GRID_LINES || lon_n > MAX_GRID_LINES) return; // huge step still won't fit — give up + // Anchor to display edges so lines always start at the border and space inward. float first_lat = vis_lat_min; float first_lon = vis_lon_min; - int lat_n = (int)((vis_lat_max - first_lat) / gs_lat) + 2; - int lon_n = (int)((vis_lon_max - first_lon) / gs_lon) + 2; - if (lat_n > 40 || lon_n > 40) return; - int x_max = area_x + area_w - 1; int y_max = area_y + area_h - 1;