GIS中的一个常见要求是将处理工具应用于多个文件,或者将一个文件中多个特征的处理应用于另一个文件。
这些操作中的许多操作都是令人尴尬地并行的,因为计算结果绝不会影响循环中的任何其他操作。不仅如此,而且输入文件通常每个都是不同的。
一个典型的例子就是将形状文件与包含多边形的文件进行平铺。
这是一个(经过测试的)经典过程方法,可通过QGIS的python脚本实现。(将临时内存文件输出为真实文件的时间比处理我的测试文件的时间减少了一半以上)
import processing
import os
input_file="/path/to/input_file.shp"
clip_polygons_file="/path/to/polygon_file.shp"
output_folder="/tmp/test/"
input_layer = QgsVectorLayer(input_file, "input file", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(input_layer)
tile_layer = QgsVectorLayer(clip_polygons_file, "clip_polys", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(tile_layer)
tile_layer_dp=input_layer.dataProvider()
EPSG_code=int(tile_layer_dp.crs().authid().split(":")[1])
tile_no=0
clipping_polygons = tile_layer.getFeatures()
for clipping_polygon in clipping_polygons:
print "Tile no: "+str(tile_no)
tile_no+=1
geom = clipping_polygon.geometry()
clip_layer=QgsVectorLayer("Polygon?crs=epsg:"+str(EPSG_code)+\
"&field=id:integer&index=yes","clip_polygon", "memory")
clip_layer_dp = clip_layer.dataProvider()
clip_layer.startEditing()
clip_layer_feature = QgsFeature()
clip_layer_feature.setGeometry(geom)
(res, outFeats) = clip_layer_dp.addFeatures([clip_layer_feature])
clip_layer.commitChanges()
clip_file = os.path.join(output_folder,"tile_"+str(tile_no)+".shp")
write_error = QgsVectorFileWriter.writeAsVectorFormat(clip_layer, \
clip_file, "system", \
QgsCoordinateReferenceSystem(EPSG_code), "ESRI Shapefile")
QgsMapLayerRegistry.instance().addMapLayer(clip_layer)
output_file = os.path.join(output_folder,str(tile_no)+".shp")
processing.runalg("qgis:clip", input_file, clip_file, output_file)
QgsMapLayerRegistry.instance().removeMapLayer(clip_layer.id())
可以,除了我的输入文件为2GB且多边形裁剪文件包含400多个多边形之外,这是可以的。在我的四核计算机上,完成的过程需要一周以上的时间。同时,三个核心都处于闲置状态。
我想到的解决方案是将进程导出到脚本文件,然后使用gnu parallel例如异步运行它们。但是,不得不退出QGIS进入特定于操作系统的解决方案,而不是使用QGIS python本身的东西似乎很可耻。所以我的问题是:
我可以在python QGIS内部对令人尴尬的并行地理操作进行并行处理吗?
如果不是,那么也许有人已经拥有将这类工作发送给异步Shell脚本的代码?