PyQGIS フューチャー選択サンプル

PyQGISでフューチャー選択の方法を調べたので、サンプルとしてまとめました。作成したサンプルは次のサイトを参考にしました。

gis.stackexchange.com

webgeodatavore.github.io


マウスで選択

使い方

f:id:Chiakikun:20200128003707p:plain

①ベクタレイヤを選択します。

 

f:id:Chiakikun:20200128003747p:plain

プラグインのアイコンを押下します。

 

f:id:Chiakikun:20200128003823p:plain

③フューチャーが選択できる状態になりますので、マウスで一つ選択すると...

 

f:id:Chiakikun:20200128003913p:plain

⑤レイヤが編集状態になり...

 

f:id:Chiakikun:20200128004143p:plain

⑥属性編集ダイアログが表示されるので、編集します。『OK』ボタンを押下すると編集内容が反映されて、レイヤの編集状態が解除されます。

 

プラグインのアイコンが押されている間は、フューチャーを選択する度に編集ダイアログが表示されます。

コード

featureselect_sample.py

class FeatureSelectSample:
    """QGIS Plugin Implementation."""

~中略~

    def execSample(self):
        if self.isrun:
            self.exitFunc()

        else:
            self.layer = self.iface.activeLayer()

            if (self.layer == None) or (type(self.layer) is not qgis.core.QgsVectorLayer):
                QMessageBox.about(None, '警告', 'ベクタレイヤを選択してから実行してください')
                self.action.setChecked(False)
                return

            self.iface.layerTreeView().currentLayerChanged.connect(self.changeLayer)
            self.iface.actionSelect().trigger()
            self.layer.selectionChanged.connect(self.editAttribute)
            self.previousMapTool = qgis.utils.iface.mapCanvas().mapTool()
            self.isrun = True

    def editAttribute(self):
        features = self.layer.selectedFeatures()

        if len(features) == 0:
            return

        if len(features) != 1:
            QMessageBox.information(None, '警告', 'フューチャーを1つ選択してください')
            return

        self.layer.startEditing()
        attdlg = self.iface.getFeatureForm(self.layer, features[0])
        attdlg.setMode(qgis.gui.QgsAttributeEditorContext.SingleEditMode)
        attdlg.finished.connect(self.commitEdit)
        attdlg.show()

    def commitEdit(self, result):
        if result == 1:
            self.layer.commitChanges()
        else:
            self.layer.rollBack()

    def changeLayer(self, layer):
        self.layer.removeSelection()

        if (layer == None) or (type(layer) is not qgis.core.QgsVectorLayer):
            self.exitFunc()
            return

        self.layer.selectionChanged.disconnect(self.editAttribute)

        self.layer = layer
        self.layer.selectionChanged.connect(self.editAttribute)

こちらにソースを置いておきます。


式で選択

使い方

f:id:Chiakikun:20200128004716p:plain

①ベクタレイヤをアクティブにした状態でプラグインアイコンを押下します。

f:id:Chiakikun:20200128004812p:plain

②上のダイアログが表示されます。

 

f:id:Chiakikun:20200128004846p:plain

③対象フィールドを選択して、クエリ式を入力します。クエリ式でフューチャーが選択可能なら画像のように表示されます。

今回は国土交通省からダウンロードできる行政区画のシェープのフィールド「N03_001」の値で「島」が入っているレコードを抽出するために、次の式を使いました。

    Like '%島%'

 

f:id:Chiakikun:20200128005703p:plain

④式が有効であれば赤丸のボタンが有効になります。

 

f:id:Chiakikun:20200128005747p:plain

⑤『実行』ボタンを押下すると、クエリ式で抽出できたレコードのみの属性テーブルが表示されます。

 

f:id:Chiakikun:20200128005940p:plain

⑥クエリで抽出できたフューチャーが選択されている状態になっています。

コード

featureselectexpr_sample_dialog.py

class FeatureSelectExprSampleDialog(QtWidgets.QDialog, FORM_CLASS):

~中略~

    def testPush(self):
        self.query = ''

        query = '"' + self.fieldsBox.currentText() + '" ' + self.queryEdit.text()

        features = self.layer.getFeatures(qgis.core.QgsFeatureRequest().setFilterExpression(query))
        if len(list(features)) == 0:
            return

        self.query = query
        QtWidgets.QMessageBox.information(None, '情報', 'エラーなし')
        self.execButton.setEnabled(True)
        self.saveButton.setEnabled(True)

~中略~

    def execPush(self):
        QSettings().setValue("/Qgis/dockAttributeTable", True)
        self.layer.selectByExpression(self.query)
        self.iface.showAttributeTable(self.layer, self.query)

~略~

こちらにソースを置いておきます。

最後までご覧頂き、ありがとうございました

QGIS オブジェクトに重なるオブジェクトの属性をカンマ区切りで取得する

こちらのページを参考に、あるオブジェクトに重なるオブジェクトの属性をカンマ区切りで取得してみました。少し手こずる箇所がありましたので、メモしたいと思います。

