Yerçekimi / Huff model araçlar


26

Nokta tabanlı bir katman kullanarak bir yerçekimi modelini simüle etmenin bir yolunu arıyorum.

Tüm puanlarıma bir z değeri verilir ve bu değer ne kadar yüksek olursa, "etki alanı" da o kadar büyük olur. Bu etki, merkeze olan uzaklık ile ters orantılıdır.

Tipik bir Huff modelidir, her nokta yerel bir maksimumdur ve aralarındaki vadiler, aralarındaki etki bölgesinin sınırlarını belirtir.

Arcgis (IDW, maliyet tahsisi, polinom interpolasyonu) ve QGIS'den (heatmap eklentisi) birkaç algoritma denedim, ancak bana yardımcı olabilecek hiçbir şey bulamadım. Bu konuyu da buldum , fakat bu benim için pek yardımcı değil.

Alternatif olarak, eğer her bir hücrenin büyüklüğünü, karşılık gelen noktanın z-değeri ile etkilemenin bir yolu varsa, Voronoi şemalarını üretmenin bir yolundan da memnun olabilirim.

Yanıtlar:


13

İşte bunu uygulayan küçük bir QGIS python işlevi. Rasterlang eklentisini gerektirir (havuz QGIS'e manuel olarak eklenmelidir).

Üç zorunlu parametre bekler: points katmanı, bir raster katmanı (çıktının boyutunu ve çözünürlüğünü belirlemek için) ve çıktı katmanı için bir dosya adı. Ayrıca mesafe bozulma fonksiyonunun üssünü belirlemek için isteğe bağlı bir argüman sağlayabilirsiniz.

Puanların ağırlıklarının, puan katmanının ilk özellik sütununda olması gerekir.

Elde edilen raster otomatik olarak tuvale eklenir.

İşte betiğin nasıl çalıştırılacağına bir örnek. Noktaların ağırlıkları 20 ile 90 arasındadır ve ızgara, boyut olarak 60 ila 50 harita birimidir.

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) Yaklaşım iyi görünüyor. Ama neden karekökü alıyorsunuz ve sonra onu yeniden hesaplıyorsunuz curGravity? Bu hesaplamalı zaman kaybı. Bir başka boşa harcanmış hesaplama kümesi, max'ı bulmadan önce tüm "yerçekimi" ızgaralarının normalleştirilmesini içerir: bunun yerine, maksimum değerlerini bulun ve bunu toplamla normalleştirin.
whuber

Bu, bütün kesriyi çözmüyor mu?
lynxlynxlynx

1
Jake, hala hiçbir zaman kareköke ihtiyacın yok: sadece tamamen unut ve hedeflenen parçanın yarısını kullan. Başka bir deyişle, z , orta derecede pahalı iki işlem olan hesaplama (sqrt (z)) ^ p yerine, koordinat farklılıklarının karelerinin toplamıysa, sadece z ^ (p / 2) değerini hesaplayın (p / 2, çünkü önceden hesaplanmış bir sayıdır ) sadece bir raster işlemidir - ve ayrıca daha net kodlara da yol açar. Bu fikir, yerçekimi modellerini başlangıçta tasarlandıkları gibi uyguladığınızda ortaya çıkıyor: seyahat süreleri için. Artık herhangi bir karekök formülü yoktur, bu nedenle seyahat süresini -p / 2 gücüne yükseltirsiniz.
whuber

Çok teşekkürler, bu ihtiyacım olana benziyor. Sadece bir sorun, Python'a pek alışkın değilim ve hiçbir zaman Rasterlang eklentisini kullanmamıştım. QGIS sürümüme yükledim, ancak "sözdizimi hatası" ile sıkışıp kaldım. İşleviniz zaten rasterlang uzantısında uygulandı mı? Hayır ise bunu nasıl yaparım? Yardımlarınız için teşekkürler! http://i.imgur.com/NhiAe9p.png
Damien

1
@Jake: Tamam, sanırım konsolun nasıl çalıştığını anlamaya başladım. Dediğiniz gibi yaptım ve kodun doğru anlaşıldığı görülüyor Şimdi "shape_base.py" python paketiyle ilgili başka bir hatam var. QGIS kurulumumda bazı özellikler bulunmuyor mu? http://i.imgur.com/TT0i2Cl.png
Damien
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.