重力/霍夫模型工具


26

我正在寻找一种使用基于点的图层来模拟重力模型的方法。

我所有的点都分配有一个z值,该值越高,其“影响范围”就越大。这种影响与到中心的距离成反比。

这是一个典型的霍夫模型,每个点都是局部最大值,它们之间的谷表明它们之间影响区域的极限。

我尝试了Arcgis(IDW,成本分配,多项式插值)和QGIS(热图插件)中的几种算法,但没有发现任何对我有帮助的算法。我也找到了这个线程,但是对我不是很有帮助。

或者,如果有一种方法可以通过相应点的z值影响每个像元的大小,那么我也可以通过生成Voronoi图的方式来满足。

Answers:


13

这是一个实现此功能的QGIS python小功能。它需要rasterlang插件(必须将存储库手动添加到QGIS)。

它需要三个必填参数:点层,栅格层(用于确定输出的大小和分辨率)以及输出层的文件名。您还可以提供一个可选参数来确定距离衰减函数的指数。

点的权重必须位于点层的第一属性列中。

生成的栅格将自动添加到画布。

这是如何运行脚本的示例。这些点的权重在20到90之间,并且网格的大小为60 x 50地图单位。

points = qgis.utils.iface.mapCanvas().layer(0)
raster = qgis.utils.iface.mapCanvas().layer(1)
huff(points,raster,"output.tiff",2)

from rasterlang.layers import layerAsArray
from rasterlang.layers import writeGeoTiff
import numpy as np

def huff(points, raster, outputfile, decay=1):
    if points.type() != QgsMapLayer.VectorLayer:
        print "Error: First argument is not a vector layer (but it has to be)"
        return
    if raster.type() != QgsMapLayer.RasterLayer:
        print "Error: Second argument is not a raster layer (but it has to be)"
        return
    b = layerAsArray(raster)
    e = raster.extent()
    provider = points.dataProvider()
    extent = [e.xMinimum(),e.yMinimum(),e.xMaximum(),e.yMaximum()]
    xcols = np.size(layerAsArray(raster),1)
    ycols = np.size(layerAsArray(raster),0)
    xvec = np.linspace(extent[0], extent[2], xcols, endpoint=False)
    xvec = xvec + (xvec[1]-xvec[0])/2
    yvec = np.linspace(extent[3], extent[1], ycols, endpoint=False)
    yvec = yvec + (yvec[1]-yvec[0])/2
    coordArray = np.meshgrid(xvec,yvec)
    gravity = b
    point = QgsFeature()
    provider.select( provider.attributeIndexes() )
    while provider.nextFeature(point):
      coord = point.geometry().asPoint()
      weight = point.attributeMap()[0].toFloat()[0]
      curGravity = weight * ( (coordArray[0]-coord[0])**2 + (coordArray[1]-coord[1])**2)**(-decay/2)
      gravity = np.dstack((gravity, curGravity))
    gravitySum = np.sum(gravity,2)
    huff = np.max(gravity,2)/gravitySum
    np.shape(huff) 
    writeGeoTiff(huff,extent,outputfile)
    rlayer = QgsRasterLayer(outputfile)
    QgsMapLayerRegistry.instance().addMapLayer(rlayer)

3
(+1)方法看起来不错。但是,为什么要在计算中取平方根然后重新平方呢curGravity?那是浪费计算时间。另一套浪费的计算包括在找到最大值之前对所有“重力”网格进行归一化:相反,找到它们的最大值并通过总和对其进行归一化。
whuber

那不是整个分数的平方吗?
lynxlynxlynx

1
杰克,您仍然永远不需要平方根:只需完全忽略它,并使用一半的预期指数即可。换句话说,如果z是坐标差的平方和,而不是计算(sqrt(z))^ p(这是两个中等昂贵的运算),只需计算z ^(p / 2),因为(因为p / 2是一个预先计算的数字)只是一个栅格操作-并导致更清晰的代码。当您应用引力模型的初衷时,这个想法就浮出水面:旅行。不再存在平方根公式,因此将行进时间提高到-p / 2幂。
Whuber

非常感谢,这看起来像我需要的。只是一个问题,我不太习惯python,也从未使用过Rasterlang扩展。我在QGIS版本上安装了它,但是遇到了“语法错误”。您的功能已经在rasterlang扩展中实现了吗?如果没有,我该怎么办?感谢您的帮助!http://i.imgur.com/NhiAe9p.png
Damien

1
@Jake:好的,我想我开始了解控制台的工作原理。我照你说的做了,代码似乎被正确理解了。现在,我有另一个与python软件包“ shape_base.py”有关的错误。我的QGIS安装是否缺少某些功能?http://i.imgur.com/TT0i2Cl.png
Damien 2013年
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.