Alinear múltiples puntos a la línea en QGIS?

11

Me gustaría alinear múltiples puntos a una línea, o líneas dentro de una capa, usando una tolerancia específica o un búfer alrededor de los objetos de línea. Consulte el boceto de muestra adjunto.

Por el bien de este ejemplo, los puntos más cercanos a la línea en la imagen ANTES están dentro de 5 unidades de mapa de la línea, mientras que los puntos más exteriores están a más de 10 unidades de mapa de distancia. Me gustaría ajustar los puntos más cercanos a la línea más cercana, usando una tolerancia de 5 unidades de mapa para lograr el resultado en la imagen DESPUÉS.

ingrese la descripción de la imagen aquí

Ed Camden
fuente
Entonces, el punto debe ser 0 unidades de mapa lateralmente de la línea, pero ¿le importa dónde termina el punto longitudinalmente de la línea con respecto a la ubicación original del punto?
Joe
El escenario ideal sería mover los puntos usando una ruta perpendicular a la línea. Sin embargo, la intención es utilizar tolerancias bastante pequeñas. Si los puntos se mueven longitudinalmente o latitudinalmente, hacia la línea, no compensará mucho los puntos desde una posición perpendicular preferible.
Ed Camden
No estoy seguro de si esta es la mejor manera, pero una forma en la que puedo pensar es escribir un código de Python para analizar los dos conjuntos de datos y producir algunas coordenadas de puntos. Si esto es lo que crees que quieres, avísame y puedo darte una respuesta. Por ejemplo, para cada punto, si el valor absoluto de lat dist de la línea <= 5 unidades, entonces distancia lateral = 0. Tendría que importar una biblioteca gdal para convertir los valores x, y en coordenadas. Ver comentarios en: gis.stackexchange.com/questions/185445/…
Joe
Con PyQGIS, se puede generar una capa de memoria donde los puntos se ajustan de acuerdo con la tolerancia previamente considerada de 5 unidades de mapa y una ruta perpendicular a la línea. Mira mi respuesta.
xunilk

Respuestas:

15

Hay una herramienta incorporada para hacer esto en la versión QGIS 3.0 (inédita). Puede obtener una instantánea nocturna del sitio web de QGIS para probar esto por adelantado.

Para hacer esto:

  1. Ejecute el algoritmo de procesamiento "Ajustar geometrías a capa"
  2. Seleccione su capa de puntos como la "capa de entrada"
  3. Seleccione la capa de línea como la "capa de referencia"
  4. Introduzca una tolerancia adecuada (distancia máxima para mover puntos mientras se ajusta)
  5. Cambie el comportamiento a "Preferir el punto más cercano"

ingrese la descripción de la imagen aquí

Aquí está el resultado, que muestra los puntos originales como "x", y los puntos ajustados como puntos verdes. He usado una tolerancia aquí para que solo algunos de los puntos de entrada estén ajustados.

ingrese la descripción de la imagen aquí

ndawson
fuente
Esto es exactamente lo que necesito. Lamentablemente, mi empleador solo instala versiones LTR de QGIS y todos tenemos restricciones para descargar e instalar versiones de prueba. (suspiro) Supongo que es cuestión de esperar. ¿Es esta una función estándar / incorporada o un complemento?
Ed Camden
Funcionalidad estándar basada en cambios en las clases de c ++: no hay forma de copiar esto manualmente a una versión anterior. Potencialmente podría intentar instalar usando OSGEO4W en una máquina diferente y luego copiar la carpeta osgeo4w a una memoria USB para ejecutarla en su estación de trabajo. He tenido suerte con ese enfoque en el pasado.
ndawson
1
Para la versión anterior, eche un vistazo a este complemento. docs.qgis.org/2.14/en/docs/user_manual/plugins/…
iRfAn
parece que el complemento no admite capas de puntos.
Mykola Kozyr
7

Esto se puede lograr con PyQGIS . Para la próxima situación:

ingrese la descripción de la imagen aquí

El siguiente código, considerando una tolerancia de 5 unidades de mapa, se ejecutó en la Consola Python de 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)

Se produjo una capa de memoria donde los puntos se ajustaban de acuerdo con la tolerancia previamente considerada de 5 unidades de mapa y una ruta perpendicular a la línea.

ingrese la descripción de la imagen aquí

xunilk
fuente
2

También puede hacer esto en la Calculadora de campo con el complemento refFunctions. Puede usar la Calculadora de campo para actualizar la geometría de una capa y los campos. refFunctions le brinda una función de "geomdistance" para encontrar la línea más cercana dentro de una distancia dada (o "geomnearest" si no desea un umbral) y devolverá un atributo o la geometría, y la función "punto_más cercano" encontrará la más cercana punto en una geometría dada. Colóquelos juntos para calcular nuevas geometrías para su capa de puntos:

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

En lugar de actualizar directamente la geometría, puede calcular un campo con la geometría ajustada. Almaceno múltiples geometrías para ajustar puntos de alcantarilla a diferentes capas de flujo y puedo actualizar fácilmente la geometría del punto en la Calculadora de campo, según las líneas de flujo que necesite usar.

Hay algunas limitaciones con esto, ambas capas deben ser el mismo CRS y la función geomdistance le dará un error si tiene más de 100,000 puntos, pero puede cambiar este límite si edita el archivo de complemento refFunctions.

amcaninch
fuente