Rendere automatico il campo della tabella degli attributi QGIS?


9

Sto lavorando in un modo per realizzare progetti idrologici usando QGIS e un foglio di lavoro Excel che ho. Per fare ciò, desidero estrarre alcune informazioni sulle linee, incluse in un livello vettoriale, che rappresenta una sezione di pipe.

Le informazioni che devo estrarre sono:

  • Numero ID
  • Lunghezza
  • Coordinate di inizio e fine X, Y.

Ho trovato un modo per acquisire questo campo usando "$ length" e un altro algoritmo per le coordinate X e Y, ma per questo ho bisogno di aprire la tabella degli attributi, inserire le espressioni in ogni colonna degli attributi e fare clic per aggiornare i campi.

C'è un modo per quando traccio una linea che questi campi vengono compilati automaticamente? Cioè, disegno / modifico una linea (inizio modifica o termina nodo) e quando apro la tabella degli attributi i campi di lunghezza e le coordinate X, Y vengono riempiti e aggiornati.


1
Non sono sicuro se sia possibile mentre si è in modalità di modifica come in una tabella temporanea. Ma potresti dare un'occhiata alle azioni. Puoi usarli ad esempio per eseguire il codice Python per compilare i tuoi calcoli. Bene, devi premere un pulsante extra per eseguirlo dalla tabella degli attributi. Puoi dare un'occhiata alle possibilità che ci sono e vedere se si adatta alla tua idea.
Matte

Risposte:


7

Se sono necessari solo questi campi all'interno di QGIS , è possibile utilizzare i campi virtuali. Ciò consente di utilizzare un'espressione (come $length) che dipende da altri valori o dalla geometria.

Apri il calcolatore di campo, aggiungi un nuovo campo con la lunghezza del nome, seleziona la casella di controllo "Campo virtuale" e inserisci $lengthcome espressione (o qualcos'altro per gli altri campi).

Questi tuttavia non verranno salvati nel file Excel.

Se si desidera mantenere un file Excel sincronizzato con un file shp per la geometria e includere campi derivati ​​nel file Excel, esiste un plug-in chiamato ShpSync che è a conoscenza di questo concetto e aggiorna automaticamente i campi quando le funzionalità vengono modificate, aggiunte o eliminate.


In effetti, la risposta di seguito funziona esattamente come voglio fare, ma questo plugin che hai detto funzionerà per il prossimo passo del mio progetto. Grazie per il vostro aiuto
LeoNazareth,

15

Domanda interessante! Non sono a conoscenza di altri modi per ottenere ciò che desideri, ma utilizzando PyQGIS.

Leggi il codice qui sotto. Ha alcuni testi in esso: 'lines', 'length', 'startX', 'startY', 'endX', 'endY'. Puoi adattare quei nomi nello script affinché funzioni sui tuoi dati. Il primo è il nome del tuo livello, mentre il resto corrisponde ai nomi dei campi. Suppongo che il tuo livello di linea abbia quei campi (dopo tutto, vuoi che i valori vengano scritti lì).

Dopo aver modificato il nome del layer e i nomi dei campi che si desidera vengano aggiornati automaticamente, copiare e incollare lo script nella console di QGIS Python.

Se tutto va bene, dovresti essere in grado di vedere che i valori dei campi vengono aggiornati automaticamente in due scenari: 1) Quando vengono aggiunte nuove funzionalità e 2) Quando le geometrie vengono modificate.

# 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 )

Ecco come funziona:

Aggiornamenti automatici dei campi in QGIS

In caso di problemi durante l'esecuzione dello script, aggiungere un commento sotto questa risposta.

Potrebbe esserti utile avere questa funzionalità già disponibile quando apri il tuo progetto QGIS. In tal caso, dimmi, potrei pubblicare le istruzioni per farlo.


MODIFICARE:

Affinché questa funzionalità sia disponibile ogni volta che apri il tuo progetto QGIS (ovvero un .qgsfile contenente, tra l'altro, il tuo livello di linea) devi seguire questi passaggi:

  1. Vai a QGIS->Project->Project Properties->Macros, seleziona l' Python macrosopzione e sostituisci l'intero codice con questo (regola i valori che indicano i nomi dei livelli e dei campi):

    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. Assicurarsi di abilitare le macro sul vostro progetto, in questo modo: Settings->Options->General->Enable macros: Always.

  3. Salva il tuo progetto QGIS.

Ora, ogni volta che apri il .qgsfile che hai appena salvato, gli attributi del tuo livello di linea verranno automaticamente aggiornati quando aggiungi una nuova funzione o modifichi una geometria (cioè, non c'è più bisogno di copiare nulla nella QGIS Python Console).


2a modifica:

Ho appena pubblicato un plugin chiamato AutoFields per aiutare le persone a risolvere questo tipo di problemi. Ho anche realizzato un video che mostra come risolvere il tuo problema, puoi guardarlo su:

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

Documentazione di AutoFields: http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/333-autofields-plugin-for-qgis


2
Questo e 'esattamente quello che stavo cercando. In realtà stavo usando il codice per prendere il coordinate X, Y, che Ive ha trovato nella risposta vecchio in questo post di collegamento , la stessa che si registra ora. Ho già testato l'automazione e funziona perfettamente. Ho salvato il codice Python come file ".pycl". Se puoi spiegarmi come può essere disponibile quando apro il mio progetto QGIS, sarà fantastico. Grazie per l'aiuto
LeoNazareth,

1
Tedesco, è stata una risposta fantastica! Grazie! Ho imparato molto da te con quello che hai pubblicato!
jbgramm,

1
In realtà sto lavorando a un plugin che ti permetterà di fare esattamente questo. Dato che posso dedicare al suo sviluppo solo il mio tempo libero, non posso dirti una data di rilascio prevista. Nel frattempo, potresti eseguire il mio primo frammento di codice dopo aver aggiunto Tramo.shp, regolando: myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'Tramo' )[0]Se ti interessa davvero il mio futuro plug-in, ti prego di inviarmi qualsiasi suggerimento tu abbia, lo apprezzerei. Potete contattarmi a GeoTux .
Germán Carrillo,

1
Sarà fantastico per me (e per molte persone, ovviamente), sto già usando il codice con questa correzione che mi hai suggerito. Aspetterò con ansia il tuo nuovo plugin, e se penso a qualcosa di utile ti contatterò. Grazie di tutto.
LeoNazareth,

1
@LeoNazareth, vuoi testare il plugin? Si sta preparando, ma mi piacerebbe eseguire alcuni test prima di rilasciarlo. Se sei disposto a provarlo, ti prego di inviarmi una e-mail .
Germán Carrillo,

2

Per QGIS 3 vai su Layers Properties=> Attributes Form=> scegli il tuo campo con i valori della geometria (ad esempio area) => digita $areala Defaults valuecasella e seleziona Apply default value on update. Questo potrebbe anche essere utile: $perimeter, $y, $x,$id


1

Vorrei mettere i dati in un database (PostGIS) ed estrarre i dati in QGIS con una vista (probabilmente materializzata).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.