Files
termanager2/config/piantine.php
Francesco Picone 9c37c1ad7b Piantine staccate dai territori, editor a schermo intero, restyle
Le piantine non dipendono piu' da un territorio esistente: territorio_id e'
nullable, la chiave esterna e' nullOnDelete invece di cascadeOnDelete, e `nome`
fa da etichetta finche' il collegamento manca. Si disegna guardando le strade e
si decide dopo di chi e' il disegno; se il territorio non c'e', lo si crea
dall'editor con numero, zona, tipologia e confini — zona e tipologia comprese,
create sul posto quando mancano.

Il cambio di cascata chiude anche una perdita di dati silenziosa: ogni import
XML svuota `territori` in blocco e finora si portava via tutte le piantine.

Il disegno passa su /piantine/editor, a schermo intero con telaio proprio: su
una mappa larga un terzo di schermo un confine si sbaglia, e finisce stampato.
/piantine resta la gestione — area, generazione, collegamenti, storico.

Cartolina S-12 reimpaginata: pagina 1 il modulo con la Localita' (che ora e' il
nome della zona, non un campo duplicato) e i confini scritti nello spazio
centrale, con il corpo del testo che si adatta alla lunghezza; pagina 2 la
piantina sola al 98%. Aggiunta l'anteprima, che compone il PDF al volo senza
toccare pdf_path ne' lo storico.

Immagine: JPEG invece di PNG (0,9 MB contro 5 per territorio), composta alle
tessere dello zoom piu' alto e ridotta con Lanczos, nelle proporzioni della
pagina cosi' riempie il foglio invece di lasciare fasce bianche. Il tratto del
confine e' espresso in pixel dell'immagine finale: si vede il confine e si legge
la via che ci passa sotto. L'attribuzione OSM si dimensiona con l'immagine,
come la ODbL richiede.

Rimossa la rigenerazione massiva: job, stato in cache e interfaccia.

Sistema visivo ripassato su tutta l'applicazione: le scale gray e indigo di
Tailwind sono ridefinite nei token, cosi' le 37 viste si riallineano insieme
invece di essere riscritte una per una. Grigi caldi, un accento solo con quattro
significati, carattere servito dall'applicazione e non da Google Fonts, via il
gradiente della testata. Aggiunto il link "salta al contenuto", che mancava.

Corretto un guasto d'ambiente che bloccava TUTTI gli upload in sviluppo: dalla
1.26 il fastcgi_params di nginx passa HTTP_HOST come $host, che perde la porta,
e ogni URL firmato smetteva di validare — l'endpoint di upload di Livewire
rispondeva 401.

294 test verdi.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 16:41:22 +02:00

60 lines
2.7 KiB
PHP

<?php
// Sotto-app "Piantine": generazione di mappe ad alta definizione per i PDF
// dei territori. Il rendering vero e proprio avviene nel container
// `map-renderer` (vedi docker/renderer/), raggiunto via HTTP sulla rete
// interna del compose: l'indirizzo predefinito funziona senza variabili
// d'ambiente aggiuntive.
return [
'renderer_url' => env('MAP_RENDERER_URL', 'http://map-renderer:3000'),
// Secondi concessi a un singolo rendering: comprende il download delle
// tessere OSM non ancora in cache, che alla prima generazione può
// richiedere qualche decina di secondi.
//
// Sta sotto `max_execution_time` (120s) di proposito: la generazione parte
// da una richiesta web, e un limite piu' alto verrebbe comunque tagliato da
// PHP con un errore fatale invece che dal messaggio gestito.
'renderer_timeout' => (int) env('MAP_RENDERER_TIMEOUT', 110),
// Lato massimo (px) dell'immagine generata.
//
// Il numero non e' arbitrario: la piantina finisce su una pagina S-12, che
// e' una cartolina da 146 x 94,4 mm, e ne occupa il 98%. A 600 dpi — il
// massimo che una stampante da ufficio sfrutti davvero — il lato lungo e'
// 143 mm / 25,4 * 600 = 3378 px. Oltre, i pixel finiscono nel file senza
// arrivare sulla carta.
'max_side' => 3400,
// Margine di contesto attorno al confine, in frazione del lato maggiore.
'margin_ratio' => 0.15,
// Proporzioni dell'immagine: quelle della pagina S-12 (146 / 94,4 mm).
//
// Senza, un territorio quasi quadrato stampato su una pagina orizzontale
// lascerebbe due fasce bianche larghe un quinto di foglio. Chiedendole al
// renderer, l'immagine nasce gia' della forma giusta e riempie la pagina
// mostrando piu' dintorni invece di carta vuota.
'aspetto' => 146 / 94.4,
// Spessore del confine, in pixel dell'immagine finale.
//
// Deve dire dove passa il confine senza cancellare la via che ci corre
// sotto: chi percorre il territorio quella via la deve leggere. Su 3400 px
// stampati su 146 mm, 3 px sono circa un decimo di millimetro — un segno
// netto e sottile. Semitrasparente per lo stesso motivo.
'tratto' => 3,
'tratto_opacita' => 0.85,
// Formato dell'immagine.
//
// JPEG e non PNG: una mappa e' un'immagine fotografica (migliaia di tinte
// fra edifici, verde e strade) e il PNG, che non perde niente, la porta a
// 4-6 MB per territorio — con 274 territori sono diversi GB di volume, e
// ogni PDF diventa lento da aprire. A qualita' 86 i nomi delle strade
// restano leggibili e il file scende sotto il megabyte.
'formato' => env('MAP_RENDERER_FORMATO', 'jpeg'),
'qualita' => (int) env('MAP_RENDERER_QUALITA', 86),
];