Files
pyxis/lib/tdeck_ui/UI/LXMF/TileMath.h
T
torlando-tech cff41d4fa0 Add offline map display and Sideband-compatible telemetry location sharing
- LVGL PNG decoder (lodepng) + SD card filesystem driver for loading OSM tiles
- MapScreen with 2x2 tile grid, GPS marker, peer location markers, pan/zoom
- 5th nav button (GPS icon) on conversation list for map access
- TelemetryCodec: Sideband/Columba-compatible LXMF telemetry encode/decode
- TelemetryManager: per-peer sharing sessions with duration/expiry, SPIFFS persistence
- ChatScreen location share button with duration picker (15min/1hr/4hr/indefinite)
- UIManager integration: telemetry send/receive via LXMF fields, map marker updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:05:28 -05:00

83 lines
2.5 KiB
C++

// Copyright (c) 2024 microReticulum contributors
// SPDX-License-Identifier: MIT
#ifndef UI_LXMF_TILEMATH_H
#define UI_LXMF_TILEMATH_H
#include <cmath>
#include <stdint.h>
namespace UI {
namespace LXMF {
/**
* Web Mercator tile coordinate math.
* Standard OSM/Slippy map tile numbering (z/x/y).
*/
namespace TileMath {
struct TileCoord {
int tile_x;
int tile_y;
int pixel_x; // 0-255, pixel offset within tile
int pixel_y;
};
/**
* Convert lat/lon to tile coordinates at a given zoom level.
* Returns the tile x/y and the pixel offset within that tile.
*/
inline TileCoord latlon_to_tile(double lat, double lon, int z) {
double n = (double)(1 << z);
double x = (lon + 180.0) / 360.0 * n;
double lat_rad = lat * M_PI / 180.0;
double y = (1.0 - log(tan(lat_rad) + 1.0 / cos(lat_rad)) / M_PI) / 2.0 * n;
TileCoord tc;
tc.tile_x = (int)floor(x);
tc.tile_y = (int)floor(y);
tc.pixel_x = (int)((x - tc.tile_x) * 256.0);
tc.pixel_y = (int)((y - tc.tile_y) * 256.0);
return tc;
}
/**
* Convert tile coordinates (top-left corner) back to lat/lon.
*/
inline void tile_to_latlon(int tile_x, int tile_y, int z, double& lat, double& lon) {
double n = (double)(1 << z);
lon = (double)tile_x / n * 360.0 - 180.0;
double lat_rad = atan(sinh(M_PI * (1.0 - 2.0 * (double)tile_y / n)));
lat = lat_rad * 180.0 / M_PI;
}
/**
* Convert a global pixel coordinate to lat/lon at a given zoom level.
* Global pixel = tile * 256 + pixel_offset
*/
inline void pixel_to_latlon(double global_px, double global_py, int z,
double& lat, double& lon) {
double n = (double)(1 << z);
lon = global_px / (n * 256.0) * 360.0 - 180.0;
double lat_rad = atan(sinh(M_PI * (1.0 - 2.0 * global_py / (n * 256.0))));
lat = lat_rad * 180.0 / M_PI;
}
/**
* Convert lat/lon to global pixel coordinates at a given zoom level.
*/
inline void latlon_to_pixel(double lat, double lon, int z,
double& px, double& py) {
double n = (double)(1 << z);
px = (lon + 180.0) / 360.0 * n * 256.0;
double lat_rad = lat * M_PI / 180.0;
py = (1.0 - log(tan(lat_rad) + 1.0 / cos(lat_rad)) / M_PI) / 2.0 * n * 256.0;
}
} // namespace TileMath
} // namespace LXMF
} // namespace UI
#endif // UI_LXMF_TILEMATH_H