Công cụ mô hình Gravity / Huff


26

Tôi đang tìm cách mô phỏng mô hình trọng lực bằng cách sử dụng lớp dựa trên điểm.

Tất cả các điểm của tôi được gán một giá trị z và giá trị này càng cao thì "phạm vi ảnh hưởng" của chúng càng lớn. Ảnh hưởng này tỷ lệ nghịch với khoảng cách đến trung tâm.

Đó là một mô hình Huff điển hình, mỗi điểm là một cực đại cục bộ và các thung lũng giữa chúng chỉ ra các giới hạn của vùng ảnh hưởng giữa chúng.

Tôi đã thử một số thuật toán từ Arcgis (IDW, phân bổ chi phí, nội suy đa thức) và QGIS (plugin bản đồ nhiệt), nhưng tôi không tìm thấy gì có thể giúp tôi. Tôi cũng tìm thấy chủ đề này , nhưng nó không hữu ích cho tôi.

Cách khác, tôi cũng có thể hài lòng bằng cách tạo sơ đồ Voronoi nếu có cách ảnh hưởng đến kích thước của mỗi ô bằng giá trị z của điểm tương ứng.

Câu trả lời:


13

Đây là một hàm python QGIS nhỏ thực hiện điều này. Nó yêu cầu plugin rasterlang (kho lưu trữ phải được thêm vào QGIS bằng tay).

Nó mong đợi ba tham số bắt buộc: Lớp điểm, lớp raster (để xác định kích thước và độ phân giải của đầu ra) và tên tệp cho lớp đầu ra. Bạn cũng có thể cung cấp một đối số tùy chọn để xác định số mũ của hàm phân rã khoảng cách.

Các trọng số cho các điểm cần phải nằm trong cột thuộc tính đầu tiên của lớp điểm.

Các raster kết quả được tự động thêm vào khung vẽ.

Đây là một ví dụ về cách chạy tập lệnh. Các điểm có trọng lượng từ 20 đến 90 và lưới có kích thước 60 x 50 đơn vị bản đồ.

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) Cách tiếp cận có vẻ tốt. Nhưng tại sao bạn lấy căn bậc hai và sau đó lại bình phương nó trong điện toán curGravity? Đó là một sự lãng phí thời gian tính toán. Một bộ tính toán lãng phí khác liên quan đến việc bình thường hóa tất cả các lưới "trọng lực" trước khi tìm max: thay vào đó, hãy tìm max của chúng và chuẩn hóa nó bằng tổng.
whuber

Không phải nó vuông toàn bộ phần?
lynxlynxlynx

1
Jake, bạn vẫn không bao giờ cần căn bậc hai: chỉ cần quên nó hoàn toàn và sử dụng một nửa số mũ dự định. Nói cách khác, nếu z là tổng bình phương của sự khác biệt tọa độ, thay vì tính toán (sqrt (z)) ^ p, là hai phép toán đắt tiền vừa phải, chỉ cần tính z ^ (p / 2), vì (vì p / 2 là một số được tính toán trước ) chỉ là một hoạt động raster - và cũng dẫn đến mã rõ ràng hơn. Ý tưởng này xuất hiện khi bạn áp dụng các mô hình hấp dẫn như dự định ban đầu: thời gian di chuyển. Không còn bất kỳ công thức căn bậc hai nào, vì vậy bạn tăng thời gian di chuyển lên mức -p / 2.
whuber

Cảm ơn rất nhiều, đây trông giống như những gì tôi cần. Chỉ là một vấn đề, tôi không quen với python và tôi không bao giờ sử dụng phần mở rộng Rasterlang. Tôi đã cài đặt nó trên phiên bản QGIS của mình, nhưng tôi bị "lỗi cú pháp". Là chức năng của bạn đã được thực hiện trong phần mở rộng rasterlang? Nếu không, làm thế nào để tôi làm điều đó? Cảm ơn sự giúp đỡ của bạn! http://i.imgur.com/NhiAe9p.png
Damien

1
@Jake: Ok, tôi nghĩ rằng tôi bắt đầu hiểu cách thức hoạt động của giao diện điều khiển. Tôi đã làm như bạn nói và mã dường như được hiểu đúng. Bây giờ tôi có một lỗi khác liên quan đến gói python "shape_base.py". Có cài đặt QGIS của tôi thiếu một số tính năng? http://i.imgur.com/TT0i2Cl.png
Damien
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.