Как создать Атлас на основе точечных атрибутов?


9

По сути, я хочу создать атлас на основе категориального поля в точечном слое.

то есть у меня есть точечный слой поставщиков услуг по уходу за детьми с категориальным полем «Предоставление». Я классифицировал каждую функцию в этом поле как «After School Club», «Breakfast Club» и т. Д., И теперь я хочу создать набор карт, которые повторяют каждую категорию и показывают только точки для каждой. Одна карта клубов после школы, одна карта клубов для завтрака и т. Д. Степени могут быть немного разными.

Я мог бы сделать это один за другим, но кажется, что должен быть способ создать атлас, основанный на экстентах каждой категории? (Я чувствую, что упускаю что-то очевидное :))

Или, альтернативно, есть ли способ автоматизировать создание многоугольного слоя и использовать его в качестве скрытого покрытия для атласа?

РЕДАКТИРОВАТЬ: я добился небольшого прогресса в этом - вы можете использовать правила на основе правил для включения и выключения функций, относящихся к текущей функции покрытия атласа. это на самом деле работает нормально, если все, что вы хотите сделать, это показать другой набор точек. Сейчас я смотрю, как привязать это к цветовой схеме и реактивной легенде.



Спасибо Крис - но не уверен, что это так. Тот, кажется, спрашивает, можете ли вы сделать податлас для каждой области в оригинальном атласе? например 4 области каждая с 4 страницами? (Хотя я изо всех сил пытался следовать тому, о чем просили)
JonoPatterson

1
Нет, в основном вы оба хотите создать серию карт. Серия показывает одинаковый экстент карты и базовую информацию, но разные функции в каждой. Мой комментарий там говорит и ссылается на это в ArcGIS через так называемые запросы определения страницы, то есть каждая страница в атласе / карте содержит запрос определения, который определяет, какие слои / объекты отображаются на этой странице. Он хочет серию сериалов, где вы просто хотите одну серию. Однако я не знаю, предлагает ли QGIS такую ​​функциональность (я думал, что прочту ответ / комментарий, которого нет, но сейчас не могу его найти).
Крис W

Кроме того, в вашем случае вы можете сгенерировать ограничивающие блоки на основе экстентов каждой точки, совместно использующих одни и те же атрибуты, а затем использовать их в качестве объектов индекса, но у вас все еще остается проблема автоматического включения и выключения различных групп точек. , Даже если вы разделите их на отдельные слои, без какого-либо запроса определения невозможно отключить эти точки на любой странице.
Крис W

Да, твой мертвец на. Это также повторение этого gis.stackexchange.com/questions/121802/… - поэтому мне, возможно, придется прибегнуть к ручному выполнению.
JonoPatterson

Ответы:


9

Я наконец решил это для своих целей, так что вот решение, которое я придумал, если оно кому-нибудь поможет:

Напишите скрипт на python (мой в конце этого), который по сути делает это:

  1. определить уникальные категории в поле интереса точечного слоя
  2. для каждой категории выберите все подходящие точки и установите степень этого набора
  3. для каждого экстента создайте новый многоугольник в пустом слое покрытия атласа с ключевым атрибутом «CategoryName»

Это дало мне слой покрытия атласа с одним полигоном для каждой интересующей категории, выглядящий следующим образом: Слой покрытия Atlas

Сконфигурируйте атлас и распечатайте композитор как обычно - оставив только проблему выключения и включения функций.

Для этого нужно немного проб и ошибок отработать точный набор опций:

  1. Выражение ниже позволяет вам получить значение, которое в данный момент содержится в поле CategoryName для текущей функции атласа.

    attribute ($atlasfeature, 'CategoryName') 
    
  2. Используйте это для создания стиля на основе правил для точечного слоя вдоль линий

    attribute ($atlasfeature, 'CategoryName') = PointCategory AND PointCategory = "RedDots"
    
  3. У меня также было правило, чтобы гарантировать, что все остальные стали прозрачными

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

Правила показаны

Проверка этого с помощью атласа работает очень хорошо. Наконец, просто используйте тот же подход для манипулирования показанными метками, сделайте метки динамическими и отфильтруйте таблицы соответствующим образом. Отметка «Фильтровать легенду по содержанию карты» также очень эффективна, если вы не хотите, чтобы все элементы легенды были на всех картах.

Окончательный набор атласа:

Атлас, основанный на функциях

Отредактируйте - как это просили, вот мой сценарий:

    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, если бы вы сейчас также поделились своим скриптом Python, упомянутым в начале, это был бы лучший ответ за всю историю;)
Бернд В.

Хорошо, мы сделаем это - хотя его грубый п готов, так что ему понадобятся некоторые настройки (не кодировал годами!). Какой лучший способ сделать это - просто вставить в кодовое поле?
JonoPatterson

@JonoPatterson Большое спасибо за сценарий. Для меня, как новичка, это уже выглядит очень хорошо :). Я уверен, что мне это понадобится в ближайшее время.
Бернд В.

Выражения вашего примера немного неправильны - это должно быть «$ atlasfeatureid», а не «$ atlasfeatureid»
ndawson
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.