QGIS属性テーブルフィールドを自動化しますか?


9

QGISと私が持っているExcelワークシートを使用して水文プロジェクトを作成する方法で作業しています。これを行うには、パイプセクションを表すベクターレイヤーに含まれているラインの情報を抽出します。

抽出する必要がある情報は次のとおりです。

  • ID番号
  • 長さ
  • X、Yの開始座標と終了座標

「$ length」とX座標とY座標の別のアルゴリズムを使用してこのフィールドをキャプチャする方法を見つけましたが、そのために属性テーブルを開き、各属性列に式を入力して、フィールドをクリックして更新する必要があります。

線を引くときに、これらのフィールドが自動的に入力される方法はありますか?つまり、線を描画/編集し(編集の開始またはノードの終了)、属性テーブルを開くと、長さフィールドと座標X、Yが入力および更新されます。


1
一時テーブルで行われるため、編集モードで可能かどうかはわかりません。しかし、あなたは行動を見ているかもしれません。たとえば、Pythonコードを実行して計算を埋めるためにそれらを使用できます。属性テーブルから実行するには、追加のボタンを押す必要があります。あなたはそこにある可能性を見て、それがあなたのアイデアに合うかどうか見ることができます。
マット2016

回答:


7

QGIS内でこれらのフィールドのみが必要な場合は、仮想フィールドを使用できます。これらにより$length、他の値またはジオメトリに依存する式(など)を使用できます。

フィールド計算機を開き、長さという名前の新しいフィールドを追加し、[仮想フィールド]チェックボックスをオンにして$length、式(または他のフィールド用の何か)として入力します。

ただし、これらはExcelファイルに保存されません。

excelファイルをジオメトリのshpファイルと常に同期させ、excelファイルに派生フィールドを含めたい場合ShpSyncと呼ばれるプラグインがあり、この概念を認識し、機能が変更、追加、または削除されたときにフィールドを自動的に更新します。


実際、以下の答えは私がやりたいように正確に機能しますが、あなたが言ったこのプラグインは私のプロジェクトの次のステップで機能します。あなたの助けをありがとう
LeoNazareth

15

興味深い質問です!私はあなたが望むものを達成する他の方法を知りませんが、PyQGISを使用します。

以下のコードを読んでください。それはそれでいくつかのテキストを持っています:'lines''length''startX''startY''endX''endY'。スクリプトでこれらの名前を調整して、データで機能するようにすることができます。最初はレイヤー名ですが、残りはフィールド名に対応しています。私はあなたのラインレイヤーがそれらのフィールドを持っていると思います(結局のところ、そこに値を書き込む必要があります)

レイヤー名と自動的に更新するフィールドの名前を調整したら、スクリプトをコピーしてQGIS Pythonコンソールに貼り付けます。

すべてがうまくいけば、2つのシナリオでフィールド値が自動的に更新されることがわかります。1)新しい機能が追加されたとき、および2)ジオメトリが変更されたとき。

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

これはどのように機能するかです:

QGISのフィールドの自動更新

スクリプトの実行中に問題が発生した場合は、この回答の下にコメントを追加してください。

QGISプロジェクトを開いたときに、この機能がすでに利用可能になっていると便利です。その場合は、教えてください。そのための指示を投稿できます。


編集:

この機能をQGISプロジェクト(つまり.qgs、とりわけラインレイヤーを含むファイル)を開くたびに使用できるようにするには、次の手順に従う必要があります。

  1. に移動しQGIS->Project->Project Properties->MacrosPython macrosオプションを確認して、コード全体を次のコードに置き換えます(レイヤー名とフィールド名を示す値を調整します)。

    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. 次のようにして、プロジェクトでマクロを必ず有効にしてくださいSettings->Options->General->Enable macros: Always

  3. QGISプロジェクトを保存します。

.qgs保存したばかりのファイルを開くたびに、新しいフィーチャを追加したり、ジオメトリを変更したりすると、ラインレイヤーの属性が自動的に更新されます(つまり、QGIS Pythonコンソールに何もコピーする必要がなくなります)。


2番目の編集:

AutoFieldsと呼ばれるプラグインを公開しました。この種の問題を解決するのに役立ちます。私はあなたの問題を解決する方法を示すビデオを作りました、あなたはそれを以下で見ることができます:

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

AutoFieldsのドキュメント:http ://geotux.tuxfamily.org/index.php/en/geo-blogs/item/333-autofields-plugin-for-qgis


2
これはまさに私が探していたものです。実際、私はあなたのコードを使用してX、Y座標をキャッチしていました。これは、この投稿リンクの以前の回答で見つけたもので、現在投稿しているものと同じです。私はすでに自動化をテストしましたが、完全に機能します。Pythonコードをファイル「.pycl」として保存しました。QGISプロジェクトを開いたときにどのように利用できるかを説明していただければすばらしいと思います。助けてくれてありがとう。
LeoNazareth

1
ドイツ語、それは素晴らしい答えでした!ありがとう!あなたが投稿したものを私はあなたから多くを学びました!
jbgramm 2016

1
私は実際にそれを行うことができるプラグインに取り組んでいます。私は自分の暇な時間しか開発に専念できないので、リリース予定日はわかりません。それまでの間、Tramo.shpを追加した後、最初のコードスニペットを実行して調整myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'Tramo' )[0]することができます。私の将来のプラグインに本当に興味がある場合は、私に提案を送ってください。よろしくお願いします。GeoTuxで私に連絡できます。
ヘルマン・カリージョ

1
それは私にとって(そしてもちろん、多くの人にとって)素晴らしいことです。私はすでにあなたが提案したこの調整でコードを使用しています。私はあなたの新しいプラグインを心配そうに待ちます、そして何か私が何か役に立つと思ったら連絡します。いろいろとありがとうございます。
LeoNazareth 2016年

1
@LeoNazareth、プラグインをテストしますか?準備はできていますが、リリースする前にいくつかのテストを実行したいと思います。テストしていただける場合は、メールでお知らせください。
ヘルマン・カリージョ

2

QGIS 3の場合はLayers Properties=> Attributes Form=>に移動し、ジオメトリ値(例:)を含むフィールドを選択しますarea=> ボックスに入力$areaして、Defaults valueをオンにしApply default value on updateます。また、これは便利かもしれません:$perimeter$y$x$id


1

データをデータベース(PostGIS)に入れ、(おそらく具体化された)ビューでデータをQGISに抽出します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.