Wie erstelle ich einen Atlas basierend auf Punktattributen?

9

Im Wesentlichen möchte ich einen Atlas erstellen, der auf einem kategorialen Feld in einer Punktebene basiert.

dh ich habe eine Punktschicht von Kinderbetreuern mit dem kategorischen Feld "Bereitstellung". Ich habe jede Funktion in diesem Feld mit "After School Club", "Breakfast Club" usw. kategorisiert und möchte jetzt eine Reihe von Karten erstellen, die jede Kategorie durchlaufen und nur die Punkte für jede anzeigen. Eine Karte von After-School-Clubs, eine Karte von Frühstücksclubs usw. Die Ausmaße können geringfügig voneinander abweichen.

Ich könnte es einzeln tun, aber es scheint, dass es eine Möglichkeit geben sollte, einen Atlas zu erstellen, der auf den Ausmaßen jeder Kategorie basiert. (Ich habe das Gefühl, ich vermisse etwas Offensichtliches :))

Oder gibt es eine Möglichkeit, die Erstellung einer Polygonebene zu automatisieren und diese als versteckte Abdeckung für den Atlas zu verwenden?

BEARBEITEN: Ich habe ein wenig Fortschritte gemacht - Sie können das regelbasierte Styling verwenden, um Funktionen ein- und auszuschalten, die für die aktuelle Atlasabdeckungsfunktion relevant sind. Es funktioniert tatsächlich einwandfrei, wenn Sie nur einen anderen Satz von Punkten anzeigen möchten. Ich versuche jetzt, das mit einem Farbschema und einer reaktiven Legende zu verknüpfen.

JonoPatterson
quelle
1
Dies ist im Grunde ein Duplikat von gis.stackexchange.com/questions/155143
Chris W
Danke Chris - aber nicht sicher, ob es so ist. Dieser scheint zu fragen, ob Sie einen Unteratlas für jeden Bereich in einem Originalatlas erstellen können? zB 4 Bereiche mit jeweils 4 Seiten? (Obwohl ich
Mühe hatte, dem
1
Nein, im Grunde möchten Sie beide eine Kartenserie erstellen. Die Serie zeigt den gleichen Kartenumfang und die gleichen Basisinformationen, jedoch jeweils unterschiedliche Merkmale. In meinem dortigen Kommentar wird über sogenannte Seitendefinitionsabfragen in ArcGIS gesprochen und darauf verwiesen. Das heißt, jede Seite im Atlas / Mapbook verfügt über eine Definitionsabfrage, die bestimmt, welche Ebenen / Features auf dieser Seite angezeigt werden. Er möchte eine Reihe von Serien, bei denen Sie nur eine einzige Serie wollen. Ich weiß jedoch nicht, ob QGIS noch solche Funktionen bietet (ich dachte, ich hätte eine Antwort / einen Kommentar gelesen, die es nicht gab, aber das kann ich jetzt nicht finden).
Chris W
In Ihrem Fall könnten Sie auch Begrenzungsrahmen basierend auf den Ausmaßen jedes Punkts mit denselben Attributen generieren und diese dann als Indexfunktionen verwenden. Sie haben jedoch weiterhin das Problem, die verschiedenen Punktgruppen automatisch ein- und auszuschalten . Selbst wenn Sie sie in separate Ebenen aufteilen, gibt es ohne eine Definitionsabfrage keine Möglichkeit, diese Punkte auf einer bestimmten Seite zu deaktivieren.
Chris W
Ja, du bist tot auf. Es ist auch eine Wiederholung dieses einen gis.stackexchange.com/questions/121802/… - also muss ich möglicherweise manuell darauf zurückgreifen.
JonoPatterson

Antworten:

9

Ich habe dies endlich für meine Zwecke gelöst. Hier ist die Lösung, die ich gefunden habe, wenn sie jemandem hilft:

Schreiben Sie ein Python-Skript (meins am Ende), das im Wesentlichen Folgendes tut:

  1. Identifizieren Sie die eindeutigen Kategorien im interessierenden Punktschichtfeld
  2. Wählen Sie für jede Kategorie alle übereinstimmenden Punkte aus und legen Sie den Umfang dieses Satzes fest
  3. Generieren Sie für jede Ausdehnung ein neues Polygon in einer leeren Atlasabdeckungsebene mit dem Schlüsselattribut "CategoryName".

Dies gab mir die Atlasabdeckungsschicht mit einem Polygon für jede interessierende Kategorie, die so aussah: Atlas-Deckschicht

Konfigurieren Sie den Atlas und den Print Composer wie gewohnt - und lassen Sie nur die Funktionen zum Ein- und Ausschalten.

Dafür ist es ein bisschen Versuch und Irrtum, die genauen Optionen herauszufinden:

  1. Mit dem folgenden Ausdruck können Sie den Wert abrufen, der derzeit im Feld CategoryName für die aktuelle Atlasfunktion gespeichert ist

    attribute ($atlasfeature, 'CategoryName') 
    
  2. Verwenden Sie diese Option, um ein regelbasiertes Styling für die Punktebene entlang der Linien von zu erstellen

    attribute ($atlasfeature, 'CategoryName') = PointCategory AND PointCategory = "RedDots"
    
  3. Ich hatte auch eine Regel, um sicherzustellen, dass alle anderen transparent wurden

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

Regeln angezeigt

Das Testen mit dem Atlas funktioniert wirklich gut. Verwenden Sie zum Schluss einfach den gleichen Ansatz, um die angezeigten Beschriftungen zu bearbeiten, Beschriftungen dynamisch zu machen und Tabellen entsprechend zu filtern. Das Aktivieren der Option "Legende nach Karteninhalt filtern" ist auch dann sehr effektiv, wenn nicht alle Legendenelemente auf allen Karten angezeigt werden sollen.

Letzter Atlas-Satz:

Funktionsbasierter Atlas

Bearbeiten - wie es verlangt wurde, hier ist mein Skript:

    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
quelle
3
@ JonPatterson Wenn Sie jetzt auch Ihr Python-Skript teilen würden, das am Anfang erwähnt wurde, wäre dies die beste Antwort aller Zeiten;)
Bernd V.
Ok wird dies tun - obwohl es grob und fertig ist, so dass es einige Verbesserungen benötigt (seit Jahren keine Codierung mehr!). Was ist der beste Weg, dies zu tun - einfach in eine Codebox einfügen?
JonoPatterson
@ JonoPatterson Vielen Dank für das Skript. Für mich als Anfänger sieht das schon sehr gut aus :). Ich bin sicher, ich werde das bald brauchen.
Bernd V.
Ihre Beispielausdrücke sind etwas falsch - es sollte "$ atlasfeature" sein, nicht "$ atlasfeatureid"
ndawson