15 votos

Determinación de los identificadores de las baldosas vecinas en QGIS

En un reciente curso de formación me preguntaron si QGIS podía calcular automáticamente los números de página siguiente/anterior y superior/inferior de un libro de mapas creado con el generador de atlas. Conseguí elaborar una expresión de etiqueta bastante razonable para una cuadrícula regular si se conoce la anchura y la altura de la cuadrícula.

Pero luego empezamos a pensar en ejemplos realistas en los que no queremos dibujar páginas que no contengan nuestro distrito de interés, como ésta de mi condado natal:

enter image description here

Así que esta tarde he jugado con un script de Python para calcular los 4 vecinos que me interesaban para cada celda de la cuadrícula y he añadido esos valores a mi cuadrícula (esto se basa en gran medida en Ujaval Gandhi tutorial ):

for f in feature_dict.values():
    print 'Working on %s' % f[_NAME_FIELD]
    geom = f.geometry()
    # Find all features that intersect the bounding box of the current feature.
    # We use spatial index to find the features intersecting the bounding box
    # of the current feature. This will narrow down the features that we need
    # to check neighboring features.
    intersecting_ids = index.intersects(geom.boundingBox())
    # Initalize neighbors list and sum
    neighbors = []
    neighbors_sum = 0
    for intersecting_id in intersecting_ids:
        # Look up the feature from the dictionary
        intersecting_f = feature_dict[intersecting_id]
        int_geom = intersecting_f.geometry()
        centroid = geom.centroid()
        height = geom.boundingBox().height()
        width = geom.boundingBox().width()
        # For our purpose we consider a feature as 'neighbor' if it touches or
        # intersects a feature. We use the 'disjoint' predicate to satisfy
        # these conditions. So if a feature is not disjoint, it is a neighbor.
        if (f != intersecting_f and
            not int_geom.disjoint(geom)):
            above_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()+height))
            below_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()-height))
            left_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()-width,
               centroid.asPoint().y()))
            right_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()+width,
               centroid.asPoint().y()))
            above = int_geom.contains(above_point)   
            below = int_geom.contains(below_point)   
            left = int_geom.contains(left_point)
            right = int_geom.contains(right_point)
            if above:
                print "setting %d as above %d"%(intersecting_f['id'],f['id'])
                f['above']=intersecting_f['id']

            if below:
                print "setting %d as below %d"%(intersecting_f['id'],f['id'])
                f['below']=intersecting_f['id']

            if left:
                print "setting %d as left of %d"%(intersecting_f['id'],f['id'])
                f['left']=intersecting_f['id']

            if right:
                print "setting %d as right of %d"%(intersecting_f['id'],f['id'])
                f['right']=intersecting_f['id']

    # Update the layer with new attribute values.
    layer.updateFeature(f)

layer.commitChanges()

Esto funciona bien.

enter image description here

Pero, para ser sincero, lo de crear un punto de prueba al norte y luego probar todos los posibles vecinos parece un error. Sin embargo, después de una tarde de devanarse los sesos, no se me ocurre una forma mejor de determinar cuál es el vecino norte de una celda de la cuadrícula.

Lo ideal sería algo lo suficientemente sencillo como para ponerlo en un cuadro de texto del compositor de la impresión, pero sospecho que es demasiado pedir.

0 votos

Qué pasa si no hay ningún vecino en un lado. ¿Quiere que el valor de la celda closeset en una dirección o dejaría un vacío?

0 votos

En ese caso me basta con un null, puedo configurar fácilmente la etiqueta para que sólo se muestre cuando no sea null o esté vacía.

0 votos

¿Cómo es posible que su cuadrícula se nombre de izquierda a derecha en lugar de arriba a abajo? Me gustaría hacer esto también. Incluso mejor, primera línea A, segunda línea B,... y numeración de izquierda a derecha. ¿Es esto posible?

11voto

Sushant23 Puntos 329

