Jak stworzyć Atlas w oparciu o atrybuty punktu?

9

Zasadniczo chcę stworzyć atlas oparty na kategorycznym polu w warstwie punktowej.

tzn. mam punktową warstwę dostawców opieki nad dziećmi z kategorycznym polem „Świadczenie”. Każda funkcja w tej dziedzinie została podzielona na kategorie według „Klubu po szkole”, „Klubu śniadaniowego” itp., A teraz chcę stworzyć zestaw map, które będą się powtarzały w poszczególnych kategoriach i pokazywały tylko punkty dla każdej z nich. Jedna mapa klubów po szkole, jedna mapa klubów śniadaniowych itp. Zakres może być nieco inny.

Mógłbym to zrobić jeden po drugim, ale wydaje się, że powinien istnieć sposób na stworzenie atlasu w oparciu o zakres każdej kategorii? (Czuję, że brakuje mi czegoś oczywistego :))

Czy też istnieje sposób automatyzacji tworzenia warstwy wielokątów i wykorzystania jej jako ukrytego pokrycia atlasu?

EDYCJA: Poczyniłem niewielkie postępy w tym zakresie - możesz używać stylizacji opartej na regułach, aby włączać i wyłączać funkcje istotne dla bieżącej funkcji pokrycia atlasu. to faktycznie działa dobrze, jeśli wszystko, co chcesz zrobić, to pokazać inny zestaw punktów. Teraz patrzę na przywiązanie tego do schematu kolorów i reaktywnej legendy.

JonoPatterson
źródło
1
Jest to w zasadzie duplikat gis.stackexchange.com/questions/155143
Chris W
Dzięki Chris - ale nie jestem pewien, czy tak jest. Ten wygląda na pytanie, czy możesz zrobić sub-atlas dla każdego obszaru w oryginalnym atlasie? np. 4 obszary z 4 stronami? (Mimo że starałem się śledzić to, o co proszono)
JonoPatterson
1
Nie, zasadniczo oboje chcecie stworzyć serię map. Seria pokazuje ten sam zasięg mapy i podstawowe informacje, ale różne funkcje w każdym z nich. Mój komentarz mówi o linkach do robienia tego w ArcGIS poprzez tak zwane zapytania definicji strony - to znaczy każda strona w atlas / mapbook ma zapytanie definicji, które określa, które warstwy / funkcje są wyświetlane na tej stronie. On chce serii seriali, w których chcesz tylko jedną serię. Jednak nie wiem, czy QGIS oferuje taką funkcjonalność (myślałem, że przeczytam odpowiedź / komentarz, że tak nie jest, ale nie mogę tego teraz znaleźć).
Chris W
Ponadto w twoim przypadku możesz wygenerować ramki ograniczające na podstawie zasięgu każdego punktu o tych samych atrybutach, a następnie użyć ich jako funkcji indeksu, ale nadal masz problem z automatycznym włączaniem i wyłączaniem różnych grup punktów . Nawet jeśli podzielisz je na osobne warstwy, bez jakiejkolwiek definicji zapytania nie ma sposobu, aby wyłączyć te punkty na danej stronie.
Chris W
Tak, nie żyjesz. Jest to także powtórzenie tego jednego gis.stackexchange.com/questions/121802/... - więc może będę musiał to zrobić ręcznie.
JonoPatterson

Odpowiedzi:

9

W końcu rozwiązałem to dla moich celów, więc oto rozwiązanie, które wymyśliłem, jeśli pomaga komukolwiek:

Napisz skrypt Pythona (mój na końcu tego), który zasadniczo robi to:

  1. zidentyfikować unikalne kategorie w polu zainteresowania warstwy punktowej
  2. dla każdej kategorii wybierz wszystkie pasujące punkty i ustal zasięg tego zestawu
  3. dla każdego zakresu wygeneruj nowy wielokąt w warstwie pokrycia pustego atlasu z kluczowym atrybutem „CategoryName”

To dało mi warstwę pokrycia atlasu z jednym wielokątem dla każdej kategorii zainteresowań wyglądającej tak: Warstwa pokrycia Atlas

Skonfiguruj atlas i drukuj kompozytora jak zwykle - pozostawiając jedynie problem z wyłączaniem i włączaniem funkcji.

W tym celu jest trochę prób i błędów, aby opracować dokładny zestaw opcji:

  1. Poniższe wyrażenie pozwala uzyskać wartość aktualnie przechowywaną w polu CategoryName dla bieżącej funkcji atlasu

    attribute ($atlasfeature, 'CategoryName') 
    
  2. Służy do tworzenia stylów opartych na regułach dla warstwy punktowej wzdłuż linii

    attribute ($atlasfeature, 'CategoryName') = PointCategory AND PointCategory = "RedDots"
    
  3. Miałem również zasadę gwarantującą, że wszystkie pozostałe stały się przejrzyste

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

Pokazane zasady

Testowanie tego za pomocą atlasu działa naprawdę dobrze. Na koniec zastosuj to samo podejście, aby manipulować wyświetlanymi etykietami, spraw, aby etykiety były dynamiczne i odpowiednio filtruj tabele. Zaznaczenie „filtruj legendę według zawartości mapy” jest również bardzo skuteczne, jeśli nie chcesz wszystkich elementów legendy na wszystkich mapach.

Ostateczny zestaw atlasów:

Atlas oparty na cechach

Edytuj - zgodnie z prośbą, oto mój skrypt:

    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
źródło
3
@JonoPatterson, jeśli teraz podzielisz się swoim skryptem Pythona wspomnianym na początku, będzie to najlepsza odpowiedź w historii;)
Bernd V.,
Ok to zrobi - chociaż jest z grubsza gotowy, więc będzie potrzebował kilku poprawek (nie robiłem żadnego kodowania od lat!). Jak najlepiej to zrobić - po prostu wklej do pudełka z kodem?
JonoPatterson
@JonoPatterson Bardzo dziękuję za skrypt. Dla mnie jako początkującego wygląda to już bardzo dobrze :). Jestem pewien, że będę tego wkrótce potrzebować.
Bernd V.
Twoje przykładowe wyrażenia są nieco niepoprawne - powinno to być „$ atlasfeature”, a nie „$ atlasfeatureid”
ndawson