Passare all'etichetta alternativa se la prima etichetta non si adatta a QGIS?


10

Sto cercando di creare una mappa da stampare e la dimensione dei miei poligoni varia notevolmente. Poiché questa sarà una mappa di riferimento, devo etichettare ogni poligono, ma alcuni nomi non si adattano al poligono. In quei casi, vorrei usare invece l'id della funzione e quindi una tabella di attributi collega l'id al nome.

Quello che vorrei fare è avere una sorta di espressione che posso usare per selezionare quale etichetta usare sulla mappa e quali righe includere nella tabella degli attributi. Qualcosa del genere isLabelledsarebbe in grado di tenere conto della scala della mappa, della lunghezza dell'etichetta, della dimensione del carattere ecc.


2
Tieni presente che potrebbe essere fonte di confusione per l'utente della mappa, quando i poligoni della stessa classe di entità geografiche sono etichettati in modi diversi e inoltre solo alcuni di essi vengono visualizzati in una tabella di attributi.
tallistroan,

Sto pensando a una mappa della contea di GB
Ian Turton

Che dire di cambiare dinamicamente il carattere per adattarlo? Potresti prendere la più lunga delle dimensioni delle caratteristiche, dividere per quanti caratteri nella stringa dell'etichetta e fare un po 'di matematica con la scala o semplicemente usarla per modificare la dimensione del carattere già impostata ... In alternativa puoi usare quella misura (la più lunga feature size / len of string) e se è un'etichetta troppo lunga con l'id.
Jesse McMillan,

per lo più mi occupo di leggibilità, quindi non voglio fare confusione con la dimensione del carattere
Ian Turton

1
Puoi usare un'espressione personalizzata di Python prendendo l'etichetta, la dimensione del carattere e la scala e restituendo vero o falso se si adatta. Quindi nel motore di espressione utilizzare una clausola if per cambiare etichetta. Elaborerò una risposta per te in seguito con esempi.
Jesse McMillan,

Risposte:


8

Ecco un modo un po 'approssimativo (ma si spera efficace) per farlo.

Prima un po 'di matematica. Dobbiamo capire quanti caratteri può contenere una determinata dimensione di un carattere. Ecco cose / ipotesi da sapere:

  • supponendo unità metriche, (aggiunto un leggero cambiamento di seguito che può far funzionare questo per noi crs)
  • la dimensione del carattere è una misura dell'altezza del carattere. La maggior parte dei caratteri sono larghi circa la metà di quelli alti.
  • usando pt per l'altezza del carattere, 1pt è circa 0,035 cm
  • supponendo che i pacchi siano approssimativamente rettangolari / regolari

Per sapere per quanto tempo un articolo è sullo schermo / stampa possiamo usare la sua dimensione più lunga (lunghezza o altezza, o solo lunghezza se le tue etichette sono solo orizzontali) / scala * 100 (per passare da M a CM)

Quindi possiamo vedere se la nostra etichetta si adatterebbe.

Potresti fare tutto nel motore delle espressioni, ma un'espressione pitone personalizzata sarebbe più efficiente. Ecco un tutorial su come crearne uno.

La mia espressione personalizzata:

from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom')
def labelFits(labelStr, fontPt, scaleM, feature, parent):
    # returns true if a label will fit in the feature at a given
    # font size and scale

    bbox = feature.geometry().boundingBox()

    # for CRS in us foot
    # fontWidth = fontPt * 0.0875

    # for CRS in metric
    # 1pt = 0.035CM
    fontWidth = fontPt * 0.035 * 0.5

    # length of maximum dimension on-screen/print in CM
    labelRoom =  max(bbox.width(),bbox.height()) / scaleM * 100

    # approx length of our label in CM based on font height * 0.5
    labelLen = len(labelStr) * fontWidth

    if labelRoom > labelLen:
        return True
    else:
        return False

Quindi usa quell'espressione nell'etichetta:

if(labelFits( "yourAttribute" , 8 , @map_scale ), "yourAttribute",$id)

Ovviamente dovrai collegare qualunque attributo stai effettivamente usando e cambiare la dimensione del carattere da 8 a qualunque cosa tu stia usando. Inoltre, poiché i caratteri variano un po ', potrebbe essere necessario modificarlo un po' fino a quando sembra giusto.

Puoi anche usare quell'espressione per fare cose come cambiare il colore in base al fatto che l'etichetta si adatti o meno.


Per usare questa espressione al di fuori dell'area di disegno della mappa (cioè in un'etichetta del compositore o in una tabella di attributi) abbiamo bisogno di un modo per ottenere a livello di programmazione la scala di un dato elemento della mappa. Ho pubblicato il codice per ottenere questo in un'altra risposta qui Il metodo ci fornisce un'espressione getScale ('composername', 'mapname') in modo da incorporarlo nella nostra espressione:

if(
    labelFits( "yourAttribute" , 8 , getScale('composername','mapname')),
    "yourAttribute",$id)

1
Stavo pensando anche a qualcosa di simile. Soprattutto se si utilizzano unità cartografiche e una proiezione in metri. Anche i nuovi operatori di geometria (ish) potrebbero essere d'aiuto, supponendo che le etichette siano centrate sul centroide. Funzionerà meglio con un carattere a larghezza fissa (monospazio) rispetto a un carattere proporzionale (dove una "W" è molto più ampia di una "i", per esempio). Stai per qualcosa qui, ma sospetto che i caratteri proporzionali e la crenatura aggiungeranno complessità.
Steven Kay,

È possibile utilizzare imagefont.getsize () di pil. Ciò ti darebbe la larghezza esatta di una stringa renderizzata nel tipo di carattere scelto, ma penso che avrebbe un notevole successo in termini di prestazioni. La matematica di cui sopra è molto più semplice, specialmente se hai centinaia di etichette sullo schermo
Jesse McMillan,

L'unico problema minore è che la funzione non sembra funzionare come filtro nelle tabelle degli attributi nel compositore di stampa.
Ian Turton

La scala della tua mappa varia da pagina a pagina? Prova a inserire manualmente la scala anziché la variabile @map_scale. suppongo che la tabella degli attributi non abbia modo di conoscere la scala della mappa. (Perché ad esempio potresti avere più elementi della mappa nel compositore a diverse scale)
Jesse McMillan,

1
@iant Ho pubblicato un collegamento a un'altra espressione personalizzata che otterrà la scala della tua mappa del compositore a livello di codice.
Jesse McMillan,

3

Duplica il livello, uno senza simbologia, e imposta livelli di zoom / impostazioni di ostacolo diversi per le etichette per ciascuno.


1

Ho avuto una situazione simile con l'obbligo di etichettare ogni strada in un livello stradale. La mia soluzione era quella di creare la tela di dimensioni maggiori, esportarla in PDF e quindi stampare il PDF nella dimensione richiesta.

Ad esempio, il prodotto finito doveva essere A3. Sulla tela di A3 non riuscivo a montare tutte le etichette. Così ho realizzato la tela A2 e ciò ha permesso di vedere tutte le etichette. Crea un PDF della mappa formato A2 e stampalo come A3.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.