Di chuyển điểm vào dòng (~ khu phố)


14

Tôi có hai lớp vectơ, trong đó một lớp là lớp điểm dựa trên "sự kiện" bằng viễn thám và lớp thứ hai là lớp đường từ nghiên cứu địa phương.

Trong trường hợp của tôi, đây là những trận động đất và sự cố kiến ​​tạo, nhưng tôi đoán người ta có thể chỉ cần chọn "tai nạn xe hơi và đường xá" làm ví dụ chung.

Vì vậy, điều tôi muốn làm là di chuyển / sao chép các điểm vào điểm gần nhất của đường thẳng, miễn là trong khoảng cách dung sai (giả sử 1-2km hoặc 0,0xx °), với lớp điểm mới (+ attr di chuyển y / n).

Có ý kiến ​​gì không?

Linux, QGIS 1.8



Bạn đang tìm kiếm một chức năng hoàn toàn tự động để làm điều này, hoặc một số công cụ chụp nhanh để làm điều đó bằng tay có ổn không?
Simbamangu

Tôi đã hỏi một câu hỏi tương tự, tôi đã cố gắng để điểm đến điểm nhưng không bao giờ tìm thấy một giải pháp dễ dàng. gis.stackexchange.com/questions/52232/...
GreyHippo

Điều gì về tam giác và khoảng cách phù hợp?
huckfinn

Tôi đã tìm thấy câu hỏi này về một phương pháp hoạt động trong ArcGIS bằng cách sử dụng Gần. Đã tìm kiếm cho QGIS Gần tương đương và tìm thấy bài đăng trên diễn đàn này , nơi ai đó đề xuất GRASS v.distance. Điều đó dẫn tôi đến hướng dẫn này có thể xác định một phương pháp. Có lẽ ở đâu đó trong đó có ai đó đã viết một plugin bây giờ?
Chris W

Câu trả lời:


13

Đã đăng một đoạn mã (được thử nghiệm trong bảng điều khiển python) mà thực hiện dưới đây

  1. Sử dụng QssSpatial Index để tìm tính năng đường gần nhất tới một điểm
  2. Tìm điểm gần nhất trên dòng này đến điểm. Tôi đã sử dụng gói tạo hình như một phím tắt cho việc này. Tôi thấy các phương thức của QGis cho điều này là không đủ (hoặc có lẽ tôi không hiểu đúng về chúng)
  3. Đã thêm dây cao su vào các vị trí chụp
from shapely.wkt import *
from shapely.geometry import *
from qgis.gui import *
from PyQt4.QtCore import Qt
lineLayer = iface.mapCanvas().layer(0)
pointLayer =  iface.mapCanvas().layer(1)
canvas =  iface.mapCanvas()
spIndex = QgsSpatialIndex() #create spatial index object
lineIter =  lineLayer.getFeatures()
for lineFeature in lineIter:
    spIndex.insertFeature(lineFeature)        
pointIter =  pointLayer.getFeatures()
for feature in pointIter:
    ptGeom = feature.geometry()
    pt = feature.geometry().asPoint()
    nearestIds = spIndex.nearestNeighbor(pt,1) # we need only one neighbour
    featureId = nearestIds[0]
    nearestIterator = lineLayer.getFeatures(QgsFeatureRequest().setFilterFid(featureId))
    nearFeature = QgsFeature()
    nearestIterator.nextFeature(nearFeature)
    shplyLineString = shapely.wkt.loads(nearFeature.geometry().exportToWkt())
    shplyPoint = shapely.wkt.loads(ptGeom.exportToWkt())
    #nearest distance from point to line
    dist = shplyLineString.distance(shplyPoint)
    print dist
    #the point on the road where the point should snap
    shplySnapPoint = shplyLineString.interpolate(shplyLineString.project(shplyPoint))
    #add rubber bands to the new points
    snapGeometry = QgsGeometry.fromWkt(shapely.wkt.dumps(shplySnapPoint))
    r = QgsRubberBand(canvas,QGis.Point)
    r.setColor(Qt.red)
    r.setToGeometry(snapGeometry,pointLayer)

