mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-31 09:18:12 +00:00
feat(map): north + scale on home mini-map; avoid overlapping labels
Home Map page mini-preview gains a north mini-icon and a fillRect scale bar with a round-distance label (metric/imperial), and its status line now shows the distance to the nearest tracked contact alongside fix/track. Trail map labels no longer smear in dense clusters: each placed label reserves a rect and a new one tries four offsets around its marker, skipping (marker still shown) when none fit without overlap. Verified: WioTrackerL1_companion_solo_dual builds clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
92d4a7ae16
commit
3ffdfd64b6
@@ -554,6 +554,13 @@ public:
|
||||
if (have_gps) fold(mla, mlo);
|
||||
if (!init) return false;
|
||||
|
||||
// North marker — top-right, the same mini-icon as the full Trail map.
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
{
|
||||
const int ns = miniIconScale(display);
|
||||
miniIconDrawTop(display, ax + aw - ICON_MAP_NORTH.w * ns - 1, ay + 1, ICON_MAP_NORTH);
|
||||
}
|
||||
|
||||
int cx = ax + aw / 2, cy = ay + ah / 2;
|
||||
// Degenerate: one coincident point — just centre the markers.
|
||||
if (mnla == mxla && mnlo == mxlo) {
|
||||
@@ -586,6 +593,37 @@ public:
|
||||
miniIconDrawCentered(display, px, py, ICON_MAP_CONTACT);
|
||||
}
|
||||
if (have_gps) { int px, py; project(mla, mlo, px, py); miniIconDrawCentered(display, px, py, ICON_MAP_CURRENT); }
|
||||
|
||||
// Scale bar (bottom-left): a round distance ~1/3 of the width, drawn with
|
||||
// fillRect ticks (gfx line isn't available this early in the TU) + a label,
|
||||
// so the preview conveys rough scale / distance.
|
||||
{
|
||||
static const float M_PER_1E6 = 0.11132f; // metres per 1e-6° lat
|
||||
float ppm = scale / M_PER_1E6; // pixels per metre
|
||||
if (ppm > 0.0f) {
|
||||
bool imp = _task->useImperial();
|
||||
static const float MET_M[] = { 5,10,25,50,100,250,500,1000,2000,5000,10000,25000,50000 };
|
||||
static const char* MET_L[] = { "5m","10m","25m","50m","100m","250m","500m","1km","2km","5km","10km","25km","50km" };
|
||||
static const float IMP_M[] = { 4.572f,15.24f,30.48f,76.2f,152.4f,402.34f,804.67f,1609.34f,4828.0f,16093.4f,80467.2f };
|
||||
static const char* IMP_L[] = { "15ft","50ft","100ft","250ft","500ft","1/4mi","1/2mi","1mi","3mi","10mi","50mi" };
|
||||
const float* M = imp ? IMP_M : MET_M;
|
||||
const char* const* L = imp ? IMP_L : MET_L;
|
||||
int N = imp ? (int)(sizeof(IMP_M) / sizeof(IMP_M[0])) : (int)(sizeof(MET_M) / sizeof(MET_M[0]));
|
||||
float target = (aw / 3.0f) / ppm; // ~1/3 of the width, in metres
|
||||
int sel = 0;
|
||||
for (int i = N - 1; i >= 0; i--) if (M[i] <= target) { sel = i; break; }
|
||||
int barpx = (int)(M[sel] * ppm + 0.5f);
|
||||
if (barpx < 6) barpx = 6;
|
||||
if (barpx > aw - 2) barpx = aw - 2;
|
||||
int bx = ax + 1, by = ay + ah - 1;
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.fillRect(bx, by, barpx, 1); // bar
|
||||
display.fillRect(bx, by - 2, 1, 3); // left tick
|
||||
display.fillRect(bx + barpx - 1, by - 2, 1, 3); // right tick
|
||||
display.setCursor(bx, by - 2 - display.getLineHeight());
|
||||
display.print(L[sel]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -963,8 +1001,26 @@ public:
|
||||
char info[40];
|
||||
int32_t la, lo;
|
||||
bool fix = _task->currentLocation(la, lo);
|
||||
int trk = _task->liveTrack().active(rtc_clock.getCurrentTime());
|
||||
snprintf(info, sizeof(info), "Fix:%s Track:%d", fix ? "y" : "n", trk);
|
||||
uint32_t now_m = rtc_clock.getCurrentTime();
|
||||
LiveTrackStore& lt = _task->liveTrack();
|
||||
int trk = lt.active(now_m);
|
||||
// Distance to the nearest tracked contact, so the page also answers
|
||||
// "how far is the closest shared point".
|
||||
float nearest = -1.0f;
|
||||
if (fix) {
|
||||
for (int i = 0; i < LiveTrackStore::CAPACITY; i++) {
|
||||
if (!lt.isActive(i, now_m)) continue;
|
||||
float d = geo::haversineKm(la, lo, lt.slotAt(i).lat_1e6, lt.slotAt(i).lon_1e6);
|
||||
if (nearest < 0 || d < nearest) nearest = d;
|
||||
}
|
||||
}
|
||||
if (nearest >= 0) {
|
||||
char ds[12];
|
||||
geo::fmtDist(ds, sizeof(ds), nearest, _task->useImperial());
|
||||
snprintf(info, sizeof(info), "Fix:%s Trk:%d %s", fix ? "y" : "n", trk, ds);
|
||||
} else {
|
||||
snprintf(info, sizeof(info), "Fix:%s Track:%d", fix ? "y" : "n", trk);
|
||||
}
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
if (!drew)
|
||||
display.drawTextCentered(display.width() / 2, content_y + area_h / 2, "No GPS / no trail");
|
||||
|
||||
Reference in New Issue
Block a user