Tornando o campo da tabela de atributos QGIS automático?

9

Estou trabalhando de maneira a criar projetos hidrológicos usando o QGIS e uma planilha do Excel que possuo. Para fazer isso, quero extrair algumas informações das linhas, incluídas em uma camada vetorial, que representa uma seção de tubo.

As informações que eu preciso extrair são:

  • Número de identidade
  • comprimento
  • Coordenadas X, Y inicial e final

Eu encontrei uma maneira de capturar esse campo usando o "$ length" e outro algoritmo para as coordenadas X e Y, mas para isso eu preciso abrir a tabela Attributes, coloque as expressões em cada coluna de atributo e clique em para atualizar os campos.

Existe uma maneira de quando eu desenho uma linha esses campos são preenchidos automaticamente? Ou seja, eu desenho / edito uma linha (iniciar a edição ou nó final) e quando abro a tabela de atributos, os campos de comprimento e as coordenadas X, Y são preenchidos e atualizados.

LeoNazareth
fonte
11
Não tenho certeza se isso é possível enquanto estiver no modo de edição, como é feito em uma tabela temporária. Mas você pode dar uma olhada nas ações. Você pode usá-los, por exemplo, para executar código python para preencher seus cálculos. Bem, você precisa pressionar um botão extra para executá-lo da tabela de atributos. Você pode dar uma olhada nas possibilidades existentes e ver se isso se encaixa na sua ideia.
Matte

Respostas:

7

Se você precisar apenas desses campos dentro do QGIS , poderá usar campos virtuais. Isso permite o uso de uma expressão (como $length) que depende de outros valores ou da geometria.

Abra a calculadora do campo, adicione um novo campo com o tamanho do nome, marque a caixa de seleção "Campo virtual" e digite $lengthcomo expressão (ou qualquer outra coisa para os outros campos).

No entanto, eles não serão salvos no arquivo do Excel.

Se você deseja manter um arquivo do Excel sincronizado com um arquivo shp para geometria e incluir campos derivados no arquivo do Excel, existe um plugin chamado ShpSync que conhece esse conceito e atualiza os campos automaticamente quando os recursos são alterados, adicionados ou excluídos.

Matthias Kuhn
fonte
De fato, a resposta abaixo funciona exatamente como eu quero fazer, mas esse plug-in que você disse funcionará para a próxima etapa do meu projeto. Obrigado pela ajuda.
LeoNazareth
15

Pergunta interessante! Não conheço outra maneira de conseguir o que deseja, mas usando o PyQGIS.

Leia o código abaixo. Tem alguns textos em que: 'lines', 'length', 'startX', 'startY', 'endX', 'endY'. Você pode ajustar esses nomes no script para que ele funcione nos seus dados. O primeiro é o nome da camada, enquanto o restante corresponde aos nomes dos campos. Presumo que sua camada de linha tenha esses campos (afinal, você deseja que os valores sejam escritos lá).

Depois de ajustar o nome da camada e os nomes dos campos que você deseja atualizar automaticamente, copie e cole o script no console do QGIS Python.

Se tudo correr bem, você poderá ver que os valores do campo são atualizados automaticamente em dois cenários: 1) Quando novos recursos são adicionados e 2) Quando as geometrias são modificadas.

# Initialize required variables
myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0]
lengthField = myLayer.fieldNameIndex( 'length' )
startXField = myLayer.fieldNameIndex( 'startX' )
startYField = myLayer.fieldNameIndex( 'startY' )
endXField = myLayer.fieldNameIndex( 'endX' )
endYField = myLayer.fieldNameIndex( 'endY' )

# Slot, updates field values
def updateFeatureAttrs( fId, geom=None ):
    f = myLayer.getFeatures( QgsFeatureRequest( fId ) ).next()    
    if not geom:
        geom = f.geometry() 
    myLayer.changeAttributeValue( fId, lengthField, geom.length() )
    myLayer.changeAttributeValue( fId, startXField, geom.vertexAt( 0 )[0] )
    myLayer.changeAttributeValue( fId, startYField, geom.vertexAt( 0 )[1] )
    myLayer.changeAttributeValue( fId, endXField, geom.asPolyline()[-1][0] )
    myLayer.changeAttributeValue( fId, endYField, geom.asPolyline()[-1][1] )

# Update feature attributes when new features are added or geometry changes
myLayer.featureAdded.connect( updateFeatureAttrs )
myLayer.geometryChanged.connect( updateFeatureAttrs )

É assim que funciona:

Atualizações automáticas de campos no QGIS

Se você tiver algum problema ao executar o script, adicione um comentário abaixo desta resposta.

Pode ser útil que você já tenha essa funcionalidade disponível ao abrir seu projeto QGIS. Se for esse o caso, diga-me, eu poderia postar instruções para fazer isso.


