¿Crear puntos equidistantes en QGIS?

22

Estoy tratando de crear puntos (nueva capa) a una distancia específica a lo largo del camino (capa existente) en QGIS. ¿Crea puntos regulares cada metro a nivel de condado usando ArcGIS Desktop? da solución para ArcGIS. ¿Cómo lograr esto en QGIS? ¿Agregar puntos a la capa vectorial de puntos usando QGIS? explica cómo crear puntos pero no hace nada sobre la distancia.


(Apliqué las soluciones propuestas con diferentes medidas de longitudes porque no conocía la conversión) La solución de @ Nathans funcionó hasta cierto punto, obtuve ...

ingrese la descripción de la imagen aquí. Aquí, la proyección de estos puntos equidistantes es diferente de la línea original.

Con la sugerencia de @ underdark, obtuve

esta imagendonde los puntos no parecen ser equidistantes. Supongo que hay algún problema de proyección con ambos que no entiendo.

Stat-R
fuente
2
Un par de puntos En primer lugar, la línea debe estar en un CRS proyectado (no lat / lon). En segundo lugar, ¿es su línea una verdadera polilínea? No creo que ningún método funcione correctamente en una línea que comprende una cadena de líneas individuales. Mella.
nhopton
También con mi código, no necesita llamar a la import locatelínea más de una vez. Sólo tiene que llamar una vez, entonces puede llamar a locate.pointsAlongLine(30)todo lo que necesita
Nathan W
Otro método (dado que Sextant como lo sugieren algunas respuestas aquí es QGIS <2.0 solamente), también es usar el complemento llamado QChainage.
Andy

Respuestas:

14

Nota: ahora hay un complemento QGIS QChainage. Hace todo esto y más. El siguiente código está desactualizado con QGIS 2.0 y superior.

Aquí hay un código de Python que puede pegar en un archivo y usar dentro de QGIS:

QGIS tiene un método en su API para hacer referencias de línea, sin embargo no pude hacer que funcione correctamente, pero me pondré en contacto con el autor del código y veré si estaba haciendo algo mal.

Por ahora necesitará la biblioteca Python bien formada , que debe instalar de todos modos porque es útil tenerla a mano. También tiene una excelente documentación en http://toblerity.github.com/shapely/manual.html

Esta es la sección que estoy usando en el siguiente ejemplo http://toblerity.github.com/shapely/manual.html#interoperation .

La mayor parte del siguiente código es un código repetitivo de QGIS que solo crea las características, las capas, la conversión de wkb y wkt y viceversa. El bit central es el point = line.interpolate(currentdistance)que devuelve un punto a una distancia a lo largo de una línea. Simplemente envolvemos esto en un bucle hasta que nos quedemos sin línea.

import qgis
from qgis.core import *
from PyQt4.QtCore import QVariant
from shapely.wkb import loads
from shapely.wkt import dumps

vl = None
pr = None

def createPointsAt(distance, geom):
    if distance > geom.length():
        print "No Way Man!"
        return

    length = geom.length()
    currentdistance = distance
    feats = []  

    while currentdistance < length: 
        line = loads(geom.asWkb())
        point = line.interpolate(currentdistance)
        fet = QgsFeature()
        fet.setAttributeMap( { 0 : currentdistance } )
        qgsgeom = QgsGeometry.fromWkt(dumps(point))
        fet.setGeometry(qgsgeom)
        feats.append(fet)
        currentdistance = currentdistance + distance

    pr.addFeatures(feats)
    vl.updateExtents()

def pointsAlongLine(distance):
    global vl
    vl = QgsVectorLayer("Point", "distance nodes", "memory")
    global pr
    pr = vl.dataProvider()  
    pr.addAttributes( [ QgsField("distance", QVariant.Int) ] )
    layer = qgis.utils.iface.mapCanvas().currentLayer()
    for feature in layer.selectedFeatures():
        geom = feature.geometry()
        createPointsAt(distance, geom)

    QgsMapLayerRegistry.instance().addMapLayer(vl)

Copie y pegue el código anterior en el archivo, llamé a mi location.py, en el ~./qgis/pythondirectorio (porque está en la ruta de Python) y solo haga esto en la consola de Python dentro de QGIS.

 import locate
 locate.pointsAlongLine(30)

Eso creará una nueva capa de puntos con puntos cada 30 metros a lo largo de las líneas seleccionadas, de esta manera:

ingrese la descripción de la imagen aquí

Nota: El código es bastante tosco y podría necesitar alguna limpieza.

EDITAR: la última versión de desarrollo de QGIS ahora puede hacer esto de forma nativa.

Cambie el bucle while createPointsAta:

 while currentdistance < length: 
    point = geom.interpolate(distance)
    fet = QgsFeature()
    fet.setAttributeMap( { 0 : currentdistance } )
    fet.setGeometry(point)
    feats.append(fet)
    currentdistance = currentdistance + distance

y puedes quitar el

from shapely.wkb import loads
from shapely.wkt import dumps
Nathan W
fuente
Gracias @Nathan. No pude obtener el paquete Shapely para mi python. Instalé python 2.7 pero el instalador Shapely dice que python 2.7 no está en mi registro. ¿Hay otra forma de instalar Shapely?
Stat-R
Seguí stackoverflow.com/questions/3652625/… y escribí las dos líneas anteriores para llamar locatey usarlo, pero aún así no obtuve los puntos equidistantes. Además, soy un neófito en Python, así que no entendí dónde ejecutar el código (1) python en el directorio qgis o (2) que en C: \ Python27 \?
Stat-R
¿En qué sistema operativo estás?
Nathan W
Windows 7 Professional
Stat-R
cree el archivo de Python y C:\Users\{you user name}\.qgis\pythonluego reinicie QGIS si está abierto, y vaya a `Complementos-> . Load a line layer, select a line a call Importar consola de Python localizar` ylocate.pointsAlongLine(30)
Nathan W
5

