Noktaları çizgilere taşıma (~ mahalle)


14

İki vektör katmanım var, bunlardan biri uzaktan algılama ile "olaylara" dayalı bir nokta katmanı, ikincisi ise yerel araştırmalardan bir çizgi katmanı.

Benim durumumda bunlar depremler ve tektonik faylar, ama sanırım genel bir örnek olarak "araba kazaları ve yollar" seçilebilir.

Yapmak istediğim şey, yeni nokta katmanı (+ attr hareket ettirildiğinde) tolerans mesafesi (1-2km veya 0.0xx °) olduğu sürece çizgilerin en yakın noktasına taşımak / kopyalamaktır. e / h).

Herhangi bir fikir ?

Linux, QGIS 1.8



Bunu yapmak için tamamen otomatik bir işlev mi arıyorsunuz, yoksa elle yapmak için bir tür yaslama aracı mı?
Simbamangu

Ben de benzer bir soru sordum, noktalara çizgi çekmeye çalışıyordum ama kolay bir çözüm bulamadım. gis.stackexchange.com/questions/52232/…
GreyHippo

Nirengi ve mesafe eşleşmesine ne dersiniz?
huckfinn

Near kullanarak ArcGIS'de çalışan bir yöntem hakkında bu soruyu buldum . QGIS Near eşdeğerini aramaya başladı ve birinin GRASS v.distance'ı önerdiği bu forum gönderisini buldu . Bu beni bir yöntemi tanımlayabilecek bu eğiticiye götürüyor. Belki de orada bir yerlerde birisi şimdiye kadar bir eklenti yazmıştır?
Chris W

Yanıtlar:


13

Aşağıdakileri gösteren bir kod snippet'i (python konsolunda test edildi) yayınlandı

  1. Bir noktaya en yakın çizgi özelliğini bulmak için QgsSpatialIndex kullanma
  2. Bu çizgideki noktaya en yakın noktayı bulun. Bunun için bir kısayol olarak düzgün bir paket kullandım. Bunun için QGis yöntemlerini yetersiz buldum (veya büyük olasılıkla onları düzgün anlamıyorum)
  3. Yapışkan yerlere lastik bantlar eklendi
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)

Düzenleme: Sadece şimdi closestSegmentWithContext kullanarak @radouxju yönteminin daha az kod satırında aynı sonuçları verdiğini bulundu. Acaba neden bu garip yöntem adını buldular? en yakınPointOnGeometry gibi bir şey olmalı.

Böylece düzgün bir şekilde kaçınabilir ve beğenebiliriz,

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
kabus içine çalışan bu python kodunu biçimlendirmeye çalışırken ..argh !!
vinayan

5

burada başlamak için bir sözde kod var. Umarım bu yardımcı olur ve birisi tam kod sağlamak için zaman olacak (şu anda yok)

Yapılacak ilk şey nokta üzerinde döngü yapmak ve her noktaya eşik mesafesi içinde bulunan çizgileri seçmektir. Thi QgsSpatialIndex ile yapılabilir

İlk döngü içinde yapılacak ikinci şey, seçilen çizgiler üzerinde döngü yapmak ve çizgi üzerindeki en yakın noktayı bulmaktır. Bu doğrudan QgsGeometry :: closestSegmentWithContext'e göre yapılabilir

çift ​​QgsGeometry :: closestSegmentWithContext (const QgsPoint & point, QgsPoint & minDistPoint, int & afterVertex, çift * leftOf = 0, çift epsilon = DEFAULT_SEGMENT_EPSILON)

Verilen noktaya en yakın geometri segmentini arar.

Parametreler noktası Arama noktasını belirtir

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: Nokta, segmentin sağ tarafının solundaysa (<0 sola,> 0 sağa demektir) segment yaslama için epsilon epsilon (1.8'e eklenir)

üçüncü adım (ilk döngü içinde), noktanın geometrisini minDistPoint'in geometrisiyle en küçük mesafeyle güncellemekten ibarettir.

bazı kodlarla güncelleme (QGIS3'te)

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)
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.