En realidad, ya has hecho la mayor parte del trabajo necesario para determinar las baldosas que quieres imprimir utilizando el atlas. Pero el punto es cómo ajustar todo junto para mostrar sólo los IDs de los azulejos que usted necesita. Para demostrar mi idea, voy a utilizar en este ejemplo una imagen DEM y un archivo vectorial de cuadrícula, como se puede ver a continuación:

enter image description here

Primero tenemos que mostrar la etiqueta de cada cuadrícula.

En la vista de diseño, utilicé la cuadrícula como capa de cobertura en el atlas, creé dos mapas: el mapa de la ventana de la vista principal, y un mapa de índice que muestra sólo la cuadrícula, como se puede ver a continuación:

enter image description here

Entonces hice lo siguiente:

  1. He ajustado la escala del mapa de índices para mostrar toda la extensión de la cuadrícula luego he fijado la escala
  2. He arreglado la extensión de la vista para evitar que el mapa se desplace cuando se utiliza Preview atlas y
  3. He habilitado el Overview para ver la extensión y la ubicación de la mapa de la vista, como se puede ver a continuación:

enter image description here

Para el mapa de la ventana de la vista principal, he fijado la escala a la medida de cada bloque de la cuadrícula, para estar seguro de que la escala no se cambiará si algo sucede, como se puede ver a continuación;

enter image description here

Utilizando un mapa de índice, puede ver fácilmente el ID y la ubicación de cada baldosa con referencia a otra baldosa, incluso cuando desactiva la cuadrícula de la ventana principal del mapa. Por ejemplo, el siguiente mapa tiene un ID de baldosa=14, y puede ver los ID de las baldosas circundantes.

enter image description here

Actualización :

Voy a actualizar mi respuesta porque me he dado cuenta de que querías mostrar el índice del número de página de los diseños circundantes, no los ID de los diseños circundantes.

Para facilitar la comprensión del proceso, actualizaré los números de identificación en el mapa del índice para que muestren el número de página de la maqueta, como se muestra a continuación:

enter image description here

Como los IDs que tengo empiezan por 0 (Cero), el ID de la primera cuadrícula que se muestra en el mapa de índices empezará por 3. Por lo tanto, quiero cambiar el número de página para que empiece por 1 restando 2 al número de ID en el Atlas: Page number: ID -2 Entonces utilizaré el número de página actual como referencia en la expresión para crear etiquetas para la página actual, la página anterior, la página siguiente, la página superior y la página inferior, como sigue:

enter image description here

  • La página actual tiene esta expresión en el cuadro de texto de la etiqueta: Current Page Number: [%@atlas_pagename%]

  • Expresión de la página anterior: [%if((@atlas_pagename = 1), Null, ' Page Number: ' || (@atlas_pagename - 1))%] ya que no hay páginas antes de la 1

  • Siguiente expresión de la página: [%if( (@atlas_pagename = 25), Null, ' Page Number: ' || (@atlas_pagename + 1))%] ya que no hay páginas después del 25

  • Expresión de la página de arriba: [%if((@atlas_pagename <= 6),NULL,' Page Number: ' || (@atlas_pagename -6))%] ya que no hay páginas antes de la 6 en la dirección superior

  • Por debajo de la expresión de la página: [%if((@atlas_pagename >= 20), Null, ' Page Number: ' || (@atlas_pagename + 6))%] ya que no hay páginas después de la 20 en la dirección inferior

Algunos resultados de salida:

enter image description here

enter image description here

enter image description here

enter image description here

1 votos

Aunque es útil, esto no responde a su pregunta.

0 votos

@Victor Gracias por tu comentario, he actualizado mi respuesta.

0 votos

Esto funciona en tu ejemplo (y en el suyo), ya que los lados del mapa de teclas/rejilla son regulares. Si no fueran rectos no funcionaría ya que el número a sumar o restar (6 en tu ejemplo) variaría dependiendo de la página del atlas en la que te encuentres.

6voto

