@@ -87,26 +87,26 @@ void OpenStreetMap::computeRequiredTiles(double longitude, double latitude, uint
87
87
const int32_t targetTileY = static_cast <int32_t >(exactTileY);
88
88
89
89
// Compute the offset inside the tile for the given coordinates
90
- const int16_t targetOffsetX = (exactTileX - targetTileX) * OSM_TILESIZE ;
91
- const int16_t targetOffsetY = (exactTileY - targetTileY) * OSM_TILESIZE ;
90
+ const int16_t targetOffsetX = (exactTileX - targetTileX) * currentProvider-> tileSize ;
91
+ const int16_t targetOffsetY = (exactTileY - targetTileY) * currentProvider-> tileSize ;
92
92
93
93
// Compute the offset for tiles covering the map area to keep the location centered
94
94
const int16_t tilesOffsetX = mapWidth / 2 - targetOffsetX;
95
95
const int16_t tilesOffsetY = mapHeight / 2 - targetOffsetY;
96
96
97
97
// Compute number of colums required
98
- const float colsLeft = 1.0 * tilesOffsetX / OSM_TILESIZE ;
99
- const float colsRight = float (mapWidth - (tilesOffsetX + OSM_TILESIZE )) / OSM_TILESIZE ;
98
+ const float colsLeft = 1.0 * tilesOffsetX / currentProvider-> tileSize ;
99
+ const float colsRight = float (mapWidth - (tilesOffsetX + currentProvider-> tileSize )) / currentProvider-> tileSize ;
100
100
numberOfColums = ceil (colsLeft) + 1 + ceil (colsRight);
101
101
102
- startOffsetX = tilesOffsetX - (ceil (colsLeft) * OSM_TILESIZE );
102
+ startOffsetX = tilesOffsetX - (ceil (colsLeft) * currentProvider-> tileSize );
103
103
104
104
// Compute number of rows required
105
- const float rowsTop = 1.0 * tilesOffsetY / OSM_TILESIZE ;
106
- const float rowsBottom = float (mapHeight - (tilesOffsetY + OSM_TILESIZE )) / OSM_TILESIZE ;
105
+ const float rowsTop = 1.0 * tilesOffsetY / currentProvider-> tileSize ;
106
+ const float rowsBottom = float (mapHeight - (tilesOffsetY + currentProvider-> tileSize )) / currentProvider-> tileSize ;
107
107
const uint32_t numberOfRows = ceil (rowsTop) + 1 + ceil (rowsBottom);
108
108
109
- startOffsetY = tilesOffsetY - (ceil (rowsTop) * OSM_TILESIZE );
109
+ startOffsetY = tilesOffsetY - (ceil (rowsTop) * currentProvider-> tileSize );
110
110
111
111
log_v (" Need %i * %i tiles. First tile offset is %d,%d" ,
112
112
numberOfColums, numberOfRows, startOffsetX, startOffsetY);
@@ -171,17 +171,11 @@ bool OpenStreetMap::isTileCachedOrBusy(uint32_t x, uint32_t y, uint8_t z)
171
171
172
172
void OpenStreetMap::freeTilesCache ()
173
173
{
174
- for (auto &tile : tilesCache)
175
- tile.free ();
176
-
177
- tilesCache.clear ();
174
+ std::vector<CachedTile>().swap (tilesCache);
178
175
}
179
176
180
177
bool OpenStreetMap::resizeTilesCache (uint16_t numberOfTiles)
181
178
{
182
- if (tilesCache.size () == numberOfTiles)
183
- return true ;
184
-
185
179
if (!numberOfTiles)
186
180
{
187
181
log_e (" Invalid cache size: %d" , numberOfTiles);
@@ -193,7 +187,7 @@ bool OpenStreetMap::resizeTilesCache(uint16_t numberOfTiles)
193
187
194
188
for (auto &tile : tilesCache)
195
189
{
196
- if (!tile.allocate ())
190
+ if (!tile.allocate (currentProvider-> tileSize ))
197
191
{
198
192
log_e (" Tile cache allocation failed!" );
199
193
freeTilesCache ();
@@ -211,7 +205,7 @@ void OpenStreetMap::updateCache(const tileList &requiredTiles, uint8_t zoom)
211
205
if (!jobs.empty ())
212
206
{
213
207
runJobs (jobs);
214
- log_i (" Updated %i tiles in %lu ms - %i ms/tile" , jobs.size (), millis () - startMS, (millis () - startMS) / jobs.size ());
208
+ log_d (" Updated %i tiles in %lu ms - %i ms/tile" , jobs.size (), millis () - startMS, (millis () - startMS) / jobs.size ());
215
209
}
216
210
}
217
211
@@ -270,8 +264,8 @@ bool OpenStreetMap::composeMap(LGFX_Sprite &mapSprite, const tileList &requiredT
270
264
continue ;
271
265
}
272
266
273
- int drawX = startOffsetX + (tileIndex % numberOfColums) * OSM_TILESIZE ;
274
- int drawY = startOffsetY + (tileIndex / numberOfColums) * OSM_TILESIZE ;
267
+ int drawX = startOffsetX + (tileIndex % numberOfColums) * currentProvider-> tileSize ;
268
+ int drawY = startOffsetY + (tileIndex / numberOfColums) * currentProvider-> tileSize ;
275
269
276
270
auto it = std::find_if (tilesCache.begin (), tilesCache.end (),
277
271
[&](const CachedTile &tile)
@@ -280,7 +274,7 @@ bool OpenStreetMap::composeMap(LGFX_Sprite &mapSprite, const tileList &requiredT
280
274
});
281
275
282
276
if (it != tilesCache.end ())
283
- mapSprite.pushImage (drawX, drawY, OSM_TILESIZE, OSM_TILESIZE , it->buffer );
277
+ mapSprite.pushImage (drawX, drawY, currentProvider-> tileSize , currentProvider-> tileSize , it->buffer );
284
278
else
285
279
log_w (" Tile (z=%d, x=%d, y=%d) not found in cache" , zoom, tileX, tileY);
286
280
@@ -293,8 +287,8 @@ bool OpenStreetMap::composeMap(LGFX_Sprite &mapSprite, const tileList &requiredT
293
287
mapSprite.setTextColor (TFT_WHITE, TFT_BLACK);
294
288
else
295
289
mapSprite.setTextColor (TFT_BLACK);
296
- mapSprite.drawRightString (" Map data from OpenStreetMap.org " ,
297
- mapSprite.width (), mapSprite.height () - 10 , &DejaVu9 );
290
+ mapSprite.drawRightString (currentProvider-> attribution ,
291
+ mapSprite.width (), mapSprite.height () - 10 , &DejaVu9Modded );
298
292
mapSprite.setTextColor (TFT_WHITE, TFT_BLACK);
299
293
300
294
return true ;
@@ -308,7 +302,7 @@ bool OpenStreetMap::fetchMap(LGFX_Sprite &mapSprite, double longitude, double la
308
302
return false ;
309
303
}
310
304
311
- if (! zoom || zoom > OSM_MAX_ZOOM )
305
+ if (zoom < currentProvider-> minZoom || zoom > currentProvider-> maxZoom )
312
306
{
313
307
log_e (" Invalid zoom level: %d" , zoom);
314
308
return false ;
@@ -320,14 +314,10 @@ bool OpenStreetMap::fetchMap(LGFX_Sprite &mapSprite, double longitude, double la
320
314
return false ;
321
315
}
322
316
323
- if (!tilesCache.capacity ())
317
+ if (!tilesCache.capacity () && ! resizeTilesCache ( tilesNeeded (mapWidth, mapHeight)) )
324
318
{
325
- log_w (" Cache not initialized, setting up a default cache..." );
326
- if (!resizeTilesCache (OSM_DEFAULT_CACHE_ITEMS))
327
- {
328
- log_e (" Could not allocate tile cache" );
329
- return false ;
330
- }
319
+ log_e (" Could not allocate tile cache" );
320
+ return false ;
331
321
}
332
322
333
323
longitude = fmod (longitude + 180.0 , 360.0 ) - 180.0 ;
@@ -366,7 +356,7 @@ bool OpenStreetMap::fillBuffer(WiFiClient *stream, MemoryBuffer &buffer, size_t
366
356
result = " Timeout: " + String (OSM_TILE_TIMEOUT_MS) + " ms" ;
367
357
return false ;
368
358
}
369
- vTaskDelay ( pdMS_TO_TICKS ( 1 ) );
359
+ taskYIELD ( );
370
360
continue ;
371
361
}
372
362
@@ -382,7 +372,7 @@ bool OpenStreetMap::fillBuffer(WiFiClient *stream, MemoryBuffer &buffer, size_t
382
372
lastReadTime = millis ();
383
373
}
384
374
else
385
- vTaskDelay ( pdMS_TO_TICKS ( 1 ) );
375
+ taskYIELD ( );
386
376
}
387
377
return true ;
388
378
}
@@ -432,22 +422,25 @@ std::optional<std::unique_ptr<MemoryBuffer>> OpenStreetMap::urlToBuffer(const ch
432
422
433
423
void OpenStreetMap::PNGDraw (PNGDRAW *pDraw)
434
424
{
435
- uint16_t *destRow = currentInstance->currentTileBuffer + (pDraw->y * OSM_TILESIZE );
425
+ uint16_t *destRow = currentInstance->currentTileBuffer + (pDraw->y * currentInstance-> currentProvider -> tileSize );
436
426
getPNGCurrentCore ()->getLineAsRGB565 (pDraw, destRow, PNG_RGB565_BIG_ENDIAN, 0xffffffff );
437
427
}
438
428
439
429
bool OpenStreetMap::fetchTile (CachedTile &tile, uint32_t x, uint32_t y, uint8_t zoom, String &result)
440
430
{
441
- char url[64 ];
442
- snprintf (url, sizeof (url), " https://tile.openstreetmap.org/%u/%u/%u.png" ,
443
- static_cast <unsigned int >(zoom),
444
- static_cast <unsigned int >(x),
445
- static_cast <unsigned int >(y));
446
-
447
- const auto buffer = urlToBuffer (url, result);
431
+ String url = currentProvider->urlTemplate ;
432
+ url.replace (" {x}" , String (x));
433
+ url.replace (" {y}" , String (y));
434
+ url.replace (" {z}" , String (zoom));
435
+ if (currentProvider->requiresApiKey && strstr (url.c_str (), " {apiKey}" ))
436
+ url.replace (" {apiKey}" , currentProvider->apiKey );
437
+
438
+ const auto buffer = urlToBuffer (url.c_str (), result);
448
439
if (!buffer)
449
440
return false ;
450
441
442
+ url.clear ();
443
+
451
444
PNG *png = getPNGCurrentCore ();
452
445
const int16_t rc = png->openRAM (buffer.value ()->get (), buffer.value ()->size (), PNGDraw);
453
446
if (rc != PNG_SUCCESS)
@@ -456,7 +449,7 @@ bool OpenStreetMap::fetchTile(CachedTile &tile, uint32_t x, uint32_t y, uint8_t
456
449
return false ;
457
450
}
458
451
459
- if (png->getWidth () != OSM_TILESIZE || png->getHeight () != OSM_TILESIZE )
452
+ if (png->getWidth () != currentProvider-> tileSize || png->getHeight () != currentProvider-> tileSize )
460
453
{
461
454
result = " Unexpected tile size: w=" + String (png->getWidth ()) + " h=" + String (png->getHeight ());
462
455
return false ;
@@ -468,7 +461,7 @@ bool OpenStreetMap::fetchTile(CachedTile &tile, uint32_t x, uint32_t y, uint8_t
468
461
const int decodeResult = png->decode (0 , PNG_FAST_PALETTE);
469
462
if (decodeResult != PNG_SUCCESS)
470
463
{
471
- result = " Decoding " + String ( url) + " failed with code: " + String (decodeResult);
464
+ result = " Decoding " + url + " failed with code: " + String (decodeResult);
472
465
tile.valid = false ;
473
466
return false ;
474
467
}
@@ -550,3 +543,25 @@ bool OpenStreetMap::startTileWorkerTasks()
550
543
log_i (" Started %d tile worker task(s)" , numberOfWorkers);
551
544
return true ;
552
545
}
546
+
547
+ uint16_t OpenStreetMap::tilesNeeded (uint16_t mapWidth, uint16_t mapHeight)
548
+ {
549
+ const int tileSize = currentProvider->tileSize ;
550
+ int tilesX = (mapWidth + tileSize - 1 ) / tileSize + 1 ;
551
+ int tilesY = (mapHeight + tileSize - 1 ) / tileSize + 1 ;
552
+ return tilesX * tilesY;
553
+ }
554
+
555
+ bool OpenStreetMap::setTileProvider (int index)
556
+ {
557
+ if (index < 0 || index >= OSM_TILEPROVIDERS)
558
+ {
559
+ log_e (" invalid provider index" );
560
+ return false ;
561
+ }
562
+
563
+ currentProvider = &tileProviders[index];
564
+ freeTilesCache ();
565
+ log_i (" provider changed to '%s'" , currentProvider->name );
566
+ return true ;
567
+ }
0 commit comments