重力/ハフモデルツール


26

ポイントベースのレイヤーを使用して重力モデルをシミュレートする方法を探しています。

すべてのポイントにはZ値が割り当てられ、この値が高いほど、「影響範囲」が大きくなります。この影響は、中心までの距離に反比例します。

これは典型的なハフモデルであり、各ポイントは極大値であり、それらの間の谷はそれらの間の影響ゾーンの限界を示します。

Arcgisのいくつかのアルゴリズム(IDW、コスト割り当て、多項式補間)およびQGIS(ヒートマッププラグイン)を試しましたが、私に役立つものは何も見つかりませんでした。このスレッドも見つけましたが、あまり役に立ちません。

別の方法として、対応するポイントのz値によって各セルのサイズに影響を与える方法がある場合、ボロノイ図を生成する方法でも満足できます。

回答:


13

これを実装する小さなQGIS python関数を次に示します。rasterlangプラグインが必要です(リポジトリはQGISに手動で追加する必要があります)。

3つの必須パラメーターが必要です:ポイントレイヤー、ラスターレイヤー(出力のサイズと解像度を決定するため)、および出力レイヤーのファイル名。オプションの引数を指定して、距離減衰関数の指数を決定することもできます。

ポイントの重みは、ポイントレイヤーの最初の属性列にある必要があります。

結果のラスタ​​は、キャンバスに自動的に追加されます。

スクリプトを実行する方法の例を次に示します。ポイントのウェイトは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が座標差の2乗和である場合、2つの適度に高価な演算である(sqrt(z))^ pを計算する代わりに、z ^(p / 2)を計算するだけです(p / 2は事前に計算された数値です)は1つのラスター操作であり、コードもより明確になります。この考えは、重力モデルを当初の意図通りに適用した場合、つまり移動時間に適用される場合に前面に出ます平方根の式はもうないので、移動時間を-p / 2乗します。
whuber

どうもありがとう、これは私が必要なもののように見えます。ただ問題ですが、私はPythonにそれほど慣れておらず、Rasterlang拡張機能を使用したことはありません。QGISバージョンにインストールしましたが、「構文エラー」が発生しています。関数は既にrasterlang拡張機能に実装されていますか?いいえの場合、どうすればいいですか?助けてくれてありがとう!http://i.imgur.com/NhiAe9p.png-
ダミアン

1
@Jake:わかりました、コンソールの仕組みを理解し始めたと思います。あなたが言ったように私はやったし、コードは正しく理解されているようだ。Pythonパッケージ「shape_base.py」に関連する別のエラーが発生しました。QGISのインストールにはいくつかの機能がありませんか?http://i.imgur.com/TT0i2Cl.png
ダミアン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.