Vlado Klimovský Puntos 196

Si no está encajando cada extensión de página (de la capa de índice) exactamente en el compositor, sino que tiene bordes superpuestos con las páginas adyacentes (como se muestra en su segunda captura de pantalla), entonces podría utilizar etiquetas de la capa de índice, con el inconveniente de que estarían dentro del borde del mapa.

Si no hay ningún solapamiento, se podría replicar una técnica que utilicé con éxito en el pasado (¡coincidiendo con el E y el W de Sussex!) en MapInfo, donde escribí un pequeño script que generaba un conjunto de cuatro puntos para cada característica de índice, desplazado en las características adyacentes, con atributos tanto del número de hoja, como de la dirección del desplazamiento. La capa de puntos se utilizó entonces para generar etiquetas de nuevo, con la dirección del desplazamiento que permitía ajustar la orientación de las etiquetas para conseguir un efecto más bonito.

No lo he probado, pero es posible que se pueda evitar la generación de una capa de datos separada en QGIS mediante el uso de la nueva funcionalidad de estilo del generador de geometría, lo que supondría una solución más elegante y dinámica que no se podía conseguir en MapInfo.

0 votos

Debería haber pensado en utilizar las etiquetas de los otros polígonos :-) Después de un rápido experimento con el Generador de Geometría puedo dibujar un cuadro delimitador, pero es más difícil construir una cuadrícula

0 votos

Estaba pensando en generar puntos de etiqueta desplazados en los polígonos adyacentes, en lugar de cuadrículas. Otra opción sería ampliar el MBR de la característica de índice en las características adyacentes para permitir que se dibujen las etiquetas.

0 votos

Acabo de jugar, y parece que la geometría generada por el estilo del generador de geometría no se etiqueta, por lo que no es la solución más elegante que esperaba.

2voto

Elliott Maynard Puntos 11

Esta solución funcionará para rejillas rectangulares y es automática (debería funcionar para cualquier escenario sin ajustar nada manualmente).

Supongamos que tiene una cuadrícula con números de página. Puede ejecutar mi script de procesamiento seleccionando como parámetros la capa de la cuadrícula y su campo de número de página. El script crea cuatro campos ( right, left, above, below ) en la capa de la cuadrícula y calcula el correspondiente id de página vecina para cada celda de la cuadrícula. A continuación, puede utilizar sus expresiones (por ejemplo [% if( "left" is not NULL, 'to page' || "left", "" ) %] ) para mostrar las etiquetas de las páginas vecinas.

Sólo hay que añadir mi repositorio ( https://github.com/gacarrillor/QGIS-Resources.git ) del plugin de intercambio de recursos de QGIS e instalar el script: enter image description here

enter image description here

Cómo funciona

El script determina la relación (derecha, izquierda, arriba o abajo) comparando las coordenadas de las cajas delimitadoras tanto de la celda actual de la cuadrícula como de cada celda de intersección. Resulta que para cada relación falta una de las coordenadas.

Si la relación es above la coordenada que falta es yMin es decir, las otras 3 coordenadas de la caja delimitadora de la celda actual estarán presentes en la caja delimitadora de la celda anterior. Recuerde que los cuadros delimitadores de QGIS se definen en este orden: [xMin, yMin, xMax, yMax] .

Para un ejemplo numérico tomemos rectángulos con lados de longitud 1. Digamos que la caja delimitadora de la celda actual se define como bbox1=[0,0,1,1] . El cuadro delimitador de la celda anterior se definiría como bbox2=[0,1,1,2] . Las coordenadas X de bbox1 están presentes en bbox2, mientras que las de bbox1 yMin falta en las coordenadas Y de bbox2.

Podemos definir nuestras 4 relaciones de esta manera (o: presente, #: falta):

right: [#,o,o,o]
above: [o,#,o,o]
left:  [o,o,#,o]
below: [o,o,o,#]

Como puede ver, el índice que falta nos da toda la información que necesitamos.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X