Я наконец решил это для своих целей, так что вот решение, которое я придумал, если оно кому-нибудь поможет:
Напишите скрипт на python (мой в конце этого), который по сути делает это:
- определить уникальные категории в поле интереса точечного слоя
- для каждой категории выберите все подходящие точки и установите степень этого набора
- для каждого экстента создайте новый многоугольник в пустом слое покрытия атласа с ключевым атрибутом «CategoryName»
Это дало мне слой покрытия атласа с одним полигоном для каждой интересующей категории, выглядящий следующим образом:
Сконфигурируйте атлас и распечатайте композитор как обычно - оставив только проблему выключения и включения функций.
Для этого нужно немного проб и ошибок отработать точный набор опций:
Выражение ниже позволяет вам получить значение, которое в данный момент содержится в поле CategoryName для текущей функции атласа.
attribute ($atlasfeature, 'CategoryName')
Используйте это для создания стиля на основе правил для точечного слоя вдоль линий
attribute ($atlasfeature, 'CategoryName') = PointCategory AND PointCategory = "RedDots"
У меня также было правило, чтобы гарантировать, что все остальные стали прозрачными
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 )