@@ -36,7 +36,7 @@ void OpenStreetMap::PNGDraw(PNGDRAW *pDraw)
3636 currentInstance->png .getLineAsRGB565 (pDraw, destRow, PNG_RGB565_BIG_ENDIAN, 0x0000 );
3737}
3838
39- void OpenStreetMap::computeRequiredTiles (double longitude, double latitude, uint8_t zoom, tileVector &requiredTiles)
39+ void OpenStreetMap::computeRequiredTiles (double longitude, double latitude, uint8_t zoom, tileList &requiredTiles)
4040{
4141 // Compute exact tile coordinates
4242 const double exactTileX = lon2tile (longitude, zoom);
@@ -100,21 +100,21 @@ void OpenStreetMap::computeRequiredTiles(double longitude, double latitude, uint
100100bool OpenStreetMap::isTileCached (uint32_t x, uint32_t y, uint8_t z)
101101{
102102 for (const auto &tile : tilesCache)
103- if (tile.valid && tile. x == x && tile.y == y && tile.z == z)
103+ if (tile.x == x && tile.y == y && tile.z == z && tile. valid )
104104 return true ;
105105
106106 return false ;
107107}
108108
109- CachedTile *OpenStreetMap::findUnusedTile (const tileVector &requiredTiles, uint8_t zoom)
109+ CachedTile *OpenStreetMap::findUnusedTile (const tileList &requiredTiles, uint8_t zoom)
110110{
111111 for (auto &tile : tilesCache)
112112 {
113113 // If a tile is valid but not required in the current frame, we can replace it
114114 bool needed = false ;
115115 for (const auto &[x, y] : requiredTiles)
116116 {
117- if (tile.valid && tile. x == x && tile.y == y && tile.z == zoom)
117+ if (tile.x == x && tile.y == y && tile.z == zoom && tile. valid )
118118 {
119119 needed = true ;
120120 break ;
@@ -161,21 +161,60 @@ bool OpenStreetMap::resizeTilesCache(uint8_t cacheSize)
161161 return true ;
162162}
163163
164- void OpenStreetMap::updateCache (tileVector &requiredTiles, uint8_t zoom)
164+ void OpenStreetMap::updateCache (tileList &requiredTiles, uint8_t zoom)
165165{
166166 for (const auto &[x, y] : requiredTiles)
167167 {
168168 if (!isTileCached (x, y, zoom))
169169 {
170170 CachedTile *tileToReplace = findUnusedTile (requiredTiles, zoom);
171171 String result;
172- const bool success = downloadAndDecodeTile (*tileToReplace, x, y, zoom, result);
173- if (!success)
172+ if (!downloadAndDecodeTile (*tileToReplace, x, y, zoom, result))
174173 log_e (" %s" , result.c_str ());
174+ }
175+ }
176+ }
175177
176- log_i (" %s" , result.c_str ());
178+ bool OpenStreetMap::composeMap (LGFX_Sprite &mapSprite, tileList &requiredTiles, uint8_t zoom)
179+ {
180+ if (mapSprite.width () != mapWidth || mapSprite.height () != mapHeight)
181+ {
182+ mapSprite.deleteSprite ();
183+ mapSprite.setPsram (true );
184+ mapSprite.setColorDepth (lgfx::rgb565_2Byte);
185+ mapSprite.createSprite (mapWidth, mapHeight);
186+ if (!mapSprite.getBuffer ())
187+ {
188+ log_e (" could not allocate" );
189+ return false ;
177190 }
178- }
191+ }
192+
193+ int tileIndex = 0 ;
194+ for (const auto &[tileX, tileY] : requiredTiles)
195+ {
196+ int drawX = startOffsetX + (tileIndex % numberOfColums) * OSM_TILESIZE;
197+ int drawY = startOffsetY + (tileIndex / numberOfColums) * OSM_TILESIZE;
198+
199+ auto it = std::find_if (tilesCache.begin (), tilesCache.end (),
200+ [&](const CachedTile &tile)
201+ {
202+ return tile.valid && tile.x == tileX && tile.y == tileY && tile.z == zoom;
203+ });
204+
205+ if (it != tilesCache.end ())
206+ mapSprite.pushImage (drawX, drawY, OSM_TILESIZE, OSM_TILESIZE, it->buffer );
207+ else
208+ log_w (" Tile (%d, %d) not found in cache" , tileX, tileY);
209+
210+ tileIndex++;
211+ }
212+
213+ const char *attribution = " Map data from OpenStreetMap.org " ;
214+ mapSprite.setTextColor (TFT_WHITE, TFT_BLACK);
215+ mapSprite.drawRightString (attribution, mapSprite.width (), mapSprite.height () - 10 , &DejaVu9);
216+
217+ return true ;
179218}
180219
181220bool OpenStreetMap::fetchMap (LGFX_Sprite &mapSprite, double longitude, double latitude, uint8_t zoom)
@@ -188,21 +227,25 @@ bool OpenStreetMap::fetchMap(LGFX_Sprite &mapSprite, double longitude, double la
188227
189228 if (!mapWidth || !mapHeight)
190229 {
191- log_e (" Invalid map dimensions: width=%d, height=%d " , mapWidth, mapHeight );
230+ log_e (" Invalid map dimension " );
192231 return false ;
193232 }
194233
195234 if (!tilesCache.capacity ())
196235 {
197236 log_w (" Cache not initialized, setting up a default cache..." );
198- resizeTilesCache (10 );
237+ if (!resizeTilesCache (OSM_DEFAULT_CACHE_ITEMS))
238+ {
239+ log_e (" Could not allocate cache" );
240+ return false ;
241+ }
199242 }
200243
201244 // normalize the coordinates
202245 longitude = fmod (longitude + 180.0 , 360.0 ) - 180.0 ;
203246 latitude = std::clamp (latitude, -90.0 , 90.0 );
204247
205- tileVector requiredTiles;
248+ tileList requiredTiles;
206249 computeRequiredTiles (longitude, latitude, zoom, requiredTiles);
207250
208251 if (tilesCache.capacity () < requiredTiles.size ())
@@ -211,59 +254,14 @@ bool OpenStreetMap::fetchMap(LGFX_Sprite &mapSprite, double longitude, double la
211254 return false ;
212255 }
213256
214- for (const auto &[x, y] : requiredTiles)
215- {
216- if (!isTileCached (x, y, zoom))
217- {
218- CachedTile *tileToReplace = findUnusedTile (requiredTiles, zoom);
219- String result;
220- const bool success = downloadAndDecodeTile (*tileToReplace, x, y, zoom, result);
221- if (!success)
222- log_e (" %s" , result.c_str ());
257+ updateCache (requiredTiles, zoom);
223258
224- log_i (" %s" , result.c_str ());
225- }
226- }
227-
228- if (mapSprite.width () != mapWidth || mapSprite.height () != mapHeight)
259+ if (!composeMap (mapSprite, requiredTiles, zoom))
229260 {
230- mapSprite.deleteSprite ();
231- mapSprite.setPsram (true );
232- mapSprite.setColorDepth (lgfx::rgb565_2Byte);
233- mapSprite.createSprite (mapWidth, mapHeight);
234- }
235-
236- if (mapSprite.getBuffer () == nullptr )
237- {
238- log_e (" could not allocate" );
261+ log_e (" Failed to compose map" );
239262 return false ;
240263 }
241264
242- int tileIndex = 0 ;
243- for (const auto &[tileX, tileY] : requiredTiles)
244- {
245- int drawX = startOffsetX + (tileIndex % numberOfColums) * OSM_TILESIZE;
246- int drawY = startOffsetY + (tileIndex / numberOfColums) * OSM_TILESIZE;
247-
248- auto it = std::find_if (tilesCache.begin (), tilesCache.end (),
249- [&](const CachedTile &tile)
250- {
251- return tile.valid && tile.x == tileX && tile.y == tileY && tile.z == zoom;
252- });
253-
254- if (it != tilesCache.end ())
255- mapSprite.pushImage (drawX, drawY, OSM_TILESIZE, OSM_TILESIZE, it->buffer );
256-
257- else
258- log_w (" Tile (%d, %d) not found in cache" , tileX, tileY);
259-
260- tileIndex++;
261- }
262-
263- const char *attribution = " Map data from OpenStreetMap.org " ;
264- mapSprite.setTextColor (TFT_WHITE, TFT_BLACK);
265- mapSprite.drawRightString (attribution, mapSprite.width (), mapSprite.height () - 10 , &DejaVu9);
266-
267265 return true ;
268266}
269267
@@ -313,7 +311,7 @@ bool OpenStreetMap::downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t
313311 return false ;
314312 }
315313
316- constexpr unsigned long TIMEOUT_MS = 500 ;
314+ constexpr unsigned long TIMEOUT_MS = 900 ;
317315 size_t readSize = 0 ;
318316 unsigned long lastReadTime = millis ();
319317
@@ -409,22 +407,22 @@ bool OpenStreetMap::saveMap(const char *filename, LGFX_Sprite &sprite, String &r
409407 uint32_t biClrImportant = 0 ;
410408
411409 // Write BMP header
412- file.write (reinterpret_cast <const uint8_t *>(&bfType), sizeof (bfType));
413- file.write (reinterpret_cast <const uint8_t *>(&bfSize), sizeof (bfSize));
414- file.write (reinterpret_cast <const uint8_t *>(&bfReserved), sizeof (bfReserved));
415- file.write (reinterpret_cast <const uint8_t *>(&bfOffBits), sizeof (bfOffBits));
416-
417- file.write (reinterpret_cast <const uint8_t *>(&biSize), sizeof (biSize));
418- file.write (reinterpret_cast <const uint8_t *>(&biWidth), sizeof (biWidth));
419- file.write (reinterpret_cast <const uint8_t *>(&biHeight), sizeof (biHeight));
420- file.write (reinterpret_cast <const uint8_t *>(&biPlanes), sizeof (biPlanes));
421- file.write (reinterpret_cast <const uint8_t *>(&biBitCount), sizeof (biBitCount));
422- file.write (reinterpret_cast <const uint8_t *>(&biCompression), sizeof (biCompression));
423- file.write (reinterpret_cast <const uint8_t *>(&biSizeImage), sizeof (biSizeImage));
424- file.write (reinterpret_cast <const uint8_t *>(&biXPelsPerMeter), sizeof (biXPelsPerMeter));
425- file.write (reinterpret_cast <const uint8_t *>(&biYPelsPerMeter), sizeof (biYPelsPerMeter));
426- file.write (reinterpret_cast <const uint8_t *>(&biClrUsed), sizeof (biClrUsed));
427- file.write (reinterpret_cast <const uint8_t *>(&biClrImportant), sizeof (biClrImportant));
410+ file.write (reinterpret_cast <const uint8_t *>(&bfType), sizeof (bfType));
411+ file.write (reinterpret_cast <const uint8_t *>(&bfSize), sizeof (bfSize));
412+ file.write (reinterpret_cast <const uint8_t *>(&bfReserved), sizeof (bfReserved));
413+ file.write (reinterpret_cast <const uint8_t *>(&bfOffBits), sizeof (bfOffBits));
414+
415+ file.write (reinterpret_cast <const uint8_t *>(&biSize), sizeof (biSize));
416+ file.write (reinterpret_cast <const uint8_t *>(&biWidth), sizeof (biWidth));
417+ file.write (reinterpret_cast <const uint8_t *>(&biHeight), sizeof (biHeight));
418+ file.write (reinterpret_cast <const uint8_t *>(&biPlanes), sizeof (biPlanes));
419+ file.write (reinterpret_cast <const uint8_t *>(&biBitCount), sizeof (biBitCount));
420+ file.write (reinterpret_cast <const uint8_t *>(&biCompression), sizeof (biCompression));
421+ file.write (reinterpret_cast <const uint8_t *>(&biSizeImage), sizeof (biSizeImage));
422+ file.write (reinterpret_cast <const uint8_t *>(&biXPelsPerMeter), sizeof (biXPelsPerMeter));
423+ file.write (reinterpret_cast <const uint8_t *>(&biYPelsPerMeter), sizeof (biYPelsPerMeter));
424+ file.write (reinterpret_cast <const uint8_t *>(&biClrUsed), sizeof (biClrUsed));
425+ file.write (reinterpret_cast <const uint8_t *>(&biClrImportant), sizeof (biClrImportant));
428426
429427 for (int y = 0 ; y < sprite.height (); y++)
430428 {
0 commit comments