Criando pontos equidistantes no QGIS?


22

Estou tentando criar pontos (nova camada) a uma distância específica ao longo da estrada (camada existente) no QGIS. Criando pontos regulares a cada metro no nível do condado usando o ArcGIS Desktop? fornece solução para ArcGIS. Como conseguir isso no QGIS? Adicionando pontos à camada vetorial de pontos usando o QGIS? explica como criar pontos, mas não faz nada sobre a distância.


(Apliquei as soluções propostas com diferentes medidas de comprimento, pois não conhecia a conversão) @ A solução de Nathans funcionou até certo ponto, consegui ...

insira a descrição da imagem aqui. Aqui, a projeção desses pontos equidistantes é diferente da linha original.

Com a sugestão de @ underdark, recebi

esta imagemonde os pontos não parecem ser equidistantes. Eu acho que há algum problema de projeção com os dois que eu não estou entendendo.



2
Alguns pontos. Em primeiro lugar, a linha deve estar em um CRS projetado (não em lat / lon). Em segundo lugar, sua linha é uma verdadeira polilinha? Eu não acho que nenhum método funcione corretamente em uma linha que compreende uma sequência de linhas individuais. Usuario.
N

Também com o meu código, você não precisa ligar para a import locatelinha mais de uma vez. Apenas chamá-lo de uma vez, então você pode chamar locate.pointsAlongLine(30)tanto quanto você precisa
Nathan W

Outro método (dado que o Sextant, conforme sugerido por algumas respostas aqui, é o QGIS <2.0 apenas), também é usar o plug-in chamado QChainage.
andy

Respostas:


14

Nota: Agora existe um plug-in QGIS QChainage. Faz tudo isso e muito mais. O código abaixo está desatualizado com o QGIS 2.0 e superior.

Aqui está um código Python que você pode colar em um arquivo e usar dentro do QGIS:

O QGIS possui um método na API para fazer referência ao liner, no entanto, não consegui fazê-lo funcionar corretamente, mas vou entrar em contato com o autor do código e ver se estou fazendo algo errado.

Por enquanto, você precisará da bem tornada biblioteca Python, que você deve instalar de qualquer maneira, porque é útil ter por perto. Ele também possui excelente documentação em http://toblerity.github.com/shapely/manual.html

Esta é a seção que estou usando no exemplo a seguir http://toblerity.github.com/shapely/manual.html#interoperation .

A maior parte do código a seguir é do código padrão do QGIS, apenas criando os recursos, as camadas, convertendo de wkb e wkt e vice-versa. O bit principal é o point = line.interpolate(currentdistance)que retorna um ponto à distância ao longo de uma linha. Nós apenas envolvemos isso em um loop até ficarmos sem linha.

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 e cole o código acima no arquivo, chamei meu localiz.py, no ~./qgis/pythondiretório (porque está no caminho do Python) e faça isso no console do Python dentro do QGIS.

 import locate
 locate.pointsAlongLine(30)

Isso criará uma nova camada de pontos com pontos a cada 30 metros, ao longo das linhas selecionadas, da seguinte forma:

insira a descrição da imagem aqui

Nota: O código é bastante difícil e pode precisar de uma limpeza.

EDIT: A última versão do desenvolvedor do QGIS agora pode fazer isso de forma nativa.

Altere o loop while createPointsAtpara:

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

e você pode remover o

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

Obrigado @ Nathan. Não consegui obter o pacote Shapely para o meu python. Eu instalei o python 2.7, mas o instalador Shapely diz que o python 2.7 não está no meu registro. Existe outra maneira de instalar o Shapely.
precisa

Eu segui stackoverflow.com/questions/3652625/… e digitei as duas linhas acima para chamar locatee usá-lo, mas ainda não obtive os pontos equidistantes. Além disso, sou um neófito em Python, então não entendi onde executar o código (1) python no diretório qgis ou (2) no C: \ Python27 \?
Stat-R

Em qual SO você está?
Nathan W

Windows 7 Professional
Stat-R

crie o arquivo python C:\Users\{you user name}\.qgis\pythone reinicie o QGIS se estiver aberto, e vá para `Plugins-> Python Console . Load a line layer, select a line a call import location` elocate.pointsAlongLine(30)
Nathan W

5

