¿Cambiar a una etiqueta alternativa si la primera etiqueta no cabe en QGIS?

10

Estoy tratando de crear un mapa para imprimir y el tamaño de mis polígonos varía mucho. Como este será un mapa de referencia, necesito etiquetar cada polígono, pero algunos de los nombres no caben en el polígono. En esos casos, me gustaría utilizar la identificación de la función y luego hacer que una tabla de atributos vincule la identificación con el nombre.

Lo que me gustaría hacer es tener algún tipo de expresión que pueda usar para seleccionar qué etiqueta usar en el mapa y qué filas incluir en la tabla de atributos. Algo así isLabelledpodría tener en cuenta la escala del mapa, la longitud de la etiqueta, el tamaño de la fuente, etc.

Ian Turton
fuente
2
Tenga en cuenta que puede ser confuso para el usuario del mapa, cuando los polígonos de la misma clase de entidad se etiquetan de diferentes maneras y, además, solo algunos de ellos aparecen en una tabla de atributos.
tallistroan
Estoy pensando en un mapa del condado de GB
Ian Turton
¿Qué hay de cambiar dinámicamente la fuente para que se ajuste? Puede tomar la dimensión más larga de las características, dividir por la cantidad de caracteres en la cadena de la etiqueta, y hacer algunos cálculos con la escala o simplemente usar eso para alterar el tamaño de fuente ya establecido ... Alternativamente, puede usar esa medida (más larga característica dimensión / longitud de cadena) y si es demasiado larga etiqueta con la identificación.
Jesse McMillan
principalmente estoy preocupado por la legibilidad, así que no quiero meterme con el tamaño de fuente
Ian Turton
1
Puede usar una expresión personalizada de Python que tome la etiqueta, el tamaño de fuente y la escala y devuelva verdadero o falso si cabe. Luego, en el motor de expresión, use una cláusula if para cambiar las etiquetas. Encontraré una respuesta para ti más tarde con ejemplos.
Jesse McMillan

Respuestas:

8

Aquí hay una forma aproximada (pero con suerte efectiva) de hacerlo.

Primero algo de matemática. Necesitamos averiguar cuántos caracteres en un determinado tamaño de fuente puede contener una característica. Aquí cosas / supuestos para saber:

  • asumiendo unidades métricas, (se agregó un ligero cambio a continuación que puede hacer que esto funcione para nosotros).
  • El tamaño de fuente es una medida de la altura de la fuente. La mayoría de las fuentes son aproximadamente la mitad de anchas que altas.
  • usando pt para la altura de la fuente, 1pt es aproximadamente 0.035 cm
  • asumiendo que sus paquetes son aproximadamente rectangulares / regulares

Para saber cuánto tiempo está un elemento en la pantalla / impresión, podemos usar su dimensión más larga (longitud o altura, o solo longitud si sus etiquetas son solo horizontales) / escala * 100 (para ir de M a CM)

Entonces podemos ver si nuestra etiqueta encajaría.

Podría hacerlo todo en el motor de expresión, pero una expresión personalizada de Python sería más eficiente. Aquí hay un tutorial sobre cómo crear uno.

Mi expresion personalizada:

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

Luego solo usa esa expresión en la etiqueta:

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

Necesitará conectar cualquier atributo que esté usando, por supuesto, y cambiar el tamaño de fuente de 8 a lo que esté usando. Además, dado que las fuentes varían bastante, es posible que deba modificarlas un poco hasta que se vean bien.

También puede usar esa expresión para hacer cosas como cambiar el color en función de si la etiqueta se ajusta o no.


Para usar esta expresión fuera del lienzo del mapa (es decir, en una etiqueta de compositor o en una tabla de atributos) necesitamos una forma de obtener mediante programación la escala de un elemento de mapa dado. He publicado código para lograr eso en otra respuesta aquí. El método allí nos da una expresión getScale ('nombre del compositor', 'nombre del mapa') para incorporarlo a nuestra expresión:

if(
    labelFits( "yourAttribute" , 8 , getScale('composername','mapname')),
    "yourAttribute",$id)
Jesse McMillan
fuente
1
Estaba pensando en algo similar también. Especialmente si se utilizan unidades de mapa y una proyección en metros. Los nuevos operadores de geometría (ish) también podrían ayudar aquí, suponiendo que las etiquetas estén centradas en el centroide. Esto funcionará mejor con una fuente de ancho fijo (monoespaciado) que una fuente proporcional (donde una 'W' es mucho más ancha que una 'i', por ejemplo). Estás haciendo algo aquí, pero sospecho que las fuentes proporcionales y el kerning agregarán complejidad.
Steven Kay
Podrías usar pil's imagefont.getsize (). Eso le daría un ancho exacto de una cadena representada en la fuente elegida, pero creo que eso tendría un gran impacto en el rendimiento. Los cálculos matemáticos anteriores son mucho más simples, especialmente si tienes cientos de etiquetas en pantalla
Jesse McMillan el
El único problema menor es que la función no parece funcionar como un filtro en las tablas de atributos en el compositor de impresión.
Ian Turton
¿La escala de su mapa varía de una página a otra? Intente poner manualmente la escala en lugar de la variable @map_scale. Supongo que la tabla de atributos no tiene forma de conocer la escala de su mapa. (Porque, por ejemplo, podría tener varios elementos de mapa en el compositor a diferentes escalas)
Jesse McMillan
1
@iant Publiqué un enlace a otra expresión personalizada que obtendrá la escala de su mapa de compositor mediante programación.
Jesse McMillan
3

Duplique la capa, una sin simbología, y establezca diferentes niveles de zoom / configuración de obstáculos para las etiquetas para cada una.

Tom Chadwin
fuente
1

Tuve una situación similar con la obligación de etiquetar cada carretera en una capa de carretera. Mi solución fue crear el lienzo en un tamaño más grande, exportar a PDF y luego imprimir el PDF al tamaño requerido.

Por ejemplo, el producto terminado debía ser A3. En el lienzo en A3 no pude colocar todas las etiquetas. Así que hice el lienzo A2 y eso permitió ver todas las etiquetas. Cree un PDF del mapa de tamaño A2 e imprímalo como A3.

Johanna
fuente