mirror of
https://github.com/0015/map_tiles.git
synced 2026-01-17 17:07:00 +01:00
165c2c07c784a3d02912e0acdc1307c0ecfaab00
Map Tiles Component for LVGL 9.x
A comprehensive map tiles component for ESP-IDF projects using LVGL 9.x. This component provides functionality to load and display map tiles with GPS coordinate conversion, designed for embedded applications requiring offline map display capabilities.
Features
- LVGL 9.x Compatible: Fully compatible with LVGL 9.x image handling
- GPS Coordinate Conversion: Convert GPS coordinates to tile coordinates and vice versa
- Dynamic Tile Loading: Load map tiles on demand from file system
- Configurable Grid Size: Support for different grid sizes (3x3, 5x5, 7x7, etc.)
- Multiple Tile Types: Support for up to 8 different tile types (street, satellite, terrain, hybrid, etc.)
- Memory Efficient: Configurable memory allocation (SPIRAM or regular RAM)
- Multiple Zoom Levels: Support for different map zoom levels
- Error Handling: Comprehensive error handling and logging
- C API: Clean C API for easy integration
Requirements
- ESP-IDF 5.0 or later
- LVGL 9.x
- File system support (FAT/SPIFFS/LittleFS)
- Map tiles in binary format (RGB565, 256x256 pixels)
Installation
Using ESP-IDF Component Manager
Add to your project's main/idf_component.yml:
dependencies:
map_tiles:
git: "https://github.com/0015/map_tiles_component.git"
version: "^1.1.0"
Manual Installation
- Copy the
map_tilesfolder to your project'scomponentsdirectory - The component will be automatically included in your build
Usage
Basic Setup
#include "map_tiles.h"
// Configure the map tiles with multiple tile types and custom grid size
const char* tile_folders[] = {"street_map", "satellite", "terrain", "hybrid"};
map_tiles_config_t config = {
.base_path = "/sdcard", // Base path to tile storage
.tile_folders = {tile_folders[0], tile_folders[1], tile_folders[2], tile_folders[3]},
.tile_type_count = 4, // Number of tile types
.default_zoom = 10, // Default zoom level
.use_spiram = true, // Use SPIRAM if available
.default_tile_type = 0, // Start with street map (index 0)
.grid_cols = 5, // Grid width (tiles)
.grid_rows = 5 // Grid height (tiles)
};
// Initialize map tiles
map_tiles_handle_t map_handle = map_tiles_init(&config);
if (!map_handle) {
ESP_LOGE(TAG, "Failed to initialize map tiles");
return;
}
Loading Tiles
// Set center position from GPS coordinates
map_tiles_set_center_from_gps(map_handle, 37.7749, -122.4194); // San Francisco
// Get grid dimensions
int grid_cols, grid_rows;
map_tiles_get_grid_size(map_handle, &grid_cols, &grid_rows);
int tile_count = map_tiles_get_tile_count(map_handle);
// Load tiles for the configured grid size
for (int row = 0; row < grid_rows; row++) {
for (int col = 0; col < grid_cols; col++) {
int index = row * grid_cols + col;
int tile_x, tile_y;
map_tiles_get_position(map_handle, &tile_x, &tile_y);
bool loaded = map_tiles_load_tile(map_handle, index,
tile_x + col, tile_y + row);
if (!loaded) {
ESP_LOGW(TAG, "Failed to load tile %d", index);
}
}
}
Displaying Tiles with LVGL
// Get grid dimensions and tile count
int grid_cols, grid_rows;
map_tiles_get_grid_size(map_handle, &grid_cols, &grid_rows);
int tile_count = map_tiles_get_tile_count(map_handle);
// Create image widgets for each tile
lv_obj_t** tile_images = malloc(tile_count * sizeof(lv_obj_t*));
for (int i = 0; i < tile_count; i++) {
tile_images[i] = lv_image_create(parent_container);
// Get the tile image descriptor
lv_image_dsc_t* img_dsc = map_tiles_get_image(map_handle, i);
if (img_dsc) {
lv_image_set_src(tile_images[i], img_dsc);
// Position the tile in the grid
int row = i / grid_cols;
int col = i % grid_cols;
lv_obj_set_pos(tile_images[i],
col * MAP_TILES_TILE_SIZE,
row * MAP_TILES_TILE_SIZE);
}
}
Switching Tile Types
// Switch to different tile types
map_tiles_set_tile_type(map_handle, 0); // Street map
map_tiles_set_tile_type(map_handle, 1); // Satellite
map_tiles_set_tile_type(map_handle, 2); // Terrain
map_tiles_set_tile_type(map_handle, 3); // Hybrid
// Get current tile type
int current_type = map_tiles_get_tile_type(map_handle);
// Get available tile types
int type_count = map_tiles_get_tile_type_count(map_handle);
for (int i = 0; i < type_count; i++) {
const char* folder = map_tiles_get_tile_type_folder(map_handle, i);
printf("Tile type %d: %s\n", i, folder);
}
GPS Coordinate Conversion
// Convert GPS to tile coordinates
double tile_x, tile_y;
map_tiles_gps_to_tile_xy(map_handle, 37.7749, -122.4194, &tile_x, &tile_y);
// Check if GPS position is within current tile grid
bool within_tiles = map_tiles_is_gps_within_tiles(map_handle, 37.7749, -122.4194);
// Get marker offset for precise positioning
int offset_x, offset_y;
map_tiles_get_marker_offset(map_handle, &offset_x, &offset_y);
Memory Management
// Clean up when done
map_tiles_cleanup(map_handle);
Tile File Format
The component expects map tiles in a specific binary format:
- File Structure:
{base_path}/{map_tile}/{zoom}/{tile_x}/{tile_y}.bin - Format: 12-byte header + raw RGB565 pixel data
- Size: 256x256 pixels
- Color Format: RGB565 (16-bit per pixel)
Example Tile Structure
/sdcard/
├── street_map/ // Tile type 0
│ ├── 10/
│ │ ├── 164/
│ │ │ ├── 395.bin
│ │ │ ├── 396.bin
│ │ │ └── ...
│ │ └── ...
│ └── ...
├── satellite/ // Tile type 1
│ ├── 10/
│ │ ├── 164/
│ │ │ ├── 395.bin
│ │ │ └── ...
│ │ └── ...
│ └── ...
├── terrain/ // Tile type 2
│ └── ...
└── hybrid/ // Tile type 3
└── ...
Configuration Options
| Parameter | Type | Description | Default |
|---|---|---|---|
base_path |
const char* |
Base directory for tile storage | Required |
tile_folders |
const char*[] |
Array of folder names for different tile types | Required |
tile_type_count |
int |
Number of tile types (max 8) | Required |
default_zoom |
int |
Initial zoom level | Required |
use_spiram |
bool |
Use SPIRAM for tile buffers | false |
default_tile_type |
int |
Initial tile type index | Required |
grid_cols |
int |
Number of tile columns (max 10) | 5 |
grid_rows |
int |
Number of tile rows (max 10) | 5 |
API Reference
Initialization
map_tiles_init()- Initialize map tiles systemmap_tiles_cleanup()- Clean up resources
Tile Management
map_tiles_load_tile()- Load a specific tilemap_tiles_get_image()- Get LVGL image descriptormap_tiles_get_buffer()- Get raw tile buffer
Grid Management
map_tiles_get_grid_size()- Get current grid dimensionsmap_tiles_get_tile_count()- Get total number of tiles in grid
Coordinate Conversion
map_tiles_gps_to_tile_xy()- Convert GPS to tile coordinatesmap_tiles_set_center_from_gps()- Set center from GPSmap_tiles_is_gps_within_tiles()- Check if GPS is within current tiles
Position Management
map_tiles_get_position()- Get current tile positionmap_tiles_set_position()- Set tile positionmap_tiles_get_marker_offset()- Get marker offsetmap_tiles_set_marker_offset()- Set marker offset
Tile Type Management
map_tiles_set_tile_type()- Set active tile typemap_tiles_get_tile_type()- Get current tile typemap_tiles_get_tile_type_count()- Get number of available typesmap_tiles_get_tile_type_folder()- Get folder name for a type
Zoom Control
map_tiles_set_zoom()- Set zoom levelmap_tiles_get_zoom()- Get current zoom level
Error Handling
map_tiles_set_loading_error()- Set error statemap_tiles_has_loading_error()- Check error state
Performance Considerations
- Memory Usage: Each tile uses ~128KB (256×256×2 bytes)
- Grid Size: Larger grids use more memory (3x3=9 tiles, 5x5=25 tiles, 7x7=49 tiles)
- SPIRAM: Recommended for ESP32-S3 with PSRAM for better performance
- File System: Ensure adequate file system performance for tile loading
- Tile Caching: Component maintains tile buffers until cleanup
Example Projects
See the examples directory for complete implementation examples:
- Basic map display
- GPS tracking with map updates
- Interactive map with touch controls
License
This component is released under the MIT License. See LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
Support
For questions and support, please open an issue on the GitHub repository.
Description
Languages
C++
53.2%
C
27.7%
Python
18.6%
CMake
0.5%