Chỉnh sửa: Vừa mới phát hiện ra rằng phương thức @radouxju bằng cách sử dụng nearSegmentWithContext cho kết quả tương tự trong ít dòng mã hơn. Tôi tự hỏi tại sao họ nghĩ ra cái tên phương pháp kỳ lạ này? nên là một cái gì đó giống như nearPointOnGeometry.

Vì vậy, chúng ta có thể tránh tạo dáng và làm như,

nearFeature = QgsFeature()
nearestIterator.nextFeature(nearFeature)   

closeSegResult = nearFeature.geometry().closestSegmentWithContext(ptGeom.asPoint())
closePoint = closeSegResult[1]
snapGeometry = QgsGeometry.fromPoint(QgsPoint(closePoint[0],closePoint[1])) 

p1 = ptGeom.asPoint()
p2 = snapGeometry.asPoint()

dist = math.hypot(p2.x() - p1.x(), p2.y() - p1.y())
print dist

1
chạy vào cơn ác mộng cố gắng định dạng mã trăn này..argh !!
vinaya

5

đây là một mã giả để bắt đầu. Tôi hy vọng điều này có ích và ai đó sẽ có thời gian để cung cấp mã đầy đủ (hiện tại tôi không có)

Điều đầu tiên cần làm là lặp trên điểm và chọn các đường nằm trong khoảng cách ngưỡng đến từng điểm. Thi có thể được thực hiện với QssSpatial Index

Trong vòng lặp đầu tiên, điều thứ hai cần làm là lặp trên các dòng đã chọn và tìm điểm gần nhất trên dòng. Điều này có thể được thực hiện trực tiếp dựa trên QssGeometry :: nearSegmentWithContext

double QssGeometry :: nearSegmentWithContext (const QssPoint & point, QssPoint & minDistPoint, int & afterVertex, double * leftOf = 0, double epsilon = DEFAULT_SEGMENT_EPSILON)

Tìm kiếm phân đoạn hình học gần nhất với điểm đã cho.

Điểm tham số Chỉ định điểm tìm kiếm

minDistPoint  Receives the nearest point on the segment

afterVertex   Receives index of the vertex after the closest segment. The vertex before the closest segment is always afterVertex -

1 leftOf Out: Trả về nếu điểm nằm ở bên trái của phân khúc (<0 có nghĩa là bên trái,> 0 có nghĩa là bên phải) epsilon epsilon để chụp phân đoạn (được thêm vào 1.8)

bước thứ ba (trong vòng lặp đầu tiên) sẽ bao gồm việc cập nhật hình dạng của điểm với hình dạng của minDistPoint với khoảng cách nhỏ nhất

cập nhật với một số mã (trên QGIS3)

pointlayer = QgsProject.instance().mapLayersByName('point')[0] #iface.mapCanvas().layer(0)
lineLayer = QgsProject.instance().mapLayersByName('lines')[0] # iface.mapCanvas().layer(1)

epsg = pointlayer.crs().postgisSrid()
uri = "Point?crs=epsg:" + str(epsg) + "&field=id:integer&field=distance:double(20,2)&field=left:integer&index=yes"
snapped = QgsVectorLayer(uri,'snapped', 'memory')

prov = snapped.dataProvider()

testIndex = QgsSpatialIndex(lineLayer)
i=0

feats=[]

for p in pointlayer.getFeatures():
    i+=1
    mindist = 10000.
    near_ids = testIndex.nearestNeighbor(p.geometry().asPoint(),4) #nearest neighbor works with bounding boxes, so I need to take more than one closest results and further check all of them. 
    features = lineLayer.getFeatures(QgsFeatureRequest().setFilterFids(near_ids))
    for tline in features:
        closeSegResult = tline.geometry().closestSegmentWithContext(p.geometry().asPoint())
        if mindist > closeSegResult[0]:
            closePoint = closeSegResult[1]
            mindist = closeSegResult[0]
            side = closeSegResult[3]
    feat = QgsFeature()
    feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(closePoint[0],closePoint[1])))
    feat.setAttributes([i,mindist,side])
    feats.append(feat)

prov.addFeatures(feats)
QgsProject.instance().addMapLayer(snapped)
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.