Я нарешті вирішив це для своїх цілей, тому ось рішення, яке я придумав, якщо це комусь допоможе:
Напишіть сценарій 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 )