使用PyQGIS生成大量地图?


10

我必须制作大量(数百种)物种分布图。我有一个shapefile,其中包含每个物种的分布,对于每个物种,我都希望获得一张地图,作为图像(jpg,png或其他格式),其中包含有关物种的名称,图例(以区分不同物种的区域)。年度分布,繁殖,非繁殖等...)。

我想使用QGIS来做到这一点。


1
您能否详细说明一下地图的细节?例如,您是否希望所有这些地图都显示相同的区域(例如特定的大陆或国家/地区),还是希望地图范围动态变化?另外,您是否希望所有范围子类型都在一张地图上还是在多张地图上?根据这些答案,您的问题可能非常简单,或者可能需要更多复杂的方法。一个不错的起点是GIS的Atlas插件,或者如果您有ArcGIS 10或更高版本,ESRI的地图册也将提供帮助。
杰·瓜纳里

1
抱歉,缺少详细信息。是的,对于所有地图,它将是同一区域(欧洲)。我有一个shapefile,其中包含所有种类,并在属性中包含相应的分布。我可以很容易地将此​​shapefile拆分为不同的shapefile(每个种类一个)。最后,我想为每个物种提供一张图片,并在每个时间都有完全相同的区域(欧洲),相同的颜色(例如,深绿色的年度分布,浅绿色的繁殖,蓝色等。。。),相同的图例,以及标题的名称。
Onesime 2013年

我认为您需要做的是计划出制作每张地图所需的每个步骤,然后用Python编码选择内容和地图导出。我知道可以在ArcGIS Python中轻松完成此操作,但是我对QGIS Python接口的了解还不足以提供很多指导。但是,我相信您可以使用一个shapefile进行这项工作。
Jay Guarneri 2013年

我已经使用Python插件对QGIS做过类似的事情。就我而言,我的图层存储在PostGIS中,但是我认为您可以使用shapefile做类似的事情。我很高兴分享我的代码。下午我。
Brian Edmond

1
您能否上传数据样本供我们使用。
内森·W

Answers:


4

我有一个类似的要求,并基于一个Shapefile文件,将其放置在所有物种的点位置上,从而将QGIS插件组合在一起以生成地图(它假定属性表中的唯一分类名称为公共标识符)。我的要求并不那么复杂-我不需要季节性信息,标题或传说,但这可能对您有用。对于更复杂的方面,您将需要使用地图编辑器。有关更多信息,请参见PyQGIS食谱

插入

该插件可自动创建地图,并允许您配置范围,分辨率和其他方面。它将与网格覆盖相同的样式应用于输出。当前,它仅在QGIS的开发版本(1.9或更高版本)上运行。

Sextante脚本

在制作插件之前,我先使用SEXTANTE确定了逻辑。此用户脚本也应在1.8中运行(尚未测试)。分发样式文件(.qml)是输出分发的样式(它忽略分发覆盖的样式)。当前,它根据您的操作系统默认值(Linux中的/ tmp,以及Windows中的各个位置-由TEMP环境变量定义)将输出映射放置在temp目录中。您可以在代码中轻松定义自己。您还需要在代码中编辑范围和输出分辨率(如果要为大海使用其他颜色,则需要编辑背景颜色)。

#Definition of inputs and outputs
#==================================
##[Scratch]=group
##all_localities=vector
##taxon_field=field all_localities
##africa_map=vector
##sa_map=vector
##grid_layer=vector
##distribution_style_file=file

#Algorithm body
#==================================
from qgis.core import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sextante.core.QGisLayers import QGisLayers
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
import tempfile
import os

def print_map(taxon,taxon_shp):
    #load taxon layer (necessary?)
    #QGisLayers.load(taxon_shp,name = "taxon",style = distribution_style_file)
    taxon_layer = QgsVectorLayer(taxon_shp,"taxon","ogr")
    QgsMapLayerRegistry.instance().addMapLayer(taxon_layer)
    taxon_layer.loadNamedStyle(distribution_style_file)

    # create image (dimensions 325x299)
    img = QImage(QSize(325,299), QImage.Format_ARGB32_Premultiplied)

    # set image's background color
    color = QColor(192,192,255)   # blue sea
    img.fill(color.rgb())

    # create painter
    p = QPainter()
    p.begin(img)
    p.setRenderHint(QPainter.Antialiasing)

    render = QgsMapRenderer()

    # create layer set
    africa_layer = QGisLayers.getObjectFromUri(africa_map)
    sa_layer = QGisLayers.getObjectFromUri(sa_map)
    #taxon_layer = QGisLayers.getObjectFromUri(taxon_shp)

    lst = []
    lst.append(taxon_layer.id())    
    lst.append(sa_layer.id())
    lst.append(africa_layer.id())

    render.setLayerSet(lst)

    # set extent (xmin,ymin,xmax,ymax)
    rect = QgsRectangle(14.75,-36.00,34.00,-21.00)
    render.setExtent(rect)

    # set output size
    render.setOutputSize(img.size(), img.logicalDpiX())

    # do the rendering
    render.render(p)
    p.end()

    # save image
    #outdir = os.path.dirname(os.path.abspath(output))
    tempdir = tempfile.gettempdir()
    img.save(os.path.join(tempdir,taxon+".png"),"png")

    # remove taxon layer from project
    QgsMapLayerRegistry.instance().removeMapLayers([taxon_layer.id()])