EDITAR:

Para que essa funcionalidade esteja disponível sempre que você abrir o seu projeto QGIS (ou seja, um .qgsarquivo que contém, entre outros, sua camada de linha), siga estas etapas:

  1. Vá para QGIS->Project->Project Properties->Macros, marque a Python macrosopção e substitua o código inteiro por este (ajuste os valores indicando seus nomes de camada e campo):

    from qgis.core import QgsMapLayerRegistry, QgsFeatureRequest
    def openProject():    
        # Initialize required variables
        myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0]
    
        # Update feature attributes when new features are added or geometry changes
        myLayer.featureAdded.connect( updateFeatureAttrs )
        myLayer.geometryChanged.connect( updateFeatureAttrs )
    
    # Slot, updates field values
    def updateFeatureAttrs( fId, geom=None ):
        myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0]
        lengthField = myLayer.fieldNameIndex( 'length' )
        startXField = myLayer.fieldNameIndex( 'startX' )
        startYField = myLayer.fieldNameIndex( 'startY' )
        endXField = myLayer.fieldNameIndex( 'endX' )
        endYField = myLayer.fieldNameIndex( 'endY' )
        f = myLayer.getFeatures( QgsFeatureRequest( fId ) ).next()    
        if not geom:
            geom = f.geometry() 
        myLayer.changeAttributeValue( fId, lengthField, geom.length() )
        myLayer.changeAttributeValue( fId, startXField, geom.vertexAt( 0 )[0] )
        myLayer.changeAttributeValue( fId, startYField, geom.vertexAt( 0 )[1] )
        myLayer.changeAttributeValue( fId, endXField, geom.asPolyline()[-1][0] )
        myLayer.changeAttributeValue( fId, endYField, geom.asPolyline()[-1][1] )
    
    def saveProject():
        pass
    
    def closeProject():
        pass
  2. Certifique-se de habilitar as macros no seu projeto, desta forma: Settings->Options->General->Enable macros: Always.

  3. Salve seu projeto QGIS.

Agora, toda vez que você abrir o .qgsarquivo que acabou de salvar, os atributos da camada de linha serão atualizados automaticamente quando você adicionar um novo recurso ou modificar uma geometria (ou seja, não será mais necessário copiar nada no QGIS Python Console).


2ª EDIÇÃO:

Acabei de publicar um plugin chamado AutoFields para ajudar as pessoas a resolver esse tipo de problema. Eu até fiz um vídeo mostrando como resolver seu problema, você pode assistir em:

https://vimeo.com/germap/autofields-geometric-properties

Documentação do AutoFields: http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/333-autofields-plugin-for-qgis

Germán Carrillo
fonte
2
Era exatamente isso que eu estava procurando. Na verdade, eu estava usando seu código para capturar as coordenadas X, Y, que encontrei na sua resposta antiga neste link de postagem , a mesma que você publica agora. Eu já testei a automação e funciona perfeitamente. Salvei o código Python como um arquivo ".pycl". Se você puder me explicar como ele estará disponível quando eu abrir o meu projeto QGIS, será ótimo. Obrigado pela ajuda.
LeoNazareth
11
Alemão, essa foi uma resposta incrível! Obrigado! Eu aprendi muito com você com o que você postou!
Jbgramm
11
Na verdade, estou trabalhando em um plug-in que permitirá que você faça exatamente isso. Como eu posso dedicar ao seu desenvolvimento apenas meu tempo livre, não posso dizer a data prevista para o lançamento. Enquanto isso, você pode executar o meu primeiro trecho de código depois de adicionar o Tramo.shp, ajustando: myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'Tramo' )[0]Se você estiver realmente interessado no meu futuro plug-in, envie-me as sugestões que tiver. Você pode entrar em contato comigo no GeoTux .
Germán Carrillo
11
Isso será ótimo para mim (e para muitas pessoas, é claro), já estou usando o código com esse ajuste que você sugeriu. Vou aguardar ansiosamente o seu novo plugin, e se eu achar algo útil, entrarei em contato com você. Obrigado por tudo.
LeoNazareth
11
@LeoNazareth, você gostaria de testar o plugin? Está se preparando, mas eu gostaria de realizar alguns testes antes de liberá-lo. Se você estiver disposto a testá-lo, envie-me um e-mail .
Germán Carrillo
2

Para o QGIS 3, vá para Layers Properties=> Attributes Form=> escolha seu campo com valores geométricos (por exemplo area) = = digite $areana Defaults valuecaixa e marque Apply default value on update. Isso também poderia ser útil: $perimeter, $y, $x,$id

Mr. Che
fonte
1

Eu colocaria os dados em um banco de dados (PostGIS) e extrairia os dados para o QGIS com uma visão (provavelmente materializada).

nielsgerrits
fonte