중력 / 허프 모델 도구


26

포인트 기반 레이어를 사용하여 중력 모델을 시뮬레이션하는 방법을 찾고 있습니다.

내 모든 포인트에는 z 값이 할당되고이 값이 높을수록 "영향 영역"이 커집니다. 이 영향은 중심까지의 거리에 반비례합니다.

일반적인 허프 모델이며 각 점은 로컬 최대 값이며 그 사이의 골짜기는 그들 사이의 영향 영역의 한계를 나타냅니다.

Arcgis (IDW, 비용 할당, 다항 보간) 및 QGIS (heatmap plugin)에서 몇 가지 알고리즘을 시도했지만 도움이되는 것은 없습니다. 나는 또한이 스레드를 찾았 지만 나에게별로 도움이되지 않습니다.

대안으로, 해당 지점의 z 값으로 각 셀의 크기에 영향을 줄 수있는 방법이 있다면 Voronoi 다이어그램을 생성하는 방법으로도 만족할 수 있습니다.

답변:


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를 계산하는 대신 (sqrt (z)) ^ p를 계산하면 z ^ (p / 2) 만 계산합니다. 미리 계산입니다 숫자가 너무 선명 코드 리드 -) 한 래스터 작업입니다. 이 아이디어는 원래 의도했던대로 중력 모델을 적용 할 때 가장 중요합니다 . 이동 시간. 더 이상 제곱근 공식이 없으므로 이동 시간을 -p / 2 제곱으로 올립니다.
whuber

고마워요, 이것은 내가 필요한 것 같습니다. 그냥 문제는, 나는 파이썬에 익숙하지 않으며 Rasterlang 확장을 사용하지 않았습니다. QGIS 버전에 설치했지만 "구문 오류"가 발생합니다. 함수가 이미 rasterlang 확장에 구현되어 있습니까? 아니라면 어떻게해야합니까? 도와 주셔서 감사합니다! http://i.imgur.com/NhiAe9p.png
Damien

1
@Jake : 좋아, 나는 콘솔이 어떻게 작동하는지 이해하기 시작한다고 생각한다. 나는 당신이 말한대로했고 코드는 올바르게 이해되는 것 같습니다. 이제 파이썬 패키지 "shape_base.py"와 관련된 또 다른 오류가 있습니다. QGIS 설치에 일부 기능이 부족합니까? http://i.imgur.com/TT0i2Cl.png
Damien
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.