Allineare più punti alla linea in QGIS?


11

Vorrei allineare più punti a una linea, o linee all'interno di un livello, usando una tolleranza o un buffer specificati attorno agli oggetti linea. Fare riferimento allo schizzo di esempio allegato.

Per il bene di questo esempio, i punti più vicini alla linea nell'immagine PRIMA sono all'interno di 5 unità della mappa della linea, mentre i punti più esterni sono a più di 10 unità della mappa. Vorrei catturare i punti più vicini sulla linea più vicina, usando una tolleranza di 5 unità della mappa per ottenere il risultato nell'immagine DOPO.

inserisci qui la descrizione dell'immagine


Quindi il punto deve essere 0 unità della mappa lateralmente alla linea, ma ti interessa dove finisce il punto longitudinalmente della linea rispetto alla posizione originale del punto?
Joe,

Lo scenario ideale sarebbe spostare i punti usando un percorso perpendicolare alla linea. Tuttavia, l'intenzione è quella di utilizzare tolleranze abbastanza piccole. Se i punti vengono spostati longitudinalmente o latitudinalmente, verso la linea, non compenseranno i punti molto da una posizione perpendicolare preferibile.
Ed Camden,

Non sono sicuro che questo sia il modo migliore, ma un modo a cui riesco a pensare è quello di scrivere del codice Python per analizzare i due set di dati e produrre alcune coordinate puntuali. Se questo è quello che pensi di volere, allora fammi sapere e posso fornirti una risposta. Ad esempio per ogni punto, se il valore assoluto di lat dist dalla linea <= 5 unità, quindi distanza laterale = 0. Dovresti importare una libreria gdal per convertire i valori x, y in coord. Vedi commenti in: gis.stackexchange.com/questions/185445/…
Joe

Con PyQGIS, può essere prodotto un livello di memoria in cui i punti vengono agganciati secondo la tolleranza precedentemente considerata di 5 unità della mappa e un percorso perpendicolare alla linea. Vedi la mia risposta
xunilk,

Risposte:


15

C'è uno strumento integrato per farlo nella versione (non rilasciata) di QGIS 3.0. È possibile ottenere un'istantanea notturna dal sito Web QGIS per testarlo in anticipo.

Per farlo:

  1. Esegui l'algoritmo di elaborazione "Aggancia geometrie al livello"
  2. Seleziona il tuo livello punti come "livello di input"
  3. Seleziona il livello linea come "livello di riferimento"
  4. Immettere una tolleranza adeguata (distanza massima per spostare i punti durante lo snap)
  5. Cambia il comportamento in "Preferisci punto più vicino"

inserisci qui la descrizione dell'immagine

Ecco il risultato, mostrando i punti originali come "x" e i punti spezzati come punti verdi. Ho usato una tolleranza qui, in modo che solo alcuni dei punti di input vengano bloccati.

inserisci qui la descrizione dell'immagine


Questo è esattamente ciò di cui ho bisogno. Sfortunatamente il mio datore di lavoro installa solo versioni LTR di QGIS e siamo tutti limitati a scaricare e installare versioni di prova. (sospiro) Immagino sia una questione di attesa. È una funzione standard / integrata o un plug-in?
Ed Camden,

Funzionalità standard basata su modifiche nelle classi c ++: non c'è modo di copiarlo manualmente in una versione precedente. Potresti potenzialmente provare a installare utilizzando OSGEO4W su un altro computer e quindi a copiare la cartella osgeo4w su una chiavetta USB da eseguire sulla tua workstation. Ho avuto fortuna con questo approccio in passato.
ndawson,

1
Per la vecchia versione dai un'occhiata a questo plugin. docs.qgis.org/2.14/en/docs/user_manual/plugins/…
iRfA

sembra che il plugin non supporti i livelli dei punti.
Mykola Kozyr,

7

Questo può essere offerto con PyQGIS . Per la prossima situazione:

inserisci qui la descrizione dell'immagine

il seguente codice, considerando una tolleranza di 5 unità cartografiche, è stato eseguito nella console Python di QGIS:

from math import sqrt

registry = QgsMapLayerRegistry.instance()

points = registry.mapLayersByName('points')
line = registry.mapLayersByName('line')

feat_points = [ feat for feat in points[0].getFeatures() ]
feat_line = line[0].getFeatures().next()

new_points = []

for feat in feat_points:
    pt = feat.geometry().asPoint()
    sqrdist, point, vertex = feat_line.geometry().closestSegmentWithContext(pt)
    if sqrt(sqrdist) <= 5:
        new_points.append(point)
    else:
        new_points.append(pt)

epsg = points[0].crs().postgisSrid()

uri = "Point?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'new_points',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(new_points)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPoint(new_points[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

È stato prodotto uno strato di memoria in cui i punti sono stati spezzati secondo la tolleranza precedentemente considerata di 5 unità della mappa e un percorso perpendicolare alla linea.

inserisci qui la descrizione dell'immagine


2

Puoi farlo anche nel Field Calculator con il plugin refFunctions. È possibile utilizzare il calcolatore di campo per aggiornare la geometria di un livello e i campi. refFunctions ti dà una funzione di "geomdistance" per trovare la linea più vicina entro una determinata distanza (o "geomnearest" se non vuoi una soglia) e restituirà un attributo o la geometria, e la funzione "più vicino" troverà la più vicina punto su una data geometria. Stringili insieme in questo modo per calcolare nuove geometrie per il tuo livello punto:

closest_point(geom_from_wkt(geomdistance('snap_lines','$geometry',10)) , $geometry)

Invece di aggiornare direttamente la geometria è possibile calcolare un campo con la geometria agganciata. Conservo più geometrie per agganciare i punti di canale sotterraneo a diversi livelli di flusso e posso facilmente aggiornare la geometria dei punti nel calcolatore di campo a seconda delle linee di flusso che devo usare.

Ci sono alcune limitazioni in questo, entrambi i livelli devono essere gli stessi CRS e la funzione di geomdistanza ti darà un errore se hai più di 100.000 punti ma puoi cambiare questo limite se modifichi il file del plugin refFunctions.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.