¿Cómo calcular distancias en una secuencia de puntos?

8

Estoy buscando ayuda para calcular la distancia entre una secuencia de puntos que están en un solo Shapefile en QGIS. A continuación se muestra cómo se ven mis datos y una columna de distancia en blanco que agregué para mostrar cómo me gustaría que se vea la distancia. Quiero saber la distancia entre el punto 1 y 2, 2 y 3, etc. Me gustaría que la distancia esté en metros o Km, pero actualmente mi Shapefile está en una proyección cuyas unidades son grados decimales.

ID  LAT         LON         TIME        DISTANCE
1   10.08527    124.59833   21:24:37    0
2   10.08523    124.59830   21:25:07    ?
3   10.08526    124.59832   21:25:37    ?
4   10.08526    124.59831   21:26:07    ?

Varias personas han formulado preguntas similares, pero ninguna ha entendido lo que quiero hacer. Esta publicación está cerca, pero está en PostGIS, no en QGIS Calcular distancias entre series de puntos en postgis

Esta publicación me consiguió parte del camino, pero como soy nuevo en QGIS, la respuesta no me proporciona suficientes detalles. Por ejemplo, una vez que instalé el complemento GRASS, creo que necesito guardar / importar el Shapefile con mi serie de puntos GPS en GRASS para poder usar el módulo v.distance, pero no sé cómo hacerlo. . QGIS calcula la distancia del punto a lo largo de una línea

¿El módulo GRASS v.distance es el único camino a seguir? ¿O hay una manera más directa? Si v.distance es la única forma en que alguien podría señalarme o explicarme más paso a paso cómo hacerlo.

Kerrie
fuente
@underdark ¿Cómo podemos hacer eso en Excel?
user2207232

Respuestas:

8

Vuelvo a este problema porque es muy similar a ¿Cómo encuentro el rumbo de línea vectorial en QGIS o GRASS? y se puede resolver con Python de la misma manera:

1) distancia de Haversine

Uno puede encontrar muchos scripts buscando en Haversine distancia con Python en Internet y elijo uno de ellos en Haversine Formula en Python (demora y distancia entre dos puntos GPS)

