Alinhando vários pontos à linha no QGIS?

11

Gostaria de alinhar vários pontos a uma linha, ou linhas dentro de uma camada, usando uma tolerância especificada ou buffer em torno dos objetos de linha. Consulte o exemplo de desenho em anexo.

Para fins de exemplo, os pontos mais próximos da linha na imagem ANTES estão dentro de 5 unidades de mapa da linha, enquanto os pontos mais externos estão a mais de 10 unidades de mapa. Gostaria de encaixar os pontos mais próximos na linha mais próxima, usando uma tolerância de 5 unidades de mapa para obter o resultado na imagem APÓS.

insira a descrição da imagem aqui

Ed Camden
fonte
Portanto, o ponto precisa ser 0 unidades de mapa lateralmente da linha, mas você se importa com o local onde o ponto termina longitudinalmente da linha em relação à localização original do ponto?
Joe
O cenário ideal seria mover os pontos usando um caminho perpendicular à linha. No entanto, a intenção é usar tolerâncias razoavelmente pequenas. Se os pontos forem movidos longitudinalmente ou latitudinalmente, em direção à linha, isso não compensará os pontos tanto de uma posição perpendicular preferível.
Ed Camden
Não tenho certeza se essa é a melhor maneira, mas uma maneira de pensar é escrever algum código python para analisar os dois conjuntos de dados e produzir algumas coordenadas de ponto. Se é isso que você pensa que deseja, entre em contato e eu posso fornecer uma resposta para você. Por exemplo, para cada ponto, se o valor absoluto de lat dist da linha <= 5 unidades, distância lateral = 0. Você teria que importar uma biblioteca gdal para converter os valores x, y em cordas. Veja comentários em: gis.stackexchange.com/questions/185445/…
Joe
Com o PyQGIS, pode ser produzida uma camada de memória na qual os pontos são capturados de acordo com a tolerância anteriormente considerada de 5 unidades do mapa e um caminho perpendicular à linha. Veja minha resposta.
Xunilk

Respostas:

15

Existe uma ferramenta interna para fazer isso na versão (não lançada) do QGIS 3.0. Você pode obter um instantâneo noturno no site do QGIS para testar isso com antecedência.

Para fazer isso:

  1. Execute o algoritmo de processamento "Snap geometries to layer"
  2. Selecione sua camada de pontos como a "camada de entrada"
  3. Selecione a camada de linha como a "camada de referência"
  4. Digite uma tolerância adequada (distância máxima para mover pontos durante o snap)
  5. Altere o comportamento para "Preferir o ponto mais próximo"

insira a descrição da imagem aqui

Aqui está o resultado, mostrando os pontos originais como "x" e os pontos ajustados como pontos verdes. Eu usei uma tolerância aqui para que apenas alguns dos pontos de entrada sejam capturados.

insira a descrição da imagem aqui

ndawson
fonte
É exatamente disso que eu preciso. Infelizmente, meu empregador instala apenas versões LTR do QGIS e todos nós estamos impedidos de baixar e instalar versões de teste. (suspiro) Acho que é uma questão de esperar. Essa é uma função padrão / embutida ou um plug-in?
Ed Camden
Funcionalidade padrão que depende de alterações nas classes c ++ - não há como copiar manualmente isso para uma versão mais antiga. Você pode tentar instalar usando o OSGEO4W em uma máquina diferente e, em seguida, copiar a pasta osgeo4w em um pendrive para executar em sua estação de trabalho. Eu tive sorte com essa abordagem no passado.
Ndawson 19/04
1
Para a versão antiga, dê uma olhada neste plugin. docs.qgis.org/2.14/en/docs/user_manual/plugins/…
iRfAn
parece que o plugin não suporta camadas de pontos.
precisa saber é o seguinte
7

Isso pode ser obtido com o PyQGIS . Para a próxima situação:

insira a descrição da imagem aqui

O código a seguir, considerando uma tolerância de 5 unidades de mapa, foi executado no Python Console do QGIS:

from math import sqrt

registry = QgsMapLayerRegistry.instance()

points = registry.mapLayersByName('points')
line = registry.mapLayersByName('line')

feat_points = [ feat for feat in points[0].getFeatures() ]
feat_line = line[0].getFeatures().next()

new_points = []

for feat in feat_points:
    pt = feat.geometry().asPoint()
    sqrdist, point, vertex = feat_line.geometry().closestSegmentWithContext(pt)
    if sqrt(sqrdist) <= 5:
        new_points.append(point)
    else:
        new_points.append(pt)

epsg = points[0].crs().postgisSrid()

uri = "Point?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'new_points',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(new_points)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPoint(new_points[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

Foi produzida uma camada de memória onde os pontos foram capturados de acordo com a tolerância anteriormente considerada de 5 unidades do mapa e um caminho perpendicular à linha.

insira a descrição da imagem aqui

xunilk
fonte
2

Você também pode fazer isso na calculadora de campo com o plug-in refFunctions. Você pode usar a Calculadora de campo para atualizar a geometria da camada e também os campos. refFunctions fornece uma função "geomdistance" para encontrar a linha mais próxima a uma determinada distância (ou "geomnearest" se você não quiser um limite) e retornará um atributo ou a geometria, e a função "closest_point" encontrará o mais próximo ponto em uma determinada geometria. Junte-os assim para calcular novas geometrias para sua camada de pontos:

closest_point(geom_from_wkt(geomdistance('snap_lines','$geometry',10)) , $geometry)

Em vez de atualizar diretamente a geometria, você pode calcular um campo com a geometria ajustada. Armazeno várias geometrias para encaixar pontos de bueiros em diferentes camadas de fluxo e posso atualizar facilmente a geometria de pontos na Calculadora de Campos, dependendo de quais linhas de fluxo eu preciso usar.

Existem algumas limitações nisso, ambas as camadas precisam ser as mesmas CRS e a função de geomdistância fornecerá um erro se você tiver mais de 100.000 pontos, mas você poderá alterar esse limite se editar o arquivo de plug-in refFunctions.

amcaninch
fonte