Das Feld der QGIS-Attributtabelle automatisch machen?

9

Ich arbeite auf eine Weise, um hydrologische Projekte mit QGIS und einem Excel-Arbeitsblatt zu erstellen, das ich habe. Zu diesem Zweck möchte ich einige Informationen zu den Linien extrahieren, die in einer Vektorebene enthalten sind, die einen Rohrabschnitt darstellt.

Die Informationen, die ich extrahieren muss, sind:

  • ID-Nummer
  • Länge
  • X-, Y-Start- und Endkoordinaten

Ich habe einen Weg gefunden, dieses Feld mit der "$ length" und einem anderen Algorithmus für die X- und Y-Koordinaten zu erfassen, aber dafür muss ich die Attributtabelle öffnen, die Ausdrücke in jede Attributspalte einfügen und klicken, um die Felder zu aktualisieren.

Gibt es eine Möglichkeit, beim Zeichnen einer Linie diese Felder automatisch auszufüllen? Das heißt, ich zeichne / bearbeite eine Linie (beginne mit der Bearbeitung oder beende den Knoten) und wenn ich die Attributtabelle öffne, werden die Längenfelder und Koordinaten X, Y gefüllt und aktualisiert.

LeoNazareth
quelle
1
Ich bin mir nicht sicher, ob es im Bearbeitungsmodus möglich ist, wie es in einer temporären Tabelle geschieht. Aber Sie könnten einen Blick auf Aktionen werfen. Sie können sie beispielsweise verwenden, um Python-Code auszuführen, um Ihre Berechnungen auszufüllen. Nun, Sie müssen einen zusätzlichen Knopf drücken, um ihn aus der Attributtabelle auszuführen. Sie können sich die Möglichkeiten ansehen und prüfen, ob sie zu Ihrer Idee passen.
Matte

Antworten:

7

Wenn Sie diese Felder nur in QGIS benötigen , können Sie virtuelle Felder verwenden. Diese ermöglichen die Verwendung eines Ausdrucks (wie $length), der von anderen Werten oder der Geometrie abhängt.

Öffnen Sie den Feldrechner, fügen Sie ein neues Feld mit der Namenslänge hinzu, aktivieren Sie das Kontrollkästchen "Virtuelles Feld" und geben Sie es $lengthals Ausdruck (oder etwas anderes für die anderen Felder) ein.

Diese werden jedoch nicht in der Excel-Datei gespeichert.

Wenn Sie eine Excel-Datei mit einer SHP-Datei für Geometrie synchron halten und abgeleitete Felder in die Excel-Datei aufnehmen möchten , gibt es ein Plugin namens ShpSync , das dieses Konzept kennt und Felder automatisch aktualisiert, wenn Features geändert, hinzugefügt oder gelöscht werden.

Matthias Kuhn
quelle
Tatsächlich funktioniert die Antwort unten genau so, wie ich es tun möchte, aber dieses Plugin, das Sie gesagt haben, funktioniert für den nächsten Schritt meines Projekts. Vielen Dank für Ihre Hilfe
LeoNazareth
15

Interessante Frage! Mir ist keine andere Möglichkeit bekannt, das zu erreichen, was Sie wollen, als PyQGIS zu verwenden.

Lesen Sie den folgenden Code. Es hat einige Texte in ihm: 'lines', 'length', 'startX', 'startY', 'endX', 'endY'. Sie können diese Namen im Skript so anpassen, dass sie mit Ihren Daten funktionieren. Der erste ist Ihr Ebenenname, während der Rest Feldnamen entspricht. Ich gehe davon aus, dass Ihre Linienebene diese Felder enthält (schließlich möchten Sie, dass dort Werte geschrieben werden).

Nachdem Sie Ihren Ebenennamen und die Namen der Felder angepasst haben, die automatisch aktualisiert werden sollen, kopieren Sie das Skript und fügen Sie es in die QGIS Python-Konsole ein.

Wenn alles gut geht, sollten Sie in zwei Szenarien sehen können, dass Feldwerte automatisch aktualisiert werden: 1) Wenn neue Features hinzugefügt werden und 2) Wenn Geometrien geändert werden.

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

So funktioniert es:

Automatische Aktualisierung von Feldern in QGIS

Wenn Sie beim Ausführen des Skripts Probleme haben, fügen Sie unter dieser Antwort einen Kommentar hinzu.

