diff --git a/src/OpenStreetMap-esp32.cpp b/src/OpenStreetMap-esp32.cpp index 4cb6d31..1a6e502 100644 --- a/src/OpenStreetMap-esp32.cpp +++ b/src/OpenStreetMap-esp32.cpp @@ -261,22 +261,11 @@ bool OpenStreetMap::fetchMap(LGFX_Sprite &mapSprite, double longitude, double la } } - // normalize the coordinates longitude = fmod(longitude + 180.0, 360.0) - 180.0; latitude = std::clamp(latitude, -90.0, 90.0); tileList requiredTiles; computeRequiredTiles(longitude, latitude, zoom, requiredTiles); - -#define SHOW_REQUIRED_TILES false -#if defined(SHOW_REQUIRED_TILES) && (SHOW_REQUIRED_TILES == true) - log_i("Required Tiles:"); - for (size_t i = 0; i < requiredTiles.size(); ++i) - { - log_i(" Tile [%zu]: X=%d, Y=%d", i, requiredTiles[i].first, requiredTiles[i].second); - } -#endif - if (tilesCache.capacity() < requiredTiles.size()) { log_e("Caching error: Need %i cache slots, but only %i are provided", requiredTiles.size(), tilesCache.capacity()); @@ -316,38 +305,22 @@ bool OpenStreetMap::readTileDataToBuffer(WiFiClient *stream, MemoryBuffer &buffe return true; } -bool OpenStreetMap::downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t y, uint8_t zoom, String &result) +std::optional> OpenStreetMap::downloadTile(const String &url, String &result, size_t &size) { - const uint32_t worldTileWidth = 1 << zoom; - if (x >= worldTileWidth || y >= worldTileWidth) - { - result = "Out of range tile coordinates"; - return false; - } - - const String url = "https://tile.openstreetmap.org/" + String(zoom) + "/" + String(x) + "/" + String(y) + ".png"; - HTTPClient http; http.setUserAgent("OpenStreetMap-esp32/1.0 (+https://github.com/CelliesProjects/OpenStreetMap-esp32)"); if (!http.begin(url)) { result = "Failed to initialize HTTP client"; - return false; + return std::nullopt; } const int httpCode = http.GET(); if (httpCode != HTTP_CODE_OK) { http.end(); - - if (httpCode == HTTP_CODE_NOT_FOUND) - { - result = "HTTP Error 404 - not found tile " + String(x) + "," + String(y) + "," + String(zoom); - return false; - } - result = "HTTP Error: " + String(httpCode); - return false; + return std::nullopt; } const size_t contentSize = http.getSize(); @@ -355,7 +328,7 @@ bool OpenStreetMap::downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t { http.end(); result = "Empty or chunked response"; - return false; + return std::nullopt; } WiFiClient *stream = http.getStreamPtr(); @@ -363,57 +336,77 @@ bool OpenStreetMap::downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t { http.end(); result = "Failed to get HTTP stream"; - return false; + return std::nullopt; } - MemoryBuffer buffer(contentSize); - if (!buffer.isAllocated()) + auto buffer = std::make_unique(contentSize); + if (!buffer->isAllocated()) { http.end(); result = "Failed to allocate buffer"; - return false; + return std::nullopt; } - if (!readTileDataToBuffer(stream, buffer, contentSize, result)) + if (!readTileDataToBuffer(stream, *buffer, contentSize, result)) { http.end(); - log_e("%s", result.c_str()); - return false; + return std::nullopt; } http.end(); + size = contentSize; + result = "Downloaded tile " + url; + return buffer; +} - const int16_t rc = png.openRAM(buffer.get(), contentSize, PNGDraw); - if (rc != PNG_SUCCESS) +bool OpenStreetMap::downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t y, uint8_t zoom, String &result) +{ + const uint32_t worldTileWidth = 1 << zoom; + if (x >= worldTileWidth || y >= worldTileWidth) { - result = "PNG Decoder Error: " + String(rc); + result = "Out of range tile coordinates"; return false; } - if (png.getWidth() != OSM_TILESIZE || png.getHeight() != OSM_TILESIZE) + const String url = "https://tile.openstreetmap.org/" + String(zoom) + "/" + String(x) + "/" + String(y) + ".png"; + { - result = "Unexpected tile size: w=" + String(png.getWidth()) + " h=" + String(png.getWidth()); - return false; - } + size_t contentSize; + auto buffer = downloadTile(url, result, contentSize); + if (!buffer) + return false; - currentInstance = this; - currentTileBuffer = tile.buffer; - const int decodeResult = png.decode(0, PNG_FAST_PALETTE); - currentTileBuffer = nullptr; - currentInstance = nullptr; + const int16_t rc = png.openRAM(buffer.value()->get(), contentSize, PNGDraw); + if (rc != PNG_SUCCESS) + { + result = "PNG Decoder Error: " + String(rc); + return false; + } - if (decodeResult != PNG_SUCCESS) - { - result = "Decoding " + url + " failed with code: " + String(decodeResult); - tile.valid = false; - return false; + if (png.getWidth() != OSM_TILESIZE || png.getHeight() != OSM_TILESIZE) + { + result = "Unexpected tile size: w=" + String(png.getWidth()) + " h=" + String(png.getWidth()); + return false; + } + + currentInstance = this; + currentTileBuffer = tile.buffer; + const int decodeResult = png.decode(0, PNG_FAST_PALETTE); + currentTileBuffer = nullptr; + currentInstance = nullptr; + + if (decodeResult != PNG_SUCCESS) + { + result = "Decoding " + url + " failed with code: " + String(decodeResult); + tile.valid = false; + return false; + } } tile.x = x; tile.y = y; tile.z = zoom; tile.valid = true; - result = "Added: " + url; return true; } diff --git a/src/OpenStreetMap-esp32.h b/src/OpenStreetMap-esp32.h index 988a15a..a4c3e86 100644 --- a/src/OpenStreetMap-esp32.h +++ b/src/OpenStreetMap-esp32.h @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -67,6 +69,7 @@ class OpenStreetMap void updateCache(const tileList &requiredTiles, uint8_t zoom); bool isTileCached(uint32_t x, uint32_t y, uint8_t z); CachedTile *findUnusedTile(const tileList &requiredTiles, uint8_t zoom); + std::optional> downloadTile(const String &url, String &result, size_t &size); bool downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t y, uint8_t zoom, String &result); bool readTileDataToBuffer(WiFiClient *stream, MemoryBuffer &buffer, size_t contentSize, String &result); bool composeMap(LGFX_Sprite &mapSprite, const tileList &requiredTiles, uint8_t zoom);