如何基于点属性创建地图集?


9

本质上,我想基于点层中的分类字段生成图集。

即,我有一个带有分类字段“ Provision”的托儿服务提供者点层。我已经用“课后俱乐部”,“早餐俱乐部”等对该字段中的每个功能进行了分类,现在我想生成一组地图,这些地图在每个类别中进行迭代,并仅显示每个类别的要点。一张课后俱乐部地图,一张早餐俱乐部地图等。程度可能略有不同。

我可以一个一个地做,但是似乎应该有一种方法可以根据每个类别的范围来制作图集?(我确实觉得我缺少明显的东西:))

或者,是否有一种方法可以自动创建多边形图层,并将其用作图集的隐藏范围?

编辑:我在此方面取得了一些进展-您可以使用基于规则的样式来打开和关闭与当前地图集覆盖范围功能相关的功能。如果您只想显示一组不同的点,它实际上就可以正常工作。我现在正在考虑将其与配色方案和反应性图例联系起来。



谢谢克里斯-但不确定是否如此。那似乎是在问您是否可以为原始地图集中的每个区域制作一个子地图集?例如4个区域,每个区域4页?(尽管我确实很难按照要求进行操作)
JonoPatterson 2015年

1
不,基本上你们两个都想创建一个地图系列。该系列显示了相同的地图范围和基础信息,但每个地图项中都有不同的功能。我在这里的评论谈论和链接到ArcGIS中通过所谓的页面定义查询进行的操作-也就是说,图集/地图册中的每个页面都有一个定义查询,该查询确定在该页面上显示哪些图层/要素。他想要一个系列,而您只想要一个系列。但是我不知道QGIS是否还提供了这样的功能(我以为我会读它没有的答案/评论,但现在找不到了)。
克里斯·W

同样,在您的情况下,您可以基于共享相同属性的每个点的范围生成边界框,然后将其用作索引特征,但是仍然存在自动打开和关闭不同点组的问题。即使将它们拆分为单独的层,也没有某种定义查询,也无法在任何给定页面上关闭这些点。
克里斯·W

是的,你死定了。这也是gis.stackexchange.com/questions/121802/…的重复-所以我可能不得不求助于手动。
JonoPatterson 2015年

Answers:


9

我终于为我的目的解决了这个问题,因此这是我想出的解决方案,可以帮助任何人:

编写一个python脚本(本文结尾处是我的脚本),该脚本实际上是这样做的:

  1. 在兴趣点层字段中标识唯一类别
  2. 对于每个类别,选择所有匹配点并确定此集合的范围
  3. 对于每个范围,在空白图集覆盖层中生成一个具有关键属性“ CategoryName”的新多边形

这给了我地图集覆盖层,每个感兴趣的类别都有一个多边形,如下所示: 地图集覆盖层

按常规配置图集和打印作曲器-仅剩下关闭和打开功能的问题。

为此,要找出确切的选项集需要反复尝试:

  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脚本,这将是有史以来最好的答案;)
Bernd V.

好的,可以这样做-尽管它已经准备好了,所以需要做一些调整(多年来没有做任何编码!)。最好的方法是什么-仅粘贴在代码框中?
JonoPatterson 2015年

@JonoPatterson非常感谢您的脚本。对于我作为一个初学者来说,这已经非常不错了:)。我敢肯定我会很快需要的。
Bernd V.

您的示例表达式有点错误-它应该是“ $ atlasfeature”,而不是“ $ atlasfeatureid”
ndawson
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.