Como criar um Atlas com base em atributos de ponto?

9

Essencialmente, estou querendo produzir um atlas com base em um campo categórico em uma camada de pontos.

ou seja, eu tenho uma camada pontual de prestadores de cuidados infantis com o campo categórico "Provisão". Eu categorizei cada recurso neste campo com "After School Club", "Breakfast Club" etc., e agora quero produzir um conjunto de mapas que iterem por cada categoria e mostrem apenas os pontos de cada um. Um mapa dos clubes depois da escola, um mapa dos clubes de café da manhã etc. As extensões podem ser sutilmente diferentes.

Eu poderia fazê-lo um por um, mas parece que deveria haver uma maneira de produzir um atlas com base nas extensões de cada categoria? (Eu sinto que estou perdendo algo óbvio :))

Ou, como alternativa, existe uma maneira de automatizar a criação de uma camada de polígono e usá-la como uma cobertura oculta para o atlas?

EDIT: Eu fiz um pequeno progresso nisso - você pode usar o estilo baseado em regras para ativar e desativar os recursos relevantes ao atual recurso de cobertura do atlas. na verdade, funciona bem se tudo o que você quer fazer é mostrar um conjunto diferente de pontos. Agora estou olhando para amarrar isso de volta a um esquema de cores e a uma legenda reativa.

JonoPatterson
fonte
11
Esta é basicamente uma duplicata de gis.stackexchange.com/questions/155143
Chris W
Obrigado Chris - mas não tenho certeza se é. Esse parece estar perguntando se você pode criar um sub-atlas para cada área em um atlas original? por exemplo, 4 áreas, cada uma com 4 páginas? (Embora eu fiz luta para acompanhar o que estava sendo pedido)
JonoPatterson
11
Não, basicamente vocês dois querem criar uma série de mapas. A série mostra a mesma extensão do mapa e informações de base, mas recursos diferentes em cada um. Meu comentário fala sobre e faz links para fazê-lo no ArcGIS através do que é chamado de consultas de definição de página - ou seja, cada página no atlas / mapbook possui uma consulta de definição que determina quais camadas / recursos são mostrados nessa página. Ele quer uma série de séries, onde você só quer uma única série. No entanto, não sei se o QGIS ainda oferece essa funcionalidade (achei que tinha lido uma resposta / comentário que não tinha, mas não consigo encontrá-lo agora).
21715 Chris W
Além disso, no seu caso, você pode gerar caixas delimitadoras com base nas extensões de cada ponto, compartilhando os mesmos atributos e depois usá-las como seus recursos de índice, mas ainda resta o problema de ativar e desativar automaticamente os diferentes grupos de pontos. . Mesmo se você as dividir em camadas separadas, sem algum tipo de consulta de definição, não há como desativar esses pontos em qualquer página.
21815 Chris W
Sim, você está morto. Também é uma repetição deste gis.stackexchange.com/questions/121802/… - então talvez eu precise recorrer a fazê-lo manualmente.
precisa saber é o seguinte

Respostas:

9

Finalmente resolvi isso para meus propósitos, então aqui está a solução que encontrei, se isso ajuda alguém:

Escreva um script python (o meu no final disso) que essencialmente faz isso:

  1. identifique as categorias exclusivas no campo de interesse da camada de pontos
  2. para cada categoria, selecione todos os pontos correspondentes e estabeleça a extensão desse conjunto
  3. para cada extensão, gere um novo polígono em uma camada de cobertura de atlas em branco com um atributo-chave "CategoryName"

Isso me deu a camada de cobertura do atlas com um polígono para cada categoria de interesse parecida com esta: Camada de cobertura Atlas

Configure o atlas e o compositor de impressão normalmente, deixando apenas a questão de desativar e ativar os recursos.

Para isso, é necessário um pouco de tentativa e erro para definir o conjunto exato de opções:

  1. A expressão abaixo permite que você obtenha o valor atualmente mantido no campo CategoryName para o recurso de atlas atual

    attribute ($atlasfeature, 'CategoryName') 
    
  2. Use isso para criar um estilo baseado em regras para a camada de pontos ao longo das linhas de

    attribute ($atlasfeature, 'CategoryName') = PointCategory AND PointCategory = "RedDots"
    
  3. Eu também tinha uma regra para garantir que todos os outros se tornassem transparentes

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

Regras mostradas

Testar isso com o atlas funciona muito bem. Finalmente, basta usar a mesma abordagem para manipular os rótulos mostrados, tornar os rótulos dinâmicos e filtrar as tabelas adequadamente. Marcar a 'legenda de filtro pelo conteúdo do mapa' também é muito eficaz se você não quiser todos os itens de legenda em todos os mapas.

Conjunto final de atlas:

Atlas baseado em recursos

Editar - como foi solicitado, aqui está o meu 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
fonte
3
@JonoPatterson se você agora também partilhar o seu script python mencionado no thebeginning, esta seria a melhor resposta sempre;)
Bernd V.
O Ok fará isso - embora esteja pronto para o processamento, ele precisará de alguns ajustes (não faz codificação há anos!). Qual é a melhor maneira de fazer isso - basta colar em um codebox?
JonoPatterson
@JonoPatterson Muito obrigado pelo script. Para mim, como iniciante, isso já parece muito bom :). Tenho certeza de que precisarei disso em breve.
Bernd V.
Suas expressões de exemplo estão um pouco erradas - deve ser "$ atlasfeature", não "$ atlasfeatureid"
ndawson 30/07/2015