Le due verita' della posizione di una foto
Stato: ✅ ATTUATO E PROVATO la sera del 2026-08-26, subito dopo il disegno.
Nasce da un difetto visto a schermo, non da una teoria: vedi sez. 1.
Gli esiti delle prove sono in sez. 6.
1. Il fatto che l'ha fatto nascere
Il 19/08/2026, giornata Campocecina-Pietrabuona. Le 23 foto del giorno:
| ora | cosa | posizione | nome sul cartellino |
| 10:05-10:27 | 16 foto, passeggiata ai prati | messa a mano col 📍 | (niente) |
| 12:42 | 1 foto, pranzo al parcheggio | messa a mano col 📍 | (niente) |
| 14:12-14:52 | 4 foto, Colonnata | dall'EXIF | Colonnata (Carrara), Italia |
| 21:11 | 2 foto, la notte | dall'EXIF | Pietrabuona (Pescia), Italia |
Le foto che abbiamo RADDRIZZATO sono le uniche senza nome del posto. E' il
contrario di quel che dovrebbe succedere.
Perche': il bottone 📍 scrive la posizione vera in
maps/trips/<viaggio>/foto_posizioni.json e azzera fluoghi nel map_points
("il nome lo rifa' il prossimo giro"). Ma il nome lo rifa'
photo_gps.py::aggiungi_luoghi(), che lo pesca da lenostre.foto.localita -
e quella colonna e' stata calcolata sulle coordinate dell'EXIF, cioe' su quelle
sbagliate. Nessuno ha mai detto all'indice che la posizione era cambiata.
Lo stesso difetto, altra forma, chiuso il 26/08 mattina: via_points.py
chiedeva a map_points DI QUALI foto fidarsi e poi rileggeva le coordinate
dall'EXIF per conto suo. Cinque foto gia' corrette rimandavano la strada in val
di Magra. E' la stessa radice: due verita' e nessuna regola su chi comanda.
2. Il timore di vitti, verificato
"avevamo in progetto di cambiare l'indice delle foto, con i nomi e le
coordinate manuali, cosi' se si rilegge l'exif non si perde il lavoro fatto"
Il progetto non era mai stato scritto (c'era solo una riga di promemoria in
bussola). Il timore invece e' fondato, ed e' verificabile in due punti:
wiz_foto/lenostre_index.php:127-129-ln_upsert()fa
ON DUPLICATE KEY UPDATE ... lat=VALUES(lat), lon=VALUES(lon).
Rileggere l'EXIF di una cartella sovrascrive le coordinate. (localita
NON e' in quella lista: per questo i nomi sopravvivono a un import.)
wiz_foto/popola_foto_index.php:25- la rigenerazione totale e' un
DELETE FROM foto. I nomi si ripescano dalla cache subito dopo (riga 35), ma
una coordinata corretta a mano non avrebbe nessuna cache da cui tornare.
Quindi: scrivere la posizione corretta dentro foto.lat sarebbe stato un
autogol. Serve un posto che l'EXIF non tocca.
3. La forma scelta: il file comanda, il DB e' una copia rifacibile
La tentazione e' "spostiamo la verita' nel DB". No. Vale la regola del
25/08: quel che sa un essere umano e il programma no si scrive in un file suo,
che i programmi leggono e non riscrivono mai.
| dove sta | chi la scrive | si puo' perdere? | |
| quel che dice la macchina | foto.lat / foto.lon | exiftool | si', e va bene: si rilegge |
| quel che dicono vitti ed Elena | trips/<v>/foto_posizioni.json | il bottone 📍 | no, comanda |
| la copia comoda | foto.lat_mano / foto.lon_mano | ln_posizioni_fill() | si', e non importa: si rifa' |
| quella che leggono tutti | foto.lat_eff / foto.lon_eff | la calcola il DB | - |
Il punto che tiene su tutto: **il DB non diventa la verita', diventa una copia
rifacibile.** Un DELETE FROM foto non fa danno, perche' i valori veri stanno
nei JSON e si riversano di nuovo. Non e' una seconda verita', e' una cache.
E lat_eff calcolata dal database serve a non ripetere l'errore di
via_points.py: **se la colonna giusta la calcola il DB, nessun lettore puo'
scordarsi di guardarla.**
4. L'ALTER (serve root: lenostre_app non ha ALTER)
ALTER TABLE lenostre.foto ADD COLUMN lat_mano DECIMAL(10,7) NULL AFTER lon, ADD COLUMN lon_mano DECIMAL(10,7) NULL AFTER lat_mano, ADD COLUMN lat_eff DECIMAL(10,7) GENERATED ALWAYS AS (COALESCE(lat_mano, lat)) VIRTUAL, ADD COLUMN lon_eff DECIMAL(10,7) GENERATED ALWAYS AS (COALESCE(lon_mano, lon)) VIRTUAL;
Solo aggiunte, nessuna colonna toccata, nessun dato riscritto: chi legge oggi
continua a leggere come prima. VIRTUAL = non occupa spazio, si calcola alla
lettura.
5. Il codice
5.1 ln_posizioni_fill(PDO $pdo, ?string $trip = null): array (nuova)
In wiz_foto/lenostre_index.php, accanto a ln_localita_fill.
Legge maps/trips/*/foto_posizioni.json (o di un viaggio solo), e per ogni
foto scrive lat_mano/lon_mano. **Dove il valore CAMBIA, azzera anche
localita**, cosi' il giro dopo il nome si rifa' sulla posizione nuova.
Torna ['foto'=>N, 'cambiate'=>N].
5.2 Chi la chiama
- il bottone 📍 (
maps/convalida_foto.php, azioneplace): subito dopo aver
scritto il JSON, per le foto toccate. Cosi' il nome si aggiorna senza aspettare.
wiz_foto/popola_foto_index.php: dopo il re-scan e prima di
ln_localita_fill, se no i nomi rinascono sulle coordinate vecchie.
wiz_foto/geocodifica_foto.php: idem, cosi' l'attrezzo dell'arretrato si
porta dietro anche le correzioni.
5.3 I lettori da spostare su lat_eff/lon_eff
Sono pochi, contati il 26/08:
| file | riga | cosa fa | tocca? |
wiz_foto/lenostre_index.php | 247 | ln_localita_fill: SELECT id, lat, lon | SI', e' il punto |
wiz_foto/geocodifica_foto.php | 25, 33 | i due contatori | si', per coerenza |
wiz_foto/popola_foto_index.php | 39 | contatore "quante col GPS" | si', per coerenza |
lab/platform/lib/vrn_foto.php | 29 | Ricerca foto: restituisce lat, lon | si' |
wiz_foto/gestore_foto.php | 709 | SELECT lat (c'e'/non c'e' il GPS) | si' |
maps/photo_gps.py | 100 | SELECT path, localita | no: non legge coordinate |
ln_upsert() NON si tocca: non nomina le colonne _mano, quindi un import non
puo' portarsele via. E' esattamente la proprieta' che si voleva.
6. Le prove, e come sono andate (26/08 sera)
6.0 La scoperta che ha alzato la posta
Prima di attuare, guardato cosa AVEVA l'indice per le 23 foto del 19/08. Non
erano senza nome: erano col nome SBAGLIATO, calcolato sulle coordinate che il
GPS si era inventato.
| ora | nel map_points si vedeva | ma nell'indice c'era scritto |
| 10:05-10:27 (16 foto) | (niente) | Ponte di Arcola, Castiglione Vara (Beverino), Bedizzano (Carrara) x8, Massa x6, Carrara |
| 12:42 (pranzo) | (niente) | Bedizzano (Carrara) |
Cioe': al primo «Ricostruisci» il cartellino della passeggiata del mattino non
sarebbe rimasto vuoto - avrebbe scritto «Bedizzano», con la faccia di chi sa.
Un nome sbagliato e' peggio di nessun nome. Non era un difetto estetico.
6.1 Esiti
| # | prova | esito |
| 1 | stato di partenza | 0 foto con lat_mano, 28 posizioni nei JSON |
| 2 | ln_posizioni_fill() | lette 28, cambiate 26, tolte 0, ignote 2 |
| 3 | geocodifica_foto.php --tutto | 26 ribattezzate in 4 posti, 8 domande a Nominatim |
| 4 | il 19/08 dopo la cura | 16 foto -> Campocecina (Carrara), il pranzo -> Colonnata (Carrara) al parcheggio |
| 5 | ln_reindex_target sulla cartella (rilegge l'EXIF di 23 foto) | 17 posizioni a mano e 16 nomi intatti |
| 6 | simulato il DELETE FROM foto (azzerate tutte le _mano + localita) | ln_posizioni_fill ne rimette 26, ln_localita_fill ribattezza 26 con 0 domande alla rete |
Le 2 ignote sono due foto del 18/08 che il JSON nomina ancora e che non sono
piu' su disco (cestinate dal Gestore foto). La funzione lo dice e tira dritto.
6.2 Quel che resta da guardare a video
Premere 🔄 Ricostruisci e controllare il cartellino della passeggiata del
mattino: deve dire Campocecina. Stasera non e' stato premuto - il map_points
del viaggio vero non e' stato toccato.
7. Cosa si sistema, oltre al cartellino
- il tooltip del Gestore foto smette di mostrare il posto sbagliato per le
foto raddrizzate (e con lui il tasto 📋 con cui Elena battezza le cartelle);
- la Ricerca foto della piattaforma trova la foto dove sta davvero;
- una foto raddrizzata resta raddrizzata anche fuori dal viaggio in cui
qualcuno l'ha corretta.
8. Quel che questo disegno NON fa
- Non permette di correggere una foto che non sta in nessun viaggio: il
bottone 📍 vive nella pagina di un viaggio. Se un giorno servira', il posto
naturale e' il Gestore foto, e allora servira' un elenco che non sia
per-viaggio. Oggi non serve: non e' un buco, e' un confine.
- Non tocca
foto_a_piedi.json/foto_nascoste.json/foto_giorno.json/
passeggiate.json: quelle sono scelte sul RACCONTO di un viaggio, non fatti
sulla foto. Stanno giuste dove stanno.