gis.stackexchange.com

 

f:id:Chiakikun:20200124125538p:plain

今回は関東地方の各県(レイヤ名は関東地方)に重なる2次メッシュ(レイヤ名はjpmesh_2)のメッシュ番号(フィールド名はcode)をカンマ区切りで取得します。


属性をカンマ区切りで取得する

仮想レイヤを作成する

f:id:Chiakikun:20200124131315p:plain

メニューの『レイヤ』→『レイヤの作成』→『仮想レイヤを新規作成』を選択します。

クエリを設定して新レイヤを追加する

f:id:Chiakikun:20200124131441p:plain

『インポート』ボタンを押下して、仮想レイヤ作成に必要なレイヤを選択します。今回は関東地方とjpmesh_2を使って新しいレイヤを作成するので、この2つをインポートします。

クエリには次のコードを入力します。

SELECT 関東地方.geometry, N03_001, group_concat(code) As meshs
FROM 関東地方 ,jpmesh_2 where st_intersects(関東地方.geometry, jpmesh_2.geometry) 
group by N03_001

 関東地方のそれぞれの県に重なるjpmesh_2を、フィールド「N03_001」の値(県名)毎にまとめて、カンマで結合してフィールド「meshs」の値として新レイヤに投入します。

『テスト』ボタンを押下して、エラーが無ければ『追加』ボタンを押下して、新レイヤを追加します。

f:id:Chiakikun:20200124132614p:plain

追加されました。

追加されたレイヤの属性

f:id:Chiakikun:20200124132734p:plain

このようにフィールド「meshs」にjpmesh_2のフィールド「code」の値がカンマ区切りで入りました。


保存時の注意点

シェープファイルで保存すると...

f:id:Chiakikun:20200124133115p:plain

シェープファイルで保存するとフィールド型の文字数設定が254である為、値が途中で切れてしまいます。

青丸部分は指数表記になってしまっています。この点については後述します。

CSVで保存すると...

f:id:Chiakikun:20200124134649p:plain

オブジェクト情報は無くなりますが、csvで保存してみます。すると...

 

f:id:Chiakikun:20200124134739p:plain

文字列は切られていませんが、指数表示の部分はそのままでした。ですが...

 

f:id:Chiakikun:20200124134953p:plain

LibreOfficeで表示してみたら、問題無く表示されており、

 

f:id:Chiakikun:20200124135051p:plain

メモ帳で開いても問題無かったので、エクセルの問題でした。

オブジェクト情報残したい場合

GeoPackageやMIFに保存した場合は文字列が切られることは無かったので、カンマ区切りで取得した文字列が長い場合はシェープ以外のファイル形式を検討してみてください。

最後までご覧頂き、ありがとうございました

QGISのポリゴン融合処理を速くしたい


国土数値情報ダウンロードサービスからダウンロードできる行政区画のシェープファイルを下のように融合させた時の処理時間が結構長かったので、時短を試みた際のメモです。

 

f:id:Chiakikun:20200118231340p:plain


一度に全部融合させた場合

まずは普通に融合させてみます。

融合を実行する

f:id:Chiakikun:20200119112238p:plain

メニューの『ベクタ』→『空間演算ツール』→『融合』を選択します。

設定

f:id:Chiakikun:20200119113538p:plain

出力レイヤ以外はそのままで『実行』ボタンを押下します。

結果

約34時間で全部融合できました。


2回に分けて融合させた場合

まずこんな感じに融合させます

f:id:Chiakikun:20200122172713p:plain

フィールドを追加する

f:id:Chiakikun:20200122172852p:plain

市町村で分けられている行政区画を大雑把に融合してみます。今回はフィールド「N03_007」の一番左の1文字目を使います。

フィールド「tmp」を追加します。タイプはテキストとします。

融合に使うフィールドに値を投入する

f:id:Chiakikun:20200122174136p:plain

左赤丸のコンボボックスからフィールド「tmp」を選択して、式の入力欄に次のコードを入力します。フィールド「N03_007」の値が空の場合は文字aが、空でない場合は値の一番左の文字がフィールド「tmp」に入ります。

if("N03_007" IS NOT NULL, left("N03_007", 1), 'a')

コードを入力したら右赤丸の『全部更新』ボタンを押下します。すると...

f:id:Chiakikun:20200122175225p:plain

文字がフィールド「tmp」に入りました。

融合を実行する

f:id:Chiakikun:20200122175416p:plain

融合してみます。メニューの『ベクタ』→『空間演算ツール』→『融合』を選択し、ダイアログの赤丸のボタンを押下すると『複数選択』ダイアログが表示されるので、「tmp」を選択して『OK』ボタンを押下します。
約1.5時間でこんな感じに融合されます。

その後は全部融合させる場合と同じ設定(入力レイヤは、融合させたレイヤ)で融合を実行します。

結果

一度融合させた時間も含めて、 約12時間で全部融合できました。

 

最後までご覧頂き、ありがとうございました。