Map improv. (#3226)

This commit is contained in:
Totoo
2026-06-16 17:54:32 +02:00
committed by GitHub
parent d8a1e2530a
commit f5a5e8e5e8
3 changed files with 172 additions and 27 deletions
+101 -2
View File
@@ -30,13 +30,16 @@
#include "bmpfile.hpp"
#include "mathdef.hpp"
#include <array>
#include <cstdio>
#include <inttypes.h>
#include "portapack.hpp"
namespace ui {
#define MAX_MAP_ZOOM_IN 4000
#define MAX_MAP_ZOOM_OUT 10
#define MAP_ZOOM_RESOLUTION_LIMIT 5 // Max zoom-in to show map; rect height & width must divide into this evenly
#define MAX_MAP_ZOOM_OUT 15
#define MAP_ZOOM_RESOLUTION_LIMIT 10 // Max zoom-in to show map;
#define INVALID_LAT_LON 200
#define INVALID_ANGLE 400
@@ -74,6 +77,101 @@ struct GeoMarker {
}
};
class BMPFileCache {
public:
static constexpr uint8_t SlotsCount = 9;
BMPFileCache() {
}
~BMPFileCache() {
clear();
}
BMPFile* get(const int32_t z, const int32_t x, const int32_t y) {
// Cache hit.
for (auto& slot : slots_) {
if (slot.used && slot.x == x && slot.y == y && slot.z == z) {
slot.last_used = next_stamp();
return &slot.bmp;
}
}
// Select free slot first, otherwise LRU slot.
Slot* target = nullptr;
uint16_t oldest = 0xFFFFu;
for (auto& slot : slots_) {
if (!slot.used) {
target = &slot;
break;
}
if (slot.last_used < oldest) {
oldest = slot.last_used;
target = &slot;
}
}
if (!target) {
return nullptr;
}
if (target->used) {
target->bmp.close();
target->used = false;
}
// OSM tile path convention: <base>/<z>/<x>/<y>.bmp
char path_buffer[64];
snprintf(path_buffer, sizeof(path_buffer), "/OSM/%" PRId32 "/%" PRId32 "/%" PRId32 ".bmp", z, x, y);
if (!target->bmp.open(path_buffer, true)) {
target->bmp.close();
return nullptr;
}
target->x = x;
target->y = y;
target->z = z;
target->last_used = next_stamp();
target->used = true;
return &target->bmp;
}
void clear() {
for (auto& slot : slots_) {
if (slot.used) {
slot.bmp.close();
slot.used = false;
}
}
}
private:
struct Slot {
BMPFile bmp{};
int32_t x{};
int32_t y{};
int32_t z{};
uint16_t last_used{};
bool used{false};
};
uint16_t next_stamp() {
if (++stamp_ == 0) {
uint16_t v = 1;
for (auto& slot : slots_) {
if (slot.used) {
slot.last_used = v++;
}
}
stamp_ = v;
}
return stamp_;
}
std::array<Slot, SlotsCount> slots_{};
uint16_t stamp_{0};
};
class GeoPos : public View {
public:
enum alt_unit {
@@ -276,6 +374,7 @@ class GeoMap : public Widget {
bool hide_center_marker_{false};
GeoMapMode mode_{};
File map_file{};
BMPFileCache bmp_cache{};
bool map_opened{};
bool map_visible{};
uint16_t map_width{}, map_height{};