149 lines
8.2 KiB
Markdown
149 lines
8.2 KiB
Markdown
Ecco il piano operativo completo per il refactoring e la creazione del modulo `python-map-manager`. Questo documento è strutturato per essere inserito direttamente nella documentazione tecnica del progetto.
|
|
|
|
---
|
|
|
|
# Piano Operativo: Refactoring e Creazione Modulo `python-map-manager`
|
|
|
|
## 1. Obiettivo del Refactoring
|
|
|
|
L'obiettivo primario è disaccoppiare la logica di gestione, recupero e visualizzazione delle mappe geografiche (attualmente integrata nell'applicazione `geoelevation`) per creare un componente software autonomo, riutilizzabile e manutenibile separatamente.
|
|
|
|
Questo nuovo componente sarà gestito come **Git Submodule** e denominato **`python-map-manager`**.
|
|
|
|
### Obiettivi Specifici
|
|
1. **Indipendenza**: Il modulo non deve avere dipendenze dalla logica di business dell'applicazione ospite (es. non deve conoscere `ElevationManager`).
|
|
2. **Modularità**: Separazione netta tra logica di elaborazione (`Engine`) e logica di visualizzazione (`Visualizer`).
|
|
3. **Testabilità**: Inclusione di un tool di debug integrato (`debug_tool.py`) per lo sviluppo e il test isolato delle funzionalità.
|
|
4. **Interfaccia Chiara**: Esposizione di API semplici per richiedere immagini di mappe basate su aree, punti o raggi.
|
|
|
|
---
|
|
|
|
## 2. Architettura del Nuovo Modulo
|
|
|
|
Il modulo `python-map-manager` esporrà due componenti principali:
|
|
|
|
### A. `MapEngine` (Logica Backend)
|
|
È il cervello del modulo. Non ha interfaccia grafica.
|
|
* **Responsabilità**:
|
|
* Gestione dei provider di mappe (es. OpenStreetMap).
|
|
* Gestione della cache su disco (download, salvataggio, recupero).
|
|
* Calcoli matematici (conversioni coordinate Geo <-> Pixel, calcolo Bounding Box).
|
|
* Stitching (unione) delle tile per formare un'unica immagine PIL.
|
|
* **Funzionalità Chiave**:
|
|
* `get_image_for_area(bbox, max_size)`: Restituisce un'immagine ottimizzata per coprire un'area.
|
|
* `get_image_for_point(lat, lon, zoom, size)`: Restituisce un'immagine centrata su un punto.
|
|
|
|
### B. `MapVisualizer` (Interfaccia Frontend - Opzionale)
|
|
È il componente di visualizzazione interattiva (basato su OpenCV).
|
|
* **Responsabilità**:
|
|
* Apertura e gestione della finestra grafica.
|
|
* Gestione dell'input utente (Mouse, Zoom, Pan).
|
|
* Rendering dell'immagine fornita dall'`Engine`.
|
|
* **Disaccoppiamento**:
|
|
* Invece di chiamare funzioni esterne, il Visualizer emette **Eventi** (tramite callback) quando l'utente interagisce (es. `on_map_click`, `on_area_selected`). L'applicazione ospite si sottoscrive a questi eventi.
|
|
|
|
---
|
|
|
|
## 3. Struttura del Repository `python-map-manager`
|
|
|
|
```text
|
|
python-map-manager/
|
|
├── map_manager/ # Package Python principale
|
|
│ ├── __init__.py # Espone MapEngine e MapVisualizer
|
|
│ ├── engine.py # Classe MapEngine (Facade logica)
|
|
│ ├── visualizer.py # Classe MapVisualizer (Gestione Window/OpenCV)
|
|
│ ├── tile_manager.py # Gestione download e cache (ex map_manager.py)
|
|
│ ├── services.py # Definizioni Provider Mappe (ex map_services.py)
|
|
│ ├── utils.py # Calcoli geografici puri (ex map_utils.py)
|
|
│ └── drawing.py # Funzioni di disegno su PIL (ex map_drawing.py)
|
|
├── debug_tool.py # Tool CLI/GUI per testare il modulo isolatamente
|
|
├── requirements.txt # Dipendenze (requests, Pillow, opencv-python, mercantile, pyproj)
|
|
└── README.md # Documentazione API
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Fasi di Implementazione
|
|
|
|
### Fase 1: Setup dell'Ambiente e Migrazione File "Puri"
|
|
In questa fase si crea la struttura base e si migrano le librerie di utilità che non richiedono refactoring logico.
|
|
|
|
1. Creare la cartella `python-map-manager` e inizializzare git.
|
|
2. Creare la struttura cartelle `map_manager/`.
|
|
3. **Migrazione Diretta**:
|
|
* Copiare `geoelevation/map_viewer/map_services.py` -> `map_manager/services.py`.
|
|
* Copiare `geoelevation/map_viewer/map_utils.py` -> `map_manager/utils.py`.
|
|
* Copiare `geoelevation/map_viewer/map_drawing.py` -> `map_manager/drawing.py`.
|
|
* Copiare `geoelevation/map_viewer/map_manager.py` -> `map_manager/tile_manager.py` (Rinominato per chiarezza).
|
|
4. **Normalizzazione Import**: Aggiornare gli import interni ai file copiati per puntare ai nuovi percorsi relativi (es. `from .services import ...` invece di `from .map_services import ...`).
|
|
|
|
### Fase 2: Implementazione di `MapEngine` (`engine.py`)
|
|
In questa fase si astrae la logica di calcolo e recupero immagini.
|
|
|
|
1. Creare `map_manager/engine.py`.
|
|
2. Definire la classe `MapEngine`.
|
|
3. Implementare il metodo `__init__` per configurare il `MapTileManager` e la cache.
|
|
4. Implementare `get_image_for_area`:
|
|
* Deve accettare coordinate `(min_lat, min_lon, max_lat, max_lon)`.
|
|
* Deve usare `utils.py` per calcolare lo zoom ottimale in base alle dimensioni pixel richieste.
|
|
* Deve chiamare `tile_manager.stitch_map_image`.
|
|
5. Implementare `get_image_for_point`:
|
|
* Accetta centro e livello di zoom.
|
|
* Calcola il Bounding Box necessario usando `utils.py`.
|
|
* Richiede lo stitching.
|
|
|
|
### Fase 3: Implementazione di `MapVisualizer` (`visualizer.py`)
|
|
In questa fase si crea il gestore della finestra, rimuovendo ogni logica di business specifica di `geoelevation`.
|
|
|
|
1. Creare `map_manager/visualizer.py`.
|
|
2. Definire la classe `MapVisualizer` che accetta un'istanza di `MapEngine`.
|
|
3. Estrarre la logica OpenCV da `geo_map_viewer.py` e `map_display.py`.
|
|
4. Implementare il loop di gestione eventi mouse (`cv2.setMouseCallback`).
|
|
5. **Refactoring Eventi**:
|
|
* Definire una proprietà `callback_on_click` (funzione che accetta lat, lon).
|
|
* Quando avviene un click, usare `engine` o `utils` per convertire Pixel -> Lat/Lon.
|
|
* Invocare `self.callback_on_click(lat, lon)` invece di chiamare `elevation_manager`.
|
|
|
|
### Fase 4: Creazione del `debug_tool.py`
|
|
Uno strumento essenziale per garantire che il modulo funzioni "out of the box".
|
|
|
|
1. Creare `debug_tool.py` nella root del repository.
|
|
2. Lo script deve:
|
|
* Istanziare `MapEngine` (con una cache temporanea o di debug).
|
|
* Istanziare `MapVisualizer`.
|
|
* Definire una funzione dummy: `def on_click(lat, lon): print(f"Clicked: {lat}, {lon}")`.
|
|
* Collegare la funzione al visualizzatore.
|
|
* Avviare la mappa su coordinate di default (es. Roma).
|
|
3. Questo tool servirà per verificare lo zoom, il pan e la correttezza del download delle tile.
|
|
|
|
### Fase 5: Integrazione nell'Applicazione Principale
|
|
Una volta che il submodule è stabile e pushato sul repository remoto.
|
|
|
|
1. In `geoelevation`, rimuovere la cartella `map_viewer` esistente.
|
|
2. Aggiungere il submodule:
|
|
```bash
|
|
git submodule add -b master <URL_REPO> external/python-map-manager
|
|
```
|
|
3. Configurare i path in `geoelevation/__init__.py` (o file di setup path dedicato) per includere il submodule.
|
|
4. Modificare `geoelevation/process_targets.py` (o dove risiede il processo mappa):
|
|
* Importare `MapEngine` e `MapVisualizer` dal submodule.
|
|
* Nel processo dedicato alla mappa, definire la funzione di callback reale che interroga `ElevationManager`.
|
|
* Passare questa callback al `MapVisualizer`.
|
|
|
|
---
|
|
|
|
## 5. Specifiche Tecniche e Standard
|
|
|
|
* **PEP8**: Tutto il codice deve seguire rigorosamente lo standard PEP8.
|
|
* **Type Hinting**: Ogni funzione deve avere le annotazioni di tipo (`-> Optional[Image.Image]`, ecc.).
|
|
* **Docstrings**: Ogni classe e metodo pubblico deve avere docstring in Inglese.
|
|
* **Dipendenze**:
|
|
* Non usare `try-except ImportError` per nascondere dipendenze mancanti all'interno del modulo. Se `MapVisualizer` richiede OpenCV, l'import deve fallire esplicitamente se manca, o essere gestito a livello di `__init__.py` per esporre le funzionalità disponibili.
|
|
* Il file `requirements.txt` deve elencare le versioni minime testate.
|
|
|
|
## 6. Risultato Atteso
|
|
|
|
Al termine di questo processo, avremo:
|
|
1. Un repository `python-map-manager` autonomo.
|
|
2. La possibilità di sviluppare e migliorare la gestione mappe lanciando solo `python debug_tool.py`.
|
|
3. L'applicazione `geoelevation` più leggera, che delega tutta la complessità cartografica al modulo esterno, mantenendo solo la logica di "cosa fare quando l'utente clicca un punto" (ovvero chiedere l'elevazione). |