Como adicionar Direção e Distância à tabela de atributos?

18

qualquer um que possa ajudar. Eu só quero adicionar direção (rolamento: N 25 35 E) e distância (comprimento: 125 metros) como meu novo campo em dados de polilinha / linha. existe um plug-in para gerar esses campos? Eu tentei usar "exportar / adicionar colunas de geometria" nos meus dados de linha, mas apenas o valor "Comprimento" foi adicionado.

Arzandia
fonte
Até agora eu posso usar o plugin mmqgis para me dar distância. Estou explorando o problema de direção.
Willy
1
Como são os seus dados de polilinha? A distância é relativamente fácil de calcular - no entanto, o 'rolamento' pode mudar ao longo do comprimento de uma polilinha. Você está procurando rumo do ponto inicial ao ponto final ?
Simbamangu
Sim, estou olhando para o rolamento do ponto de partida ao ponto final ... obrigado
arzandia
1
Deseja uma distância em linha reta do ponto inicial ao ponto final ou o comprimento da linha seguindo o caminho da linha? Eles podem variar amplamente se o segmento de linha tiver curvas intermediárias ou outras mudanças de direção.
RyanKDalton-OffTheGridMaps

Respostas:

42

Você pode calcular o rumo na calculadora de campo no QGIS. Isso funciona em coordenadas UTM (métricas) em pequenas distâncias (centenas de km), mas algo mais sofisticado seria necessário para grandes distâncias ou graus decimais.

Abra a tabela de atributos para sua camada de linha, alterne a edição e clique no botão Calculadora de Campo para abrir a caixa de diálogo:

insira a descrição da imagem aqui

Crie um novo campo como decimal com precisão de 1 ou 2.

Cole este código na caixa "Expressão" e clique em "OK": (atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/3.14159 + (180 *(((yat(-1)-yat(0)) < 0) + (((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) >0)*2)))

A primeira parte calcula a tangente inversa das diferenças x e y e a converte em graus (180 / pi). A segunda parte adiciona 180 ou 360 à figura resultante para dar um rolamento de 0 a 360 °.

Simbamangu
fonte
2
Uma solução mais elegante, obrigado. Eu mencionaria que, se você precisar determinar o rumo para cada segmento de uma polilinha, poderá fazê-lo dividindo o arquivo shapefile da linha com o plug-in 'Split Feature'. Em seguida, carregue o novo shapefile (dividido) e siga o procedimento acima.
N
1
@arzandia - observe que você DEVE usar o QGIS 1.9 (consulte a página inicial para downloads beta), pois as funções xat () e yat () não funcionam na versão 1.7, que você está usando!
Simbamangu
Eu já usei o plug que você mencionou. como você pode ver a imagem, nome da camada é "dividida" ...
arzandia
1
Para responder minha própria pergunta, "Sim, você pode inserir valores de campo para yat (0) / yat (-1) e xat (0) / xat (-1)".
cbunn
1
Para mim, eu tive que fazer algumas alterações no script para fazê-lo funcionar: (atan ((xat (0) -xat (1)) / (yat (0) -yat (1)))) * 180 / 3.14159 (180 * (((yat (0) -yat (1)) <0) + (((xat (0) -xat (1)) <0 AND (yat (0) - yat (1))> 0) * 2)))
oskarlin
21

Você não precisa de um plugin. Tudo está na classe QgsPoint de PyQGIS

Se você examinar o conteúdo de uma classe de pontos QGIS com a função incorporada Python dir () no Console Python.

dir(point])
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__'
, '__getitem__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'azimuth', 
'multiply', 'set', 'setX', 'setY', 'sqrDist', 'sqrDistToSegment', 'toDegreesMinutesSeconds', 'toString', 'wellKnownText', 'x', 'y']

Você pode ver que existem funções de azimute e sqrDist e depois de algumas tentativas:

- xy[0].azimuth(xy[1]) or xy[1].azimuth(xy[0]) gives the azimuth direction between two points(in degrees, +/- 180°)
- xy[0].sqrDist(xy[1]) give the square distance between two points (in the unit of the project)

O problema insira a descrição da imagem aqui

Então, no console Python

def select_all(layer):
     layer.select([])
     layer.setSelectedFeatures([obj.id() for obj in layer])

myline = qgis.utils.iface.activeLayer()
select_all(myline)
for elem in myline.selectedFeatures():
      xy = elem.geometry().asPolyline()

agora xy contém todos os nós (pontos) da linha

# first point
print "x=%2d y=%2d" % (xy[0].x(),xy[0].y())
x=112935 y=117784
# and others...

Usando todos os pontos de nó da linha:

1) ponto azimutal i para ponto i + 1 (+/- 180 °) (nós de uma linha)

for i in range(len(xy)-1):
     print "x=%2d y=%2d azim=%6.1f azim2=%6.1f" % (xy[i].x(), xy[i].y(), xy[i].azimuth(xy[i+1]), xy[i+1].azimuth(xy[i]))

x=112935 y=117784 azim= 168.4 azim2= -11.6
x=113032 y=117312 azim=-167.5 azim2=  12.5
x=112926 y=116835 azim= 177.3 azim2=  -2.7
x=112943 y=116472 azim= 145.1 azim2= -34.9
[...]

2) distância euclidiana entre o ponto i e o ponto i + 1

for i in range(len(xy)-1):
     print "x=%2d y=%2d dist=%6.1f" % (xy[i].x(), xy[i].y(), xy[i].sqrDist(xy[i+1]))

x=112935 y=117784 dist=232533.9
x=113032 y=117311 dist=238243.6
x=112926 y=116835 dist=131839.8
x=112943 y=116472 dist=209268.1
[...]

Depois, não é muito difícil adicionar esses valores à tabela de atributos.

Eu uso essa técnica para analisar os lineamentos (geologia) com matplotlib e o plugin Script Runner

insira a descrição da imagem aqui

gene
fonte
5
+1 - Ótima solução! Deve ... aprender ... Python ...
Simbamangu
Esta é uma ótima solução e super valiosa para os geólogos .. mas também muito complicada
Shawn
10

A solução fornecida pelo @Simbamangu é bastante eficaz, mas não abrange todos os casos. Por exemplo, aplicar a fórmula com um deslocamento horizontal NULL o resultado, portanto você deve usar esta fórmula na Calculadora de campo do QGIS

case
when yat(-1)-yat(0) < 0 or yat(-1)-yat(0) > 0 then 
(atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/3.14159 + 
(180 *
(((yat(-1)-yat(0)) < 0) + 
(((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) >0)*2)
))
when ((yat(-1)-yat(0)) = 0 and (xat(-1) - xat(0)) >0) then 90
when ((yat(-1)-yat(0)) = 0 and (xat(-1) - xat(0)) <0) then 270
end
Sergio
fonte