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)