def haversine(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(math.radians, [lon1, lat1, lon2, lat2])
    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2
    c = 2 * math.asin(math.sqrt(a)) 
    km = 6367 * c
    return km

Tenemos una serie de líneas (puntos) en el archivo que deben tratarse en pares (punto1 - punto2) para calcular la distancia. Para esto usaremos un iterador simple de la forma más pitónica para obtener el elemento anterior

def offset(iterable):
    prev = None
    for elem in iterable:
        yield prev, elem
        prev = elem

Ahora es posible leer el archivo (ejemplo de Kerrie) en pares de líneas / puntos

import csv
with open('testhavers.csv', 'rb') as f:
   reader = csv.DictReader(f)
   for  pair in offset(reader):
       print pair

 (None, {'LAT': '10.08527', 'LON': '124.59833', 'ID': '1', 'TIME': '21:24:37'})
 ({'LAT': '10.08527', 'LON': '124.59833', 'ID': '1', 'TIME': '21:24:37'},
 {'LAT':    '10.08523', 'LON': '124.59830', 'ID': '2', 'TIME': '21:25:07'})
 ({'LAT': '10.08523', 'LON': '124.59830', 'ID': '2', 'TIME': '21:25:07'}, 
 {'LAT': '10.08526', 'LON': '124.59832', 'ID': '3', 'TIME': '21:25:37'})
 ({'LAT': '10.08526', 'LON': '124.59832', 'ID': '3', 'TIME': '21:25:37'}, 
 {'LAT':    '10.08526', 'LON': '124.59831', 'ID': '4', 'TIME': '21:26:07'})

Luego cree un archivo shape que contenga los campos originales del archivo csv y un nuevo campo para la distancia con los módulos Python Shapely y Fiona de Sean Gillies:

import fiona
from shapely.geometry import Point, mapping
# creation of the schema of the shapefile (geometry and fields)
schema = { 'geometry': 'Point', 'properties':{'ID': 'int', 'LAT':'float', 'LON':'float', 'TIME':'str','distance' : 'float'}}
# creation of the shapefile:
with fiona.collection("result.shp", "w", "ESRI Shapefile", schema) as output:
    # reading the csv file
    with open('testhavers.csv', 'rb') as f:
       reader = csv.DictReader(f)
       # we need here to eliminate the first pair of point with None
       for i, pair in enumerate(offset(reader)):
            if i == 0: (pair with None)
                # writing of the point geometry and the attributes
                point = Point(float(pair[1]['LON']), float(pair[1]['LAT']))
                dist = 0 # None
                output.write({'properties': {'ID':int(pair[1]['ID']),'LAT':float(pair[1]['LAT']),'LON':float(pair[1]['LON']), 'TIME':pair[1]['TIME'],'distance': dist},'geometry': mapping(point)})
             else:
                # writing of the point geometry and the attributes
                point = Point(float(pair[1]['LON']), float(pair[1]['LAT']))
                # Haversine distance between pairs of points
                dist = haversine(float(pair[0]['LON']), float(pair[0]['LAT']), float(pair[1]['LON']),float(pair[1]['LAT']))
                output.write({'properties': {'ID':int(pair[1]['ID']),'LAT':float(pair[1]['LAT']),'LON':float(pair[1]['LON']), 'TIME':pair[1]['TIME'],'distance': dist},'geometry': mapping(point)})

y el resultado: ingrese la descripción de la imagen aquí

También es posible hacerlo con PyQGIS, pero es más complejo que Fiona, que utiliza diccionarios simples para crear archivos de forma.

Puede usar otra función para calcular la distancia de Haversine ( ¿Por qué la ley de cosenos es más preferible que la de Haversine al calcular la distancia entre dos puntos de latitud y longitud? ) Sin ningún problema, solo cambia el cálculo de la distancia, no el proceso de creación del shapefile.

gene
fuente
5

Si está familiarizado con r, intente usar una combinación del paquete 'sp' y 'dismo'.

Por ejemplo así (suponiendo que tenga puntos con coordenadas x, y):

library(sp)
library(dismo)

data <- read.csv2(..) # Read in your data
coordinates(data) <- ~x+y # point them to your coordinates to make a spatialpoint layer
# Or like this:
Pointlayer <- SpatialPoints(cbind(data$x,data$y))


# then calculate your distance matrix your point sequence
d <- pointDistance(pp,longlat=F)

# Looks for example like this:
head(d)
          [,1]     [,2]     [,3]     [,4]     [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
[1,]  0.000000       NA       NA       NA       NA   NA   NA   NA   NA    NA    NA    NA
[2,] 54.561891  0.00000       NA       NA       NA   NA   NA   NA   NA    NA    NA    NA
[3,] 25.000000 73.49830  0.00000       NA       NA   NA   NA   NA   NA    NA    NA    NA
[4,] 50.487622 43.93177 53.14132  0.00000       NA   NA   NA   NA   NA    NA    NA    NA
[5,]  4.123106 57.00877 26.30589 54.58938  0.00000   NA   NA   NA   NA    NA    NA    NA
[6,] 32.249031 37.21559 57.14018 60.30755 32.01562    0   NA   NA   NA    NA    NA    NA

#More information about the method in dismo package help
Zarapito
fuente
3

¿Quizás la herramienta de matriz de distancia podría ayudar? Está debajo del menú Vector. Para cada punto, esto calculará la distancia a cada uno de los otros puntos y almacenará el resultado en un archivo CSV.

Si desea las distancias en metros, creo que tendría sentido transformar sus puntos de lat / lon a un archivo de forma proyectado (posiblemente UTM51 en su caso) antes de usar la herramienta.

NORTE.

nhopton
fuente
0

Use v.to.db en GRASS (por ejemplo, a través del complemento Sextante) con option = length (longitud de línea).

Ejemplo de carga de longitudes de línea (en metros) de cada línea de vector a la tabla de atributos (complete los campos correspondientes en la GUI):

v.to.db map=roads option=length type=line col=linelength units=me

markusN
fuente
0

Creo que este problema es más fácil de resolver trabajando en una hoja de cálculo, no use los gis. El trabajo de Chris Veness me pareció muy útil.

http://www.movable-type.co.uk/scripts/latlong.html

Si desplaza el párrafo inferior, encontrará enlaces a dos hojas de Excel, que son;

http://www.movable-type.co.uk/scripts/latlong-distance+bearing.xls

http://www.movable-type.co.uk/scripts/latlong-dest-point.xls

Ver también;

¿Por qué es más preferible la ley de cosenos que la de Haversine cuando se calcula la distancia entre dos puntos de latitud y longitud?

y puedes buscar gis.se para haversine.

salud

Colita
fuente
¿Necesita ayuda para obtener los datos del archivo de forma a la hoja de cálculo?
Willy