QGIS: DIMMI DOVE TI TROVI E TI ETICHETTO BENE!!! ;-)

Nella mailing list del gruppo utenti italiani QGIS è apparso un quesito molto interessante, ecco un un estratto:

…[Ho generato un Atlante di 130 pagine in formato A3 di un territorio molto vasto e nel quale è riportato un layer di punti (all’incirca 350 punti) disseminati variamente su tutto questo territorio.Per il 99% va tutto bene. In alcune tavole dell’Atlante però, capita che alcuni punti vadano a cadere proprio in adiacenza del bordo della tavola (alias, in adiacenza del bordo del rettangolo del layer di copertura dell’Atlante).

Ora, il punto, ovviamente, a stampa si vede e viene stampato ma l’etichetta associata a questi punti (si tratta, in tutto di 4 punti su oltre 350), poichè è spostata di qualche millimetro rispetto al punto, non si vede perchè va fuori campo di stampa, cioè capita fuori l’area del rettangolo del layer di copertura dell’Atlante che in quel momento sta andando a stampa.

Esiste un comando “forzatura” per imporre al compositore di stampe di far sempre, comunque e in ogni caso far ricadere entro la tavola tutte le etichette associate ai punti ricadenti nella tavola?] …

Ho prospettato due soluzioni: una molto rapida, ma in certe condizioni potrebbe non essere utilizzata per problemi legati alla scala di rappresentazione; una seconda molto più complessa ma che risolve del tutto il problema nel caso di vettore di copertura rettangolare (nel caso generico NON ho avuto il tempo di testarlo!!!).

Non avendo i dati a disposizione, uso dei dati fittizi ma utili allo scopo:

  • vettore di punti (pti_pill);
  • vettore reticolo poligonale che ricopre i punti (reticolo);
N2
dati fittizi – punti e reticolo poligonale

Vediamo un dettaglio del problema:

N5
Atlas – feature corrente

Come si vede alcune etichette NON sono visibili o tranciate!.

Prima soluzione:

La prima soluzione si basa su una semplice tematizzazione dei punti tramite una regola; tale regola fa si che si vedano solo i punti ricadenti nel vettore di copertura corrente:

N6
regola

assieme alla regola occorre attivare ‘il margine attorno all’elemento‘ :

N7
Atlas – prima soluzione

questa soluzione va bene se non si hanno restrizioni sulla scala di rappresentazione.

Seconda soluzione:

In questo caso creeremo una espressione che legga la posizione del punto rispetto al rettangolo e se troppo vicino ai bordi (definito tramite una variabile @dist_bordo) deve cambiare il quadrante (TLS,BSR ecc..) di posizionamento dell’etichetta; i casi possibili sono 4: sopra, sotto, destra o sinistra.


CASE
WHEN
length( shortest_line( $geometry, boundary( @atlas_geometry ) ) ) < @dist_bordo
and
angle_at_vertex( shortest_line( $geometry, boundary( @atlas_geometry ) ) ,0) =180
THEN 'TSL'
WHEN
length( shortest_line( $geometry, boundary( @atlas_geometry ))) <@dist_bordo
and
angle_at_vertex( shortest_line( $geometry, boundary( @atlas_geometry ) ),0 ) =0
THEN 'BSR'
WHEN
length( shortest_line( $geometry, boundary( @atlas_geometry) ) ) <@dist_bordo
and
angle_at_vertex( shortest_line( $geometry, boundary( @atlas_geometry ) ),0 ) =270
THEN 'R'
WHEN
length( shortest_line( $geometry, boundary( @atlas_geometry )) ) <@dist_bordo
and
angle_at_vertex( shortest_line( $geometry, boundary( @atlas_geometry ) ),0 )=90
THEN 'L'
END

questa espressione, da usare nelle etichette, è stata definita per metodo cartographic- position priority:

N8
espressione

dove gli ingressi attesi sono:

N13
valori attesi

magicamente:

N9
Atlas – dopo espressione

FATTO!!!


APPROFONDIMENTO

