Come creare un atlante in base agli attributi dei punti?


9

In sostanza, voglio produrre un atlante basato su un campo categoriale in un livello punto.

cioè ho un livello di fornitori di servizi di assistenza all'infanzia con il campo categorico "Fornitura". Ho classificato ciascuna caratteristica in questo campo con "After School Club", "Breakfast Club" ecc., E ora voglio produrre una serie di mappe che passano attraverso ciascuna categoria e mostrino solo i punti per ciascuna. Una mappa di club dopo la scuola, una mappa di club per la colazione, ecc. Le estensioni potrebbero essere leggermente diverse.

Potrei farlo uno per uno, ma sembra che ci dovrebbe essere un modo per produrre un atlante basato sulle dimensioni di ciascuna categoria? (Sento che mi manca qualcosa di ovvio :))

O in alternativa c'è un modo per automatizzare la creazione di uno strato poligonale e utilizzarlo come copertura nascosta per l'atlante?

MODIFICA: Ho fatto alcuni piccoli progressi in questo senso: puoi utilizzare lo stile basato su regole per attivare e disattivare le funzionalità relative alla funzionalità di copertura dell'atlante corrente. funziona davvero bene se tutto ciò che vuoi fare è mostrare una serie diversa di punti. Ora sto cercando di ricollegarlo a una combinazione di colori e una leggenda reattiva.


1
Questo è fondamentalmente un duplicato di gis.stackexchange.com/questions/155143
Chris W

Grazie Chris, ma non sono sicuro che lo sia. Quello sembra chiederti se puoi fare un sotto-atlante per ogni area in un atlante originale? ad es. 4 aree ciascuna con 4 pagine? (Anche se ho fatto fatica a seguire ciò che mi veniva chiesto)
JonoPatterson,

1
No, praticamente entrambi volete creare una serie di mappe. La serie mostra la stessa estensione della mappa e le informazioni di base, ma caratteristiche diverse in ognuna. Il mio commento parla e si collega a farlo in ArcGIS tramite quelle che vengono chiamate query di definizione della pagina - cioè, ogni pagina nell'atlante / mapbook ha una query di definizione che determina quali layer / caratteristiche sono mostrati su quella pagina. Vuole una serie di serie, dove vuoi solo una singola serie. Tuttavia non so se QGIS offra ancora tale funzionalità (ho pensato di leggere una risposta / un commento che non aveva, ma non riesco a trovarlo ora).
Chris W,

Inoltre, nel tuo caso potresti generare riquadri di delimitazione basati sulle estensioni di ciascun punto che condividono gli stessi attributi e quindi utilizzarli come caratteristiche dell'indice, ma ti rimane ancora il problema di attivare e disattivare automaticamente i diversi gruppi di punti . Anche se li dividi in livelli separati, senza una sorta di query di definizione non c'è modo di disattivare quei punti su una data pagina.
Chris W,

Sì, sei morto. È anche una ripetizione di questo gis.stackexchange.com/questions/121802/… - quindi potrei dover ricorrere a farlo manualmente.
JonoPatterson,

Risposte:


9

Ho finalmente risolto questo per i miei scopi, quindi ecco la soluzione che ho trovato se aiuta qualcuno:

Scrivi uno script Python (il mio alla fine di questo) che essenzialmente fa questo:

  1. identificare le categorie uniche nel campo di interesse del livello punto
  2. per ogni categoria, selezionare tutti i punti corrispondenti e stabilire l'estensione di questo set
  3. per ogni misura genera un nuovo poligono in un livello di copertura dell'atlante vuoto con un attributo chiave "NomeCategoria"

Questo mi ha dato il livello di copertura dell'atlante con un poligono per ogni categoria di interesse simile a questa: Strato di copertura Atlas

Configura l'atlante e il compositore di stampa come al solito, lasciando solo il problema di disattivare e attivare le funzionalità.

Per questo è un po 'di tentativi ed errori per elaborare il set esatto di opzioni:

  1. L'espressione seguente consente di ottenere il valore attualmente contenuto nel campo NomeCategoria per la funzione atlante corrente

    attribute ($atlasfeature, 'CategoryName') 
    
  2. Usalo per creare uno stile basato su regole per il livello punto lungo le linee di

    attribute ($atlasfeature, 'CategoryName') = PointCategory AND PointCategory = "RedDots"
    
  3. Avevo anche una regola per garantire che tutti gli altri diventassero trasparenti

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

Regole mostrate

Testare questo con l'atlante funziona davvero bene. Infine, usa lo stesso approccio per manipolare le etichette mostrate, rendere dinamiche le etichette e filtrare le tabelle in modo appropriato. Spuntare la 'legenda del filtro per contenuto della mappa' è anche molto efficace se non si desidera tutti gli elementi della legenda su tutte le mappe.

Set atlante finale:

Atlante basato sulle caratteristiche

Modifica - come è stato richiesto, ecco il mio 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 )

3
@JonoPatterson se ora condividessi anche il tuo script Python menzionato all'inizio, questa sarebbe la risposta migliore in assoluto;)
Bernd V.

Ok lo farà - anche se è pronto e pronto quindi avrà bisogno di alcune modifiche (non ho fatto alcuna codifica per anni!). Qual è il modo migliore per farlo: basta incollare in una codebox?
JonoPatterson,

@JonoPatterson Grazie mille per la sceneggiatura. Per me come principiante, questo sembra già molto buono :). Sono sicuro che ne avrò bisogno presto.
Bernd V.

Le tue espressioni di esempio sono un po 'sbagliate - dovrebbe essere "$ atlasfeature", non "$ atlasfeatureid"
ndawson
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.