Como calcular distâncias em uma sequência de pontos?

8

Estou procurando ajuda para calcular a distância entre uma sequência de pontos que estão em um único Shapefile no QGIS. Abaixo está a aparência dos meus dados e uma coluna de distância em branco que eu adicionei para mostrar como eu gostaria que a distância fosse. Quero saber a distância entre os pontos 1 e 2, 2 e 3, etc. Gostaria que a distância estivesse em metros ou Km, mas atualmente meu Shapefile está em uma projeção cujas unidades são graus decimais.

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    ?

Várias pessoas fizeram perguntas semelhantes, mas nenhuma conseguiu o que eu queria fazer. Esta publicação está encerrada, mas está no PostGIS, não no QGIS Calcular distâncias entre séries de pontos no postgis

Este post me fez parte do caminho, mas como eu sou novo no QGIS, a resposta não fornece detalhes suficientes para mim. Por exemplo, depois de instalar o plug-in GRASS, acho que preciso salvar / importar o Shapefile com minha série de pontos GPS no GRASS para poder usar o módulo v.distance, mas não sei como fazer isso . QGIS calcula a distância do ponto ao longo de uma linha

O módulo GRASS v.distance é o único caminho a percorrer? Ou existe um caminho mais direto? Se v.distance é a única maneira de alguém me indicar ou explicar mais passo a passo como fazer isso?

Kerrie
fonte
@underdark Como podemos fazer isso no excel?
user2207232

Respostas:

8

Volto a esse problema porque é muito semelhante a Como encontro o rolamento de linhas vetoriais no QGIS ou GRASS? e pode ser resolvido com o Python da mesma maneira:

1) Distância de Haversine

Pode-se encontrar muitos scripts pesquisando a distância de Haversine com Python na Internet e eu escolho um deles na fórmula de Haversine em Python (rolamento e distância entre dois pontos de 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

Temos uma série de linhas (pontos) no arquivo que devem ser tratadas em pares (ponto1 - ponto2) para calcular a distância. Para isso, usaremos um iterador simples da maneira Most pythonic para obter o elemento anterior

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

Agora é possível ler o arquivo (exemplo de Kerrie) em pares de linhas / pontos

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'})

Em seguida, crie um shapefile contendo os campos originais do arquivo csv e um novo campo para a distância com os módulos Python Shapely e 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)})

e o resultado: insira a descrição da imagem aqui

Também é possível fazer isso com o PyQGIS, mas é mais complexo que o Fiona, que usa dicionários simples para criar shapefiles.

Você pode usar outra função para calcular a distância de Haversine ( por que a lei dos cossenos é mais preferível do que a haversine ao calcular a distância entre dois pontos de latitude-longitude? ) Sem nenhum problema, apenas o cálculo da distância muda, não o processo de criação do shapefile.

gene
fonte
5

Se você está familiarizado com r, tente usar uma combinação dos pacotes 'sp' e 'dismo'.

Por exemplo, assim (supondo ter pontos com as 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
Maçarico
fonte
3

Talvez a ferramenta de matriz à distância possa ajudar? Está no menu Vetor. Para cada ponto, isso calculará a distância de cada um dos outros pontos e armazenará o resultado em um arquivo CSV.

Se você deseja as distâncias em metros, acho que faria sentido transformar seus pontos de lat / lon em um shapefile projetado (possivelmente UTM51 no seu caso) antes de usar a ferramenta.

N.

Nhopton
fonte
0

Use v.to.db no GRASS (por exemplo, via plugin Sextante) com a opção = length (comprimento da linha).

Exemplo de upload de comprimentos de linha (em metros) de cada linha de vetor para a tabela de atributos (preencha os campos correspondentes na GUI):

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

markusN
fonte
0

Acho que esse problema é mais fácil de resolver trabalhando em uma planilha, não use os gis. Achei o trabalho de Chris Veness muito útil -

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

Se você rolar o parágrafo inferior, encontrará links para duas planilhas do Excel, que são;

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

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

Veja também;

Por que a lei dos cossenos é mais preferível que a haversine no cálculo da distância entre dois pontos de latitude-longitude?

e você pode pesquisar no gis.se por haversine.

Felicidades

Willy
fonte
Você precisa de ajuda para obter os dados do shapefile para a planilha?
Willy