Você pode usar a ferramenta v.to.points do plugin QGIS GRASS para criar pontos ao longo das linhas em 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

Usei dmax como 100 e as projeções resultantes para cada uma são as seguintes. (Eu não sei como o CRS está sendo atribuído por si só.)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

Agora também como este: QGIS -> Sextante -> GRASS -> v.to.points
markusN

5

Se você deseja plotar a corrente em intervalos fixos ao longo de uma estrada, pode usar o plug-in 'Perfil da linha' para fazer isso. Você precisa de um DEM sob a camada de linha da estrada, mas o procedimento é rápido e muito simples. Usuario.

insira a descrição da imagem aqui


este é um método muito bom e fácil também, obrigado!
Shepherdjo

2

Observe que o modelo de dados Shapely (Python) / GEOS (C ++) está definido em um plano. Portanto, se seus pontos consistirem em posições GPS (latitude, longitude), o shapely.geometry.LineString.interpolate(distance)método emitirá uma posição GPS na distância euclidiana ao longo do dado LineString.

O Shapely's interpolate()é baseado na geos::linearref::LengthIndexedLineclasse do GEOS usando o extractPointmétodo

Supostamente, a interpolação igualmente espaçada no plano de latitude-longitude é suficiente para aplicações que consideram distâncias relativamente pequenas. Em geral, no entanto, deve-se considerar a distância em uma esfera para aplicativos GIS (conforme definido em WGS84 ).

Posso pensar em duas soluções alternativas usando o módulo Shapely:

  • LineStringtodas as propriedades recebem pontos e curvas interpoladas linearmente ao longo deles. Talvez você possa escrever um membro que acesse as curvas interpoladas e implementar a seguinte linha integral, substituindo a distância euclidiana. Eu gosto dessa abordagem porque, usando a curva contínua em partes, os pontos desejados podem ser obtidos calculando-se as interseções dos círculos adjacentes ao longo da curva com o raio r = radian_measure(arc_length) = arc_length / R, onde R é igual ao raio da Terra na posição determinada.
  • codifique seu próprio método de interpolação (sem tocar no código Shapely) usando uma função de distância apropriada (por exemplo, fórmula haversine).

Para conseguir isso, gostaria de consultar a seguinte pergunta StackOverflow e esta resposta em particular:

É possível gerar pontos equidistantes ao longo da curva. Mas deve haver mais definição do que você deseja para uma resposta real. Desculpe, mas o código que escrevi para esta tarefa está no MATLAB, mas posso descrever as idéias gerais. Existem três possibilidades.

Primeiro, os pontos são realmente equidistantes dos vizinhos em termos de uma simples distância euclidiana? Fazer isso envolveria encontrar a interseção em qualquer ponto da curva com um círculo de raio fixo. Depois, basta seguir a curva.

Em seguida, se você pretende que distância seja distância média ao longo da própria curva, se a curva é linear por partes, o problema é novamente fácil. Basta seguir a curva, já que a distância em um segmento de linha é fácil de medir.

Finalmente, se você pretende que a curva seja um spline cúbico, novamente isso não é incrivelmente difícil, mas é um pouco mais trabalhoso. Aqui o truque é:

  • Calcule o comprimento do arco linear por partes de ponto a ponto ao longo da curva. Chame de t. Gere um par de splines cúbicos, x (t), y (t).

  • Diferencie x e y como funções de t. Como esses são segmentos cúbicos, isso é fácil. As funções derivadas serão
    quadráticas por partes .

  • Use um solucionador de ode para se mover ao longo da curva, integrando a função diferencial de comprimento de arco. No MATLAB, o ODE45 funcionou bem.

Assim, integra-se

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

Novamente, no MATLAB, o ODE45 pode ser configurado para identificar os locais em que a função cruza determinados pontos especificados.

Se suas habilidades no MATLAB estão à altura da tarefa, você pode consultar o código no interparc para obter mais explicações. É um código razoavelmente bem comentado.

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


1

O Sextante possui uma ferramenta que pode funcionar para você. O Sextante pode ser baixado do repositório de plugins Qgis.

Procure por:
"Ferramentas para camadas de linha"
"Linhas para pontos com espaço equidistante"


Este plugin não parece estar disponível para QGIS 2 ou 3.
Martin Burch
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.