approfondiamo la logica della riga 3 e 5, le altre sono una ripetizione.

riga 3: length( shortest_line( $geometry, boundary( @atlas_geometry ) ) )<@dist_bordo

  • @atlas_geometry : è la geometria corrente dell’atlas;
  • boundary( @atlas_geometry ): ricava il limite topologico della geometria corrente dell’atlas (da poligono a linea);
  • N10
  • shortest_line( $geometry, boundary( @atlas_geometry ) ) ): disegna la linea (segmento) più breve tra la $geometry (relativa la punto) e il bordo della geometria corrente dell’atlas;
  • length( shortest_line( $geometry, boundary( @atlas_geometry ) ) ): calcola la lunghezza del segmento;

quindi la riga 3, espressa in parole umane: calcola la lunghezza minima tra il punto e il bordo del rettangolo che lo contiene.

riga 5: angle_at_vertex( shortest_line($geometry, boundary( @atlas_geometry ) ) ,0) =180

  • shortest_line($geometry, boundary( @atlas_geometry ) ): come sopra;
  • angle_at_vertex(geometry, vertex): richiede una geometria (quella di sopra, cioè il segmento minimo) e un vertice di quest’ultimo che può essere 1 o 0;N11

quindi la riga 5, espressa graficamente:

N12
calcolo angolo

l’intera espressione analizza i quattro casi (0,90,180 o 270°):

  • 0: il punto si trova sotto il bordo;
  • 90: il punto si trova a sinistra del bordo;
  • 180:  il punto si trova sopra il bordo;
  • 270: il punto si trova a destra del bordo.

 


NOTE FINALI: non so se è una mia lacuna o meno, ma questa funzionalità dovrebbe essere presente in QGIS; ma intuisco che non è di semplice implementare in quanto dipende fortemente dal vettore di copertura. Ringrazio Marco Spaziani per aver posto il problema in ML QGIS-it-user (iscrivetevi!) e ringrazio G. Allegri per avermi dato lo spunto, altrimenti non avrei mai approfondito il problema.


EDIT:

Nel caso generico, cioè con vettore di copertura NON rettangolare, basti usare questa espressione (grazie al suggerimento di G. Allegri)


CASE
WHEN
length( shortest_line( $geometry, boundary( bounds( @atlas_geometry ) ) ) ) < @dist_bordo
and
angle_at_vertex( shortest_line( $geometry, boundary( bounds( @atlas_geometry ) ) ) ,0) =180
THEN 'TSL'
WHEN
length( shortest_line( $geometry, boundary( bounds( @atlas_geometry ) ))) <@dist_bordo
and
angle_at_vertex( shortest_line( $geometry, boundary( bounds( @atlas_geometry ) ) ),0 ) =0
THEN 'BSR'
WHEN
length( shortest_line( $geometry, boundary( bounds( @atlas_geometry) ) ) ) <@dist_bordo
and
angle_at_vertex( shortest_line( $geometry, boundary( bounds( @atlas_geometry ) ) ),0 ) =270
THEN 'R'
WHEN
length( shortest_line( $geometry, boundary( bounds( @atlas_geometry ) )) ) <@dist_bordo
and
angle_at_vertex( shortest_line( $geometry, boundary( bounds( @atlas_geometry ) ) ),0 )=90
THEN 'L'
END

NB:

 

Buon lavoro.

ConQGIStando

donate al progetto QGIS:

http://qgis.it/

se il l’articolo vi è stato utile:

https://www.paypal.me/pigrecoinfinito

 

Pubblicità

5 pensieri su “QGIS: DIMMI DOVE TI TROVI E TI ETICHETTO BENE!!! ;-)

      1. Scusami, che sbadato sono stato. Mi ero perso nell0impressionante uso del codice e dele funzioni, che mi ero dimenticato che, tutit i comandi dinamici, hanno dei valori in uscita predeterminati, bastava leggerli nella descrizione del comando…. 😉 che genialata, ora é evidente che si puó far davveri tutto!!

        "Mi piace"

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.