25 votos

Creando puntos equidistantes en QGIS?

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


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

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

Con la sugerencia de @underdark, obtuve

esta imagen donde los puntos no parecen ser equidistantes. Supongo que hay algún problema de proyección con ambos que no estoy entendiendo.

1 votos

2 votos

Un par de puntos. En primer lugar, la línea debe estar en un CRS proyectado (no lat/lon). En segundo lugar, ¿su línea es una polilínea real? No creo que ningún método funcione correctamente en una línea que consta de una serie de líneas individuales. Nick.

0 votos

También, con mi código, no es necesario llamar la línea import locate más de una vez. Simplemente llámala una vez y luego puedes llamar a locate.pointsAlongLine(30) todas las veces que necesites.

16voto

Jauder Ho Puntos 3172

Nota: Ahora hay un complemento de QGIS QChainage. Hace todo esto y más. El código a continuación está desactualizado con QGIS 2.0 y versiones posteriores.

Aquí tienes un poco de código Python que puedes pegar en un archivo y usar dentro de QGIS:

QGIS tiene un método en su API para hacer referencia lineal, sin embargo no pude hacer que funcionara correctamente, pero contactaré al autor del código para ver si estaba haciendo algo mal.

Por ahora necesitarás la librería de Python shapely, la cual deberías instalar de todas formas 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 utilizando en el siguiente ejemplo http://toblerity.github.com/shapely/manual.html#interoperation.

La mayoría del código a continuación es código básico de QGIS que simplemente crea las características, capas, convierte de wkb y wkt y viceversa. La parte central es 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 se nos acabe la 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 se puede!"
        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)

Copia y pega el código anterior en un archivo, yo lo llamé locate.py, en el directorio ~./qgis/python (porque está en la ruta de Python) y simplemente haz lo siguiente 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, así:

enter image description here

Nota: El código está bastante básico y podría necesitar algún ajuste.

EDICIÓN: La última versión de desarrollo de QGIS ahora puede hacer esto nativamente.

Cambia el bucle while en createPointsAt a:

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

y puedes eliminar el

from shapely.wkb import loads
from shapely.wkt import dumps

0 votos

Gracias @Nathan. No pude obtener el paquete Shapely para mi python. Instalé python 2.7 pero el instalador de Shapely dice que python 2.7 no está en mi registro. ¿Hay otra forma de instalar Shapely?

0 votos

Seguí stackoverflow.com/questions/3652625/… y escribí las dos líneas anteriores para llamar a locate y 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) en el directorio de qgis o (2) en C:\Python27\.

0 votos

¿En qué sistema operativo estás?

5voto

tobes Puntos 19

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

# convertir línea a puntos; dmax = distancia entre puntos
v.to.points -i -v -t in=carretera out=puntos_carretera type=line dmax=90

0 votos

He usado dmax como 100 y las proyecciones resultantes para cada uno son las siguientes. (No sé cómo se está asignando automáticamente el CRS). CRS del archivo de forma original, la línea = EPSG:26915 - NAD83 / UTM zona 15N, CRS del vector de línea de pasto obtenido usando v.in.ogr = EPSG:4269 - NAD83, CRS del vector de puntos de pasto obtenido usando v.to.points = EPSG:4326 - WGS 84

0 votos

Ahora también así: QGIS -> Sextante -> GRASS -> v.to.points

5voto

Si deseas trazar el kilometraje a intervalos fijos a lo largo de una línea de carretera, podrías usar el complemento 'Perfil desde línea' para hacerlo. Necesitas un MDT debajo de la capa de la línea de carretera, pero el procedimiento es rápido y muy simple. Nick.

introduce aquí la descripción de la imagen

0 votos

Esta es una forma bastante buena y fácil también, ¡gracias!

3voto

phuong tran Puntos 1

Cuidado, el modelo de datos Shapely (Python) / GEOS (C++) está definido en un plano. Por lo tanto, si tus puntos consisten en posiciones GPS (latitud, longitud) usar el método shapely.geometry.LineString.interpolate(distance) devolverá una posición GPS a la distancia euclidiana a lo largo del LineString dado.

El método interpolate() de Shapely está basado en la clase geos::linearref::LengthIndexedLine de GEOS usando el método extractPoint.

Supuestamente, la interpolación equiespaciada en el plano de latitud-longitud es suficiente para aplicaciones considerando distancias relativamente pequeñas. Sin embargo, en general, se debería considerar la distancia en una esfera para aplicaciones GIS (como se define en WGS84).

Puedo pensar en dos soluciones utilizando el módulo Shapely:

  • Las propiedades de LineString son todos los puntos dados e interpolaciones lineales a lo largo de ellos. Quizás puedas escribir un método que accede a las curvas interpoladas e implemente la siguiente integral de línea sustituyendo la distancia euclidiana. Me gusta este enfoque porque usando la curva continua por partes los puntos deseados se pueden obtener calculando las intersecciones de círculos adyacentes a lo largo de la curva con un radio r = medida_radian(arc_length) = arc_length / R, donde R es el radio de la Tierra en la posición dada.
  • Codificar tu propio método de interpolación (sin tocar el código de Shapely) usando una función de distancia apropiada (por ejemplo, la fórmula haversine).

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

Sí es posible generar puntos equidistantes a lo largo de la curva. Pero debe haber más definición de lo que deseas 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 deben estar verdaderamente equidistantes de los vecinos en términos de una simple distancia euclidiana? Hacerlo implicaría encontrar la intersección en cualquier punto de la curva con un círculo de radio fijo. Luego solo avanzar a lo largo de la curva.

Luego, si la distancia se refiere a la distancia a lo largo de la propia curva, si la curva es lineal por partes, el problema es fácil. Solo avanza a lo largo de la curva, ya que la distancia en un segmento de línea es fácil de medir.

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

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

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

  • Usa un solucionador de edos para moverte a lo largo de la curva, integrando la función de longitud de arco diferencial. En MATLAB, ODE45 funcionó bien.

Entonces, uno integra

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

Nuevamente, en MATLAB, ODE45 se puede configurar para identificar las ubicaciones donde la función cruza ciertos puntos especificados.

Si tus habilidades en MATLAB son suficientes para la tarea, puedes revisar el código en interparc para obtener más explicaciones. Es un código razonablemente comentado.

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

1voto

Monroecheeseman Puntos 825

Sextante tiene una herramienta que podría servirte. Sextante se puede descargar del repositorio de complementos de Qgis.

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

0 votos

Este plugin parece no estar disponible para QGIS 2 o 3.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X