tempdir = tempfile.gettempdir()   
taxa = sextante.runalg('qgis:listuniquevalues', all_localities, taxon_field, None)['UNIQUE_VALUES'].split(";")
for taxon in taxa:
    sextante.runalg('qgis:selectbyattribute', all_localities, taxon_field, 0, taxon)
    sextante.runalg('qgis:selectbylocation', grid_layer, all_localities, 0)
    filename = os.path.join(tempdir,"taxon.shp")    #memory file better?
    sextante.runalg('qgis:saveselectedfeatures', grid_layer, filename)
    print_map(taxon,filename)

大家好,感谢您的所有答复。为了给您提供更多的元素,它是来自BirdLife的数据(specie的示例:birdlife.org/datazone/speciesfactsheet.php? id= 2794)。简而言之,有一个shapefile,其中包含所有物种的所有多边形(因此,对于某些物种来说,一个物种有很多线),并且存在一个与季节分布相对应的属性(值从1到5对应于不同的用途) ),另外一个用于起源等。图例和标题不是必不可少的。
Onesime 2013年

-我在背景中使用国家/地区图层,只是为了方便放置。-对于与“季节”属性不同值的不同颜色,我认为适合使用.qml文件。-可选地,对于标题和图例,我认为我必须使用composer中的文件,如果太难了,可以与其他软件一起添加。-必须对所有种类重复该操作,因此,这对应于按属性进行的选择,该属性将用于指定最终图片的名称。
Onesime 2013年

我尝试使用插件“ Atlas”,但它似乎更适合于各个位置,就我而言,它一直在同一地区使用:欧洲。我尝试了插件“ Distribution map manager”,因为它可以修复覆盖区域,但似乎在这一点上是相对应的,但是我不需要具有与网格层相交的过程,因为我已经有了一个多边形层。我在ArcGis中尝试过,但对于QGis Atlas插件来说却完全相同,解决方案似乎是编写python脚本...
Onesime 2013年

因此,我想我将基于“ rudivonstaden”脚本使用Sextante(感谢您!)并将其适应我的情况。最后,对不起这些不同的评论,但有一个字符数限制...
Onesime 2013年

@Onesime,除了标题和图例之外,我认为您可以适应上面的六边形脚本来完成所需的操作。您可能需要删除该selectbylocation步骤,并为每个季节添加一个额外的selectbyattributesaveselectedfeatures步骤(更改grid_layerall_localities)。然后加载更多.qml文件并添加附加您的季节性shapefile(最前面附加的顶层)。如果您不确定如何操作,我可能可以尝试编辑上面的脚本以进行或多或少的工作。
rudivonstaden 2013年

2

我今天花了一些时间来做这个。因此,我对您的脚本进行了一些更改。我不需要添加其他selectbyattribute和saveselectedfeatures步骤,因为我使用的是.qml文件,并且Seasonal字段位于同一shapefile中。在下面,您可以看到我做了什么:

#Definition of inputs and outputs
#==================================
##[Scratch]=group
##all_localities=vector
##taxon_field=field all_localities
##seasonal_field=field all_localities
##countries_map=vector
##distribution_style_file=file
##output_folder=folder

#Algorithm body
#==================================
from qgis.core import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sextante.core.QGisLayers import QGisLayers
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
import tempfile
import os

def print_map(taxon,taxon_shp):
#load taxon layer (necessary?)
#QGisLayers.load(taxon_shp,name = "taxon",style = distribution_style_file)
taxon_layer = QgsVectorLayer(taxon_shp,"taxon","ogr")
QgsMapLayerRegistry.instance().addMapLayer(taxon_layer)
taxon_layer.loadNamedStyle(distribution_style_file)

# create image (dimensions 325x299)
img = QImage(QSize(325,299), QImage.Format_ARGB32_Premultiplied)

# set image's background color
color = QColor(221,249,254)   # blue sea
img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

render = QgsMapRenderer()

# create layer set
countries_layer = QGisLayers.getObjectFromUri(countries_map)
taxon_layer = QGisLayers.getObjectFromUri(taxon_shp)

lst = []
lst.append(taxon_layer.id())    
lst.append(countries_layer.id())
render.setLayerSet(lst)

# set extent (xmin,ymin,xmax,ymax)
rect = QgsRectangle(-11,32,39,71)
render.setExtent(rect)
# set output size
render.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
render.render(p)
p.end()

#save image
#outdir = os.path.dirname(os.path.abspath(output))
tempdir = output_folder
img.save(os.path.join(tempdir,taxon+".png"),"png")

# remove taxon layer from project
QgsMapLayerRegistry.instance().removeMapLayers([taxon_layer.id()])

tempdir = tempfile.gettempdir()  

taxa = sextante.runalg('qgis:listuniquevalues', all_localities, taxon_field, None)        ['UNIQUE_VALUES'].split(";")

for taxon in taxa:
sextante.runalg('qgis:selectbyattribute', all_localities, taxon_field, 0, taxon)
filename = os.path.join(tempdir,"taxon.shp")    #memory file better?
sextante.runalg('qgis:saveselectedfeatures', all_localities, filename)
print_map(taxon,filename)

如果您有任何意见或建议来改进它,请不要犹豫。

为了对其进行改进,最好是在选择范围时(例如欧洲),它使用此范围仅选择此范围内包括的物种。这是因为我获得了所有物种的地图,甚至包括欧洲以外的物种(因此我有很多空的地图)。您认为这可能吗?

干杯,

奥尼西姆

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.