Гравітація / інструменти Хаффа


26

Я шукаю спосіб імітувати гравітаційну модель за допомогою точкового шару.

Всі мої бали присвоюються z-значенням і чим вище це значення, тим більша їх "сфера впливу". Цей вплив обернено пропорційний відстані до центру.

Це типова модель Хаффа, кожна точка є локальним максимумом, а долини між ними вказують межі зони впливу між ними.

Я спробував кілька алгоритмів від Arcgis (IDW, розподіл витрат, поліноміальна інтерполяція) та QGIS (плагін-термінал), але я не знайшов нічого, що могло б мені допомогти. Я також знайшов цю тему , але це не дуже допомагає мені.

Як альтернативу, я також міг би бути задоволений способом генерації діаграм Вороного, якщо є спосіб вплинути на розмір кожної комірки z-значенням відповідної точки.

Відповіді:


13

Ось невелика функція QGIS python, яка реалізує це. Для цього потрібен плагін rasterlang (репозиторій потрібно додати до QGIS вручну).

Він очікує трьох обов’язкових параметрів: точковий шар, растровий шар (для визначення розміру та роздільної здатності виводу) та ім'я файлу для вихідного шару. Ви також можете надати необов'язковий аргумент для визначення показника функції занепаду відстані.

Ваги для очок повинні бути в першому стовпчику атрибутів шару точок.

Отриманий растр автоматично додається до полотна.

Ось приклад того, як запустити скрипт. Очки мають вагу між 20 і 90, а сітка розміром 60 на 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
Дамієн

1
@Jake: Гаразд, я думаю, я починаю розуміти, як працює консоль. Я зробив, як ви сказали, і код, здається, розуміється правильно. Тепер у мене є ще одна помилка, яка стосується пакету python "shape_base.py". У моїй установці QGIS відсутні деякі функції? http://i.imgur.com/TT0i2Cl.png
Дамієн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.