¿Cómo crear un Atlas basado en atributos de puntos?

9

Esencialmente, quiero producir un atlas basado en un campo categórico en una capa de puntos.

es decir, tengo una capa puntual de proveedores de cuidado infantil con el campo categórico "Provisión". He categorizado cada función en este campo con "After School Club", "Breakfast Club", etc., y ahora quiero producir un conjunto de mapas que recorran cada categoría y muestren solo los puntos para cada uno. Un mapa de clubes después de la escuela, un mapa de clubes de desayuno, etc. Las extensiones pueden ser sutilmente diferentes.

Podría hacerlo uno por uno, pero parece que debería haber una manera de producir un atlas basado en la extensión de cada categoría. (Siento que me falta algo obvio :))

O, alternativamente, ¿hay alguna forma de automatizar la creación de una capa de polígono y usarla como una cobertura oculta para el atlas?

EDITAR: He progresado un poco con esto: puede usar un estilo basado en reglas para activar y desactivar las funciones relevantes para la función de cobertura de atlas actual. en realidad funciona bien si todo lo que quieres hacer es mostrar un conjunto diferente de puntos. Ahora estoy buscando vincular eso a un esquema de color y una leyenda reactiva.

JonoPatterson
fuente
1
Esto es básicamente un duplicado de gis.stackexchange.com/questions/155143
Chris W
Gracias Chris, pero no estoy seguro si es así. ¿Parece preguntarse si puede hacer un sub-atlas para cada área en un atlas original? por ejemplo, 4 áreas cada una con 4 páginas? (Aunque tuve problemas para seguir lo que se pedía)
JonoPatterson
1
No, básicamente los dos quieren crear una serie de mapas. La serie muestra la misma extensión de mapa e información base, pero diferentes características en cada una. Mi comentario allí habla y enlaza para hacerlo en ArcGIS a través de lo que se llama consultas de definición de página, es decir, cada página en el atlas / mapbook tiene una consulta de definición que determina qué capas / características se muestran en esa página. Él quiere una serie de series, donde solo quieres una sola serie. Sin embargo, no sé si QGIS todavía ofrece esa funcionalidad (pensé que había leído una respuesta / comentario que no lo hizo, pero no puedo encontrar eso ahora).
Chris W
Además, en su caso, podría generar cuadros delimitadores basados ​​en la extensión de cada punto que comparte los mismos atributos y luego usarlos como sus características de índice, pero aún tiene el problema de activar y desactivar automáticamente los diferentes grupos de puntos . Incluso si los divide en capas separadas, sin algún tipo de consulta de definición, no hay forma de desactivar esos puntos en una página determinada.
Chris W
Sí, estás muerto. También es una repetición de este gis.stackexchange.com/questions/121802/… , por lo que podría tener que recurrir a hacerlo manualmente.
JonoPatterson

Respuestas:

9

Finalmente resolví esto para mis propósitos, así que aquí está la solución que se me ocurrió si ayuda a alguien:

Escribe un script de Python (el mío al final de esto) que esencialmente hace esto:

  1. Identificar las categorías únicas en el campo de interés de la capa de puntos
  2. para cada categoría, seleccione todos los puntos coincidentes y establezca la extensión de este conjunto
  3. para cada extensión generar un nuevo polígono en una capa de cobertura de atlas en blanco con un atributo clave "CategoryName"

Esto me dio la capa de cobertura del atlas con un polígono para cada categoría de interés que se ve así: Capa de cobertura Atlas

Configure el atlas y el compositor de impresión de manera normal, dejando solo el problema de desactivar y activar las funciones.

Para esto, es un poco de prueba y error determinar el conjunto exacto de opciones:

  1. La siguiente expresión le permite obtener el valor que actualmente se encuentra en el campo CategoryName para la característica de atlas actual

    attribute ($atlasfeature, 'CategoryName') 
    
  2. Use esto para crear un estilo basado en reglas para la capa de puntos a lo largo de las líneas de

    attribute ($atlasfeature, 'CategoryName') = PointCategory AND PointCategory = "RedDots"
    
  3. También tenía una regla para garantizar que todos los demás se volvieran transparentes

    attribute ($atlasfeature, 'CategoryName') IS NOT PointCategory
    

Reglas mostradas

Probar esto con el atlas funciona muy bien. Finalmente, utilice el mismo enfoque para manipular las etiquetas que se muestran, haga que las etiquetas sean dinámicas y filtre las tablas adecuadamente. Marcar la opción 'filtrar leyenda por contenido del mapa' también es muy efectivo si no desea todos los elementos de la leyenda en todos los mapas.

Conjunto final de atlas:

Atlas basado en funciones

Editar: como se solicitó, aquí está mi script:

    from PyQt4.QtCore import *

#main script----------------------------------------------
    #set up the layer references - you will need to change this
targetlayer=QgsMapLayerRegistry.instance().mapLayer("AtlasExtents20150727154732521")
eylayer = QgsMapLayerRegistry.instance().mapLayer("Early_Years_Providers20150727152919862")

#establish the unique categories 
names = getUniqueAttributes(eylayer, 'Mapping_La')

#get a set of boxes
boxset = getBoundings(eylayer, names)

#ensure layer is emptied, then add bounding boxes
deleteBoxes(targetlayer)
createBoxes(targetlayer, boxset)
 #end main script----------------------------------------------   


 #------functions-------#
#gets unique set of attributes - returns a set()
def getUniqueAttributes(layer, fieldname):
    values = set()
    for feature in layer.getFeatures():
        values.add(feature[fieldname])
    return values

#quickly selects all points on a layer, given a query 
def selectionQuick(layer, queryitem):
    layer.removeSelection ()

    #hardcoded field name
    expr = QgsExpression( "\"Mapping_La\" = '" + queryitem +"'")
    it = layer.getFeatures( QgsFeatureRequest( expr ) )
    ids = [i.id() for i in it]
    layer.setSelectedFeatures( ids )

#for a set of unique items, get bounding boxes 
def getBoundings(layer, itemset):
    bboxes = {}
    for itemname in itemset:
        selectionQuick(layer,itemname)
        box = layer.boundingBoxOfSelected()
        bboxes[itemname] = box
    return bboxes

#for a layer create a bunch of boxes
def createBoxes(layer, boxes):
    id=0
    for boxkey in boxes:
        id = id +1
        box=boxes[boxkey]
        feat = QgsFeature(layer.pendingFields())
        geom = QgsGeometry.fromRect(box)
        feat.setAttribute('id', id)
        #hardcoded field name
        feat.setAttribute('CareType', boxkey)
        feat.setGeometry(geom)
        (res, outFeats) = layer.dataProvider().addFeatures([feat])

def deleteBoxes(layer):
        ids = [f.id() for f in layer.getFeatures()]
        layer.dataProvider().deleteFeatures( ids )
JonoPatterson
fuente
3
@JonoPatterson si ahora también compartieras tu script de Python mencionado al principio, esta sería la mejor respuesta de la historia;)
Bernd V.
Ok lo hará, aunque está listo y listo, por lo que necesitará algunos ajustes (¡no he hecho ninguna codificación en años!). ¿Cuál es la mejor manera de hacerlo, simplemente pegar en un cuadro de código?
JonoPatterson
@JonoPatterson Muchas gracias por el guión. Para mí como principiante, esto ya se ve muy bien :). Estoy seguro de que lo necesitaré pronto.
Bernd V.
Sus expresiones de ejemplo son un poco incorrectas - debería ser "$ atlasfeature", no "$ atlasfeatureid"
ndawson