5e6a974a5d
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.7 KiB
4.7 KiB
id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
| id | title | status | type | domain | scope | priority | depends | blocks | related | created | updated | tags | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0035 | C++ map_tiles (slippy map OSM) | pendiente | feature |
|
multi-app | baja | 2026-05-17 | 2026-05-17 |
0035 — C++ map_tiles (slippy map OSM)
APP Metadata
| Campo | Valor |
|---|---|
| ID | 0035 |
| Estado | pendiente |
| Prioridad | baja |
| Tipo | feature — C++ viz (cpp/functions/viz) |
Dependencias
gl_texture_load_cpp_gfx (issue 0026), gl_loader_cpp_gfx. Vendor: cpp-httplib (si ya esta vendoreado por 0033) o reusar.
Desbloquea: apps GIS minimas, dashboards con localizacion (entities con lat/lon), debugging de scrapers geograficos.
Objetivo
Componente ImGui que renderiza un slippy map estilo Leaflet sobre OpenStreetMap tiles, con pan/zoom y soporte para markers + polylines.
Contexto
Hay datos geograficos en varios proyectos (registry de proveedores, viajes, infrastructura). No hay forma de visualizarlos en C++; se exporta a una notebook con folium o se monta un frontend React.
Arquitectura
cpp/functions/viz/
├── map_tiles.h # NEW
├── map_tiles.cpp # NEW
└── map_tiles.md # NEW (impure)
cpp/apps/primitives_gallery/
├── demos_map.cpp # NEW
├── demos.h # MOD
├── main.cpp # MOD
└── CMakeLists.txt # MOD
API propuesta
namespace fn {
struct MapMarker { double lat, lon; ImU32 color; const char* label; };
struct MapPolyline { std::vector<ImVec2> latlon; ImU32 color; float thickness = 2.f; }; // ImVec2 = (lat, lon)
struct MapState {
double lat = 40.4168; // Madrid default
double lon = -3.7038;
int zoom = 6; // 0..18
std::string tile_url = "https://tile.openstreetmap.org/{z}/{x}/{y}.png";
std::string user_agent = "fn-registry-map/0.1 (egutierrez@aurgi.com)";
bool show_attribution = true; // OSM atribucion obligatoria
};
void map_tiles(const char* id, MapState&,
const MapMarker* markers, int n_markers,
const MapPolyline* polylines, int n_polylines,
ImVec2 size = {-1, -1});
}
Tareas
Fase 1 — Tile cache
- 1.1 Cache en disco bajo
~/.cache/fn-registry/tiles/{z}/{x}/{y}.png. Crear directorio si no existe. - 1.2 Cache en RAM (LRU) de
GlTextureya subidas, max 256 entradas. - 1.3 Funcion
tile_get_or_fetch(z, x, y): si en RAM → return; si en disco → load (gl_texture_load); si no → spawn thread que descarga via cpp-httplib y guarda en disco. Mientras tanto, devolver placeholder.
Fase 2 — Proyeccion + interaction
- 2.1 Funciones puras
lonlat_to_xy(lat, lon, zoom) -> (px, py)yxy_to_lonlat. - 2.2
map_tiles_handle_input: drag pan, wheel zoom (clamp 0-18), mantener punto bajo cursor durante zoom.
Fase 3 — Render
- 3.1 Calcular tiles visibles dado el viewport y zoom.
- 3.2 Para cada tile visible:
ImGui::Image(texture, screen_rect)oAddImageen el DrawList. - 3.3 Markers:
AddCircleFilled+ texto. - 3.4 Polylines: convertir lat/lon a screen y
AddPolyline. - 3.5 Atribucion en esquina inferior derecha:
"© OpenStreetMap contributors".
Fase 4 — User-Agent + ToS
- 4.1 Enviar
User-Agentcustom (OSM lo exige). Documentar en.mdque el usuario debe poner su contacto. - 4.2 Cap a 2 requests/segundo simultaneos para no abusar del tile server.
Fase 5 — Gallery demo
- 5.1
demos_map.cppcondemo_map_tiles(): mapa centrado en Espana, 5 markers en ciudades, polyline conectandolas. - 5.2 Registrar.
Fase 6 — Tests + docs
- 6.1 Tests puros de proyeccion (Madrid → conocidos pixels a zoom 10).
- 6.2
./fn index+./fn show map_tiles_cpp_viz.
Ejemplo de uso
fn::MapState m;
fn::MapMarker markers[] = {
{40.4168, -3.7038, IM_COL32(255,80,80,255), "Madrid"},
{41.3851, 2.1734, IM_COL32(80,150,255,255), "Barcelona"},
};
fn::map_tiles("##m", m, markers, 2, nullptr, 0);
Decisiones de diseño
- OSM tile server por defecto: gratis, sin API key. Documentar limite y alternativa (carto, stamen) cambiando
tile_url. - Cache en
~/.cache/fn-registry/tiles/: respeta XDG; persistente entre runs. - Sin GeoJSON parsing en MVP: solo markers/polylines via API. GeoJSON en issue futuro.
Riesgos
- Bloqueo de IP por OSM: documentar terminos de uso (max 1 req/s recomendado, User-Agent unico).
- Tiles a alta latitud: documentar que la proyeccion Web Mercator distorsiona >85°.
- Threading de descargas: cuidado con marshalling de texturas GL (deben crearse en hilo con contexto). Patron: descargar PNG bytes en thread, crear GL texture en main thread.