mirror of
https://github.com/0015/map_tiles.git
synced 2026-01-17 17:07:00 +01:00
292 lines
9.8 KiB
Markdown
Executable File
292 lines
9.8 KiB
Markdown
Executable File
# 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.3
|
||
- File system support (FAT/SPIFFS/LittleFS)
|
||
- Map tiles in binary format (RGB565, 256x256 pixels)
|
||
|
||
## Installation
|
||
|
||
### Using ESP-IDF Component Manager
|
||
|
||
You can easily add this component to your project using the idf.py command or by manually updating your idf_component.yml file.
|
||
|
||
#### Option 1: Using the idf.py add-dependency command (Recommended)
|
||
From your project's root directory, simply run the following command in your terminal:
|
||
|
||
```bash
|
||
idf.py add-dependency "0015/map_tiles^1.2.0"
|
||
```
|
||
|
||
This command will automatically add the component to your idf_component.yml file and download the required files the next time you build your project.
|
||
|
||
#### Option 2: Manual idf_component.yml update
|
||
Add to your project's `main/idf_component.yml`:
|
||
|
||
```yaml
|
||
dependencies:
|
||
map_tiles:
|
||
git: "https://github.com/0015/map_tiles.git"
|
||
version: "^1.2.0"
|
||
```
|
||
|
||
### Manual Installation
|
||
|
||
1. Copy the `map_tiles` folder to your project's `components` directory
|
||
2. The component will be automatically included in your build
|
||
|
||
## Usage
|
||
|
||
### Basic Setup
|
||
|
||
```c
|
||
#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
|
||
|
||
```c
|
||
// 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
|
||
|
||
```c
|
||
// 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
|
||
|
||
```c
|
||
// 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
|
||
|
||
```c
|
||
// 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
|
||
|
||
```c
|
||
// 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 system
|
||
- `map_tiles_cleanup()` - Clean up resources
|
||
|
||
### Tile Management
|
||
- `map_tiles_load_tile()` - Load a specific tile
|
||
- `map_tiles_get_image()` - Get LVGL image descriptor
|
||
- `map_tiles_get_buffer()` - Get raw tile buffer
|
||
|
||
### Grid Management
|
||
- `map_tiles_get_grid_size()` - Get current grid dimensions
|
||
- `map_tiles_get_tile_count()` - Get total number of tiles in grid
|
||
|
||
### Coordinate Conversion
|
||
- `map_tiles_gps_to_tile_xy()` - Convert GPS to tile coordinates
|
||
- `map_tiles_set_center_from_gps()` - Set center from GPS
|
||
- `map_tiles_is_gps_within_tiles()` - Check if GPS is within current tiles
|
||
|
||
### Position Management
|
||
- `map_tiles_get_position()` - Get current tile position
|
||
- `map_tiles_set_position()` - Set tile position
|
||
- `map_tiles_get_marker_offset()` - Get marker offset
|
||
- `map_tiles_set_marker_offset()` - Set marker offset
|
||
|
||
### Tile Type Management
|
||
- `map_tiles_set_tile_type()` - Set active tile type
|
||
- `map_tiles_get_tile_type()` - Get current tile type
|
||
- `map_tiles_get_tile_type_count()` - Get number of available types
|
||
- `map_tiles_get_tile_type_folder()` - Get folder name for a type
|
||
|
||
### Zoom Control
|
||
- `map_tiles_set_zoom()` - Set zoom level
|
||
- `map_tiles_get_zoom()` - Get current zoom level
|
||
|
||
### Error Handling
|
||
- `map_tiles_set_loading_error()` - Set error state
|
||
- `map_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.
|