Puede usar la herramienta v.to.points del complemento QGIS GRASS para crear puntos a lo largo de líneas a intervalos regulares

# convert line to points; dmax = distance between points
v.to.points -i -v -t in=road out=road_pts type=line dmax=90
bajo oscuro
fuente
Usé dmax como 100 y las proyecciones resultantes para cada uno son las siguientes. (No sé cómo se está asignando el CRS por sí mismo.)CRS of Original Shape file, the line = EPSG:26915 - NAD83 / UTM zone 15N, CRS of Grass line vector obtained using v.in.ogr = EPSG:4269 - NAD83, CRS of Grass points vector obtained using v.to.points = EPSG:4326 - WGS 84
Stat-R
Ahora también como este: QGIS -> Sextante -> GRASS -> v.to.points
markusN
5

Si desea trazar el PK a intervalos fijos a lo largo de una línea de carretera, puede usar el complemento 'Perfil desde la línea' para hacer esto. Necesita un DEM debajo de la capa de línea de ruta, pero el procedimiento es rápido y muy simple. Mella.

ingrese la descripción de la imagen aquí

nhopton
fuente
Este es un método bastante bueno y fácil también, ¡gracias!
Shepherdjo
2

Tenga en cuenta que el modelo de datos Shapely (Python) / GEOS (C ++) se define en un plano. Entonces, si sus puntos consisten en posiciones de GPS (latitud, longitud) usando el shapely.geometry.LineString.interpolate(distance)método, generará una posición de GPS a la distancia euclidiana a lo largo de la dada LineString.

Shapely's interpolate()se basa en la geos::linearref::LengthIndexedLineclase de GEOS utilizando el extractPointmétodo.

Supuestamente, la interpolación igualmente espaciada en el plano de latitud-longitud es suficiente para aplicaciones que consideran distancias relativamente pequeñas. En general, sin embargo, uno debe considerar la distancia en una esfera para aplicaciones SIG (como se define en WGS84 ).

Puedo pensar en dos soluciones alternativas usando el módulo Shapely:

  • LineStringtodas las propiedades son puntos dados y curvas interpoladas linealmente a lo largo de ellos. Quizás pueda escribir un miembro que acceda a las curvas interpoladas e implementar la siguiente integral de línea sustituyendo la distancia euclidiana. Este enfoque me gusta porque usando la curva continua por partes se pueden obtener los puntos deseados calculando las intersecciones de los círculos adyacentes a lo largo de la curva con el radio r = radian_measure(arc_length) = arc_length / R, donde R es igual al radio de la Tierra en la posición dada.
  • codifique su propio método de interpolación (sin tocar el código Shapely) utilizando una función de distancia apropiada (por ejemplo, fórmula de Haversine).

Para lograr esto, me gustaría consultar la siguiente pregunta de StackOverflow y esta respuesta en particular:

ES posible generar puntos equidistantes a lo largo de la curva. Pero debe haber más definición de lo que quieres para una respuesta real. Lo siento, pero el código que he escrito para esta tarea está en MATLAB, pero puedo describir las ideas generales. Hay tres posibilidades

Primero, ¿los puntos son verdaderamente equidistantes de los vecinos en términos de una distancia euclidiana simple? Hacerlo implicaría encontrar la intersección en cualquier punto de la curva con un círculo de radio fijo. Luego solo camina a lo largo de la curva.

A continuación, si tiene la intención de distancia a distancia media a lo largo de la curva en sí, si la curva es lineal por partes, el problema es nuevamente fácil de resolver. Simplemente avance por la curva, ya que la distancia en un segmento de línea es fácil de medir.

Finalmente, si tiene la intención de que la curva sea una spline cúbica, nuevamente esto no es increíblemente difícil, pero es un poco más de trabajo. Aquí el truco es:

  • Calcule la longitud de arco lineal por partes de un punto a otro a lo largo de la curva. Llámalo t. Genere un par de splines cúbicos, x (t), y (t).

  • Diferenciar xey como funciones de t. Dado que estos son segmentos cúbicos, esto es fácil. Las funciones derivadas serán
    cuadráticas por partes .

  • Use un solucionador de odas para moverse a lo largo de la curva, integrando la función de longitud de arco diferencial. En MATLAB, ODE45 funcionó muy bien.

Por lo tanto, uno integra

sqrt((x')^2 + (y')^2)

Nuevamente, en MATLAB, ODE45 se puede configurar para identificar aquellas ubicaciones donde la función cruza ciertos puntos específicos.

Si sus habilidades con MATLAB están a la altura, puede consultar el código en interparc para obtener más explicaciones. Es un código razonablemente bien comentado.

3 : http://www.mathworks.com/matlabcentral/fileexchange/34874-interparc

Patryk
fuente
1

Sextante tiene una herramienta que podría funcionar para usted. Sextante se puede descargar desde el repositorio de complementos de Qgis.

Busque:
"Herramientas para capas de línea"
"Líneas a puntos equiespaciados"

klewis
fuente
Este complemento no parece estar disponible para QGIS 2 o 3.
Martin Burch