Es kann hilfreich sein, diese Funktion bereits beim Öffnen Ihres QGIS-Projekts verfügbar zu haben. Wenn das der Fall ist, sag mir, ich könnte Anweisungen dazu posten.


BEARBEITEN:

Damit diese Funktionalität jedes Mal verfügbar ist, wenn Sie Ihr QGIS-Projekt öffnen (dh eine .qgsDatei, die unter anderem Ihre Linienebene enthält), müssen Sie die folgenden Schritte ausführen:

  1. Gehen Sie zu QGIS->Project->Project Properties->Macros, aktivieren Sie die Python macrosOption und ersetzen Sie den gesamten Code durch diesen (passen Sie die Werte an, die Ihre Ebenen- und Feldnamen angeben):

    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. Stellen Sie sicher, dass Sie Makros in Ihrem Projekt folgendermaßen aktivieren : Settings->Options->General->Enable macros: Always.

  3. Speichern Sie Ihr QGIS-Projekt.

Jedes Mal, wenn Sie die .qgsgerade gespeicherte Datei öffnen , werden die Attribute Ihrer Linienebene automatisch aktualisiert, wenn Sie ein neues Feature hinzufügen oder eine Geometrie ändern (dh Sie müssen nichts mehr in die QGIS Python-Konsole kopieren).


2. EDIT:

Ich habe gerade ein Plugin namens AutoFields veröffentlicht , um Menschen bei der Lösung dieser Art von Problemen zu helfen. Ich habe sogar ein Video gemacht, das zeigt, wie Sie Ihr Problem lösen können. Sie können es unter folgender Adresse ansehen:

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

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

Germán Carrillo
quelle
2
Genau das habe ich gesucht. Eigentlich habe ich Ihren Code verwendet, um die X-, Y-Koordinaten zu erfassen, die ich in Ihrer alten Antwort in diesem Post- Link gefunden habe , genau wie Sie jetzt posten. Ich habe die Automatisierung bereits getestet und sie funktioniert einwandfrei. Ich habe den Python-Code als Datei ".pycl" gespeichert. Wenn Sie mir erklären können, wie es verfügbar sein kann, wenn ich mein QGIS-Projekt öffne, ist das großartig. Vielen Dank für die Hilfe.
LeoNazareth
1
Deutsch, das war eine tolle Antwort! Vielen Dank! Ich habe viel von dir gelernt mit dem, was du gepostet hast!
jbgramm
1
Ich arbeite gerade an einem Plugin, mit dem Sie genau das tun können. Da ich mich nur meiner Freizeit widmen kann, kann ich Ihnen keinen voraussichtlichen Veröffentlichungstermin nennen. In der Zwischenzeit können Sie mein erstes Code-Snippet ausführen, nachdem Sie Tramo.shp hinzugefügt haben. Passen Sie Folgendes an: myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'Tramo' )[0]Wenn Sie wirklich an meinem zukünftigen Plugin interessiert sind, senden Sie mir bitte Ihre Vorschläge. Ich würde mich freuen . Sie können mich bei GeoTux kontaktieren .
Germán Carrillo
1
Das wird großartig für mich (und natürlich für viele Leute), ich verwende den Code bereits mit dieser von Ihnen vorgeschlagenen Anpassung. Ich werde gespannt auf dein neues Plugin warten und wenn ich an etwas Nützliches denke, melde ich mich bei dir. Danke für alles.
LeoNazareth
1
@LeoNazareth, möchtest du das Plugin testen? Es wird fertig, aber ich möchte einige Tests durchführen, bevor ich es veröffentliche. Wenn Sie bereit sind, es zu testen, senden Sie mir bitte eine E-Mail .
Germán Carrillo
2

Für QGIS 3 gehen Sie zu Layers Properties=> Attributes Form=> wählen Sie Ihr Feld mit Geometriewerten aus (im Beispiel area) => geben Sie $areadas Defaults valueKontrollkästchen ein und aktivieren Sie es Apply default value on update. Dies könnte auch sein nützlich: $perimeter, $y, $x,$id

Herr Che
quelle
1

Ich würde die Daten in eine Datenbank (PostGIS) stellen und die Daten mit einer (wahrscheinlich materialisierten) Ansicht in QGIS extrahieren.

Nielsgerrits
quelle