ホーム » QGIS (ページ 5)

QGIS」カテゴリーアーカイブ

QGISのメニューをPythonから操作

プロジェクトを開くメニューを呼び出す

[code]
actionOpenProject = iface.actionOpenProject();
actionOpenProject.trigger()
[/code]

地物の登録

[code]
actionAddFeature = iface.actionAddFeature();
actionAddFeature.trigger();
[/code]

事前にPOINTレイヤを選択していたらポイントの登録メニューを呼び出す

QGIS3 python レイヤ

レイヤの一覧を照会

[code]
for layer in QgsProject.instance().mapLayers().values():
QgsMessageLog.logMessage(layer.name(), ‘test plugin’, Qgis.Info)
[/code]

レイヤIDからレイヤを求める

[code]
layerTreeLayer=QgsProject.instance().layerTreeRoot().findLayer(layers[0].id())
layer = layerTreeLayer.layer()
[/code]

レイヤ名からレイヤのリスト(List[QgsMapLayer])を照会

[code]
layers=layerTreeLayer=QgsProject.instance().mapLayersByName(レイヤ名)
[/code]

レイヤの表示、非表示を切り替え

[code]
QgsProject.instance().layerTreeRoot().findLayer(レイヤID).setItemVisibilityChecked(False)
[/code]

setItemVisibilityCheckedはQgsMapLayerのメンバーではなくQgsLayerTreeNodeのメンバー。
QgsLayerTreeNodeはQgsLayerTreeLayerの基底クラスであり、QgsLayerTreeNodeはQgsLayerTreeGroupのfindLayerで照会

QGIS3 plugin おさらい

ログの出力

from qgis.core import *

QgsMessageLog.logMessage(“__init__”, ‘test plugin’, Qgis.Info)

メッセージレベルの定数が変更

ダイアログのカスタマイズ

QT Creatorでtest_plugin_dialog_base.uiを開きボタン「btnTest」を追加

通常はQT Creator上でbtnTestのシグナルとスロットの設定を行う。

今回はプログラムで対応。

test_plugin_dialog.pyを編集
[code]
class TestPluginDialog(QtWidgets.QDialog, FORM_CLASS):
def __init__(self, parent=None):
"""Constructor."""
super(TestPluginDialog, self).__init__(parent)
# Set up the user interface from Designer.
# After setupUI you can access any designer object by doing
# self.<objectname>, and you can use autoconnect slots – see
# http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
# #widgets-and-dialogs-with-auto-connect
self.setupUi(self)
self.btnTest.clicked.connect(self.pushButton)

def pushButton(self):
self.close()
[/code]

以上の編集を終了したらQGIS再起動で動作確認(makeは不要)

pyQt4の頃はself.btnTestではなくself.ui.btnTestだったような

スロットの前には@pyqtSlot()を付けたような

レイヤの一覧を出力

ボタンが押されたらレイヤの一覧をログに出力
[code]
def pushButton(self):
for layer in QgsProject.instance().mapLayers().values():
QgsMessageLog.logMessage(layer.name(), ‘test plugin’, Qgis.Info)
[/code]

QGIS3のプラグイン

QGIS2からQGIS3に変更されたことに伴い、プラグインに変更があったので再度確認!

開発環境のセットアップ

※環境はWin10

Qt Creatorのインストール

QTのインストーラー「qt-unified-windows-x86-3.0.5-online.exe」をダウンロードしてインストールを実行

インストールするファイルはとりあえず最小限とする。

QTにアカウントを作成

Python3をインストール

Python3-3.7.0-amd64.exe( Windows x86-64 executable installer)をダウンロードして実行。

インストールが完了したらバージョンを確認して正しくインストールされていることを確認

pyqt5をインストール

pip3コマンド(python3のパッケージ管理システム)を使ってインストール

GNUのmakeコマンドをインストール

Make for WindowsのサイトよりComplete package, except sourcesをダウンロードしてデフォルトのフォルダ(C:\Program Files(X86)\GnuWin32)にインストールしC:\Program Files(X86)\GnuWin32\binにPATHを通す。

以上で環境の構築は終了

とりあえず、Plugin Builderを起動してサンプルとなるPlugin(今回はべたなTest Plugin)を作成

作成したPluginフォルダをカレントにしてmakeコマンドを実行

makeコマンドの出力結果
[code]
pyrcc5 -o resources.py resources.qrc
[/code]
pyrcc5コマンドでQtのリソースファイルをPythonファイルに変換している。
resources.qrcの内容
[code]
<RCC>
<qresource prefix="/plugins/test_plugin" >
<file>icon.png</file>
</qresource>
</RCC>
[/code]

以上のファイルをプラグインのフォルダに配置

[code]
C:\Users\ユーザー名\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins
[/code]

QGISを起動するとプラグインが追加されている

参考にしたサイト

Quick Guide to Getting Started with PyQGIS 3 on Windows

合同会社 緑IT事務所のサイト

QGIS3 wiki Some hints for porting QGIS 2 plugins to the new API of QGIS 3.

Porting QGIS plugins to API v3 – Strategy and tools

stackexchange Make QGIS python plugin for both versions 2.x and 3.x?

書籍 The PyQGIS Programmer’s Guide

QGIS 3 Plugin folder location

JpnStdMeshImportプラグインをQGIS3.0で動くように修正しました

PyQGIS 開発者用 Cookbook ※QGIS2.18の頃の資料

QGIS 選択したFeatureを新規レイヤーに貼り付け

TOOLバーの「領域またはシングルクリックによるチ物選択」ボタンを選択し対象のFeatureを選択

編集メニューのチ物のコピーを選択

編集メニューの新規レイヤへの地物貼り付けを選択

レイヤ名を入力してレイヤを作成

座標を可視化

ポリゴンを表す緯度、経度のCSVファイルを空間データとして可視化するには、
WellknownText形式に変換してQGISで開くのがとっても簡単!

緯度、経度のCSVを
[code]
34.2225148615066,135.164278680816
34.2222647892155,135.164253691228
34.2209399347514,135.164065751247
34.2208400011058,135.166490542546
省略
34.2190481285219,135.163178891017
34.219082076719,135.161066074617
34.2202399699249,135.162128943605
34.220981886875,135.162165915966
34.2225148615066,135.164278680816
[/code]

以下のフォーマットに変換
[code]
POLYGON((135.164278680816 34.2225148615066,135.164253691228 34.2222647892155,135.164065751247 34.2209399347514,135.166490542546 34.2208400011058,135.167490488286 34.2198321377673,135.167478515946 34.2190232289557,135.166240626338 34.2189572083141,135.16444085933 34.2166574274783,135.164740868754 34.2155735568347,135.165003879174 34.2145576776619,135.163853988215 34.214298680841,135.162641134789 34.2130657927005,135.162741137292 34.2127238336321,135.162841140057 34.2123738754678,135.162904142211 34.2121409032373,135.162616135067 34.2131237855764,135.162354128904 34.2140076796957,135.163191050544 34.2141656808295,135.164365856843 34.2169323946867,135.163178891017 34.2190481285219,135.161066074617 34.219082076719,135.162128943605 34.2202399699249,135.162165915966 34.220981886875,135.164278680816 34.2225148615066))
[/code]

更に以下のCSVに変換
[code]
NAME,GEOM
店舗,"POLYGON((135.164278680816 34.2225148615066,135.164253691228 34.2222647892155,135.164065751247 34.2209399347514,135.166490542546 34.2208400011058,135.167490488286 34.2198321377673,135.167478515946 34.2190232289557,135.166240626338 34.2189572083141,135.16444085933 34.2166574274783,135.164740868754 34.2155735568347,135.165003879174 34.2145576776619,135.163853988215 34.214298680841,135.162641134789 34.2130657927005,135.162741137292 34.2127238336321,135.162841140057 34.2123738754678,135.162904142211 34.2121409032373,135.162616135067 34.2131237855764,135.162354128904 34.2140076796957,135.163191050544 34.2141656808295,135.164365856843 34.2169323946867,135.163178891017 34.2190481285219,135.161066074617 34.219082076719,135.162128943605 34.2202399699249,135.162165915966 34.220981886875,135.164278680816 34.2225148615066))"
[/code]

QGISを開き「レイヤ」-「レイヤの追加」-「デリミテッドテキストレイヤの追加」を選択し作成したCSVを開く

座標系を聞かれるので旧日本測地ならばEPSG:4301を選択、世界測地ならばEPSG:4326を選択

以上でQGIS上で確認

spatialiteにイメージをimport(gdal_transfer編)

rasterlite2にこてんぱにやられたので今回はgdal_transferを試す。

参考にしたのはgdal_translateのリファレンスとRasterlite – Rasters in SQLite DB

今回使用したGDAL関連のモジュールはQGISをインストールした際にC:\OSGeo4W\binにインストールしたファイル。

rasterlite2編と同様に「空間データを使うために必要なテーブルを作成」までを実行。

各画像をインポート
[code]
C:\work\pasco>gdal_translate -of Rasterlite 2135.jpg RASTERLITE:work.sqlite,table=source -co DRIVER=JPEG
Input file size is 5000, 3750
0…10…20…30…40…50…60…70…80…90…100 – done.
C:\work\pasco>gdal_translate -of Rasterlite 2136.jpg RASTERLITE:work.sqlite,table=source -co DRIVER=JPEG
Input file size is 5000, 3750
0…10…20…30…40…50…60…70…80…90…100 – done.
C:\work\pasco>gdal_translate -of Rasterlite 2137.jpg RASTERLITE:work.sqlite,table=source -co DRIVER=JPEG
Input file size is 5000, 3750
0…10…20…30…40…50…60…70…80…90…100 – done.
[/code]

Creating internal overviews
[code]
C:\work\pasco>gdaladdo RASTERLITE:work.sqlite,table=source 2 4 8 16
0…10…20…30…40…50…60…70…80…90…100 – done.
0…10…20…30…40…50…60…70…80…90…100 – done.
0…10…20…30…40…50…60…70…80…90…100 – done.
0…10…20…30…40…50…60…70…80…90…100 – done.
[/code]
Creating internal overviewsは以下のほうがよさそうなので改めてGDAL1.10以上バージョンを実行
Creating internal overviews with options (GDAL 1.10 or later):
[code]
C:\work\pasco>gdaladdo RASTERLITE:work.sqlite,table=source 2 4 8 16 –config RASTERLITE_OVR_OPTIONS DRIVER=JPEG,COMPRESS
=JPEG,PHOTOMETRIC=YCbCr
Warning 6: Unexpected option ‘COMPRESS’ for driver ‘JPEG’
Warning 6: Unexpected option ‘PHOTOMETRIC’ for driver ‘JPEG’
0…10…20…30…40…50…60…70…80…90…100 – done.
Warning 6: Unexpected option ‘COMPRESS’ for driver ‘JPEG’
Warning 6: Unexpected option ‘PHOTOMETRIC’ for driver ‘JPEG’
0…10…20…30…40…50…60…70…80…90…100 – done.
Warning 6: Unexpected option ‘COMPRESS’ for driver ‘JPEG’
Warning 6: Unexpected option ‘PHOTOMETRIC’ for driver ‘JPEG’
0…10…20…30…40…50…60…70…80…90…100 – done.
Warning 6: Unexpected option ‘COMPRESS’ for driver ‘JPEG’
Warning 6: Unexpected option ‘PHOTOMETRIC’ for driver ‘JPEG’
0…10…20…30…40…50…60…70…80…90…100 – done.
Creating internal overviews with options (GDAL 1.10 or later):
[/code]

Cleaning internal overviews :
[code]
C:\work\pasco>gdaladdo -clean RASTERLITE:work.sqlite,table=source
[/code]

Creating external overviews in a .ovr file:
[code]
C:\work\pasco>gdaladdo -ro RASTERLITE:work.sqlite,table=source 2 4 8 16
ERROR 6: Cannot add external overviews to a dataset with internal overviews
Overview building failed.
[/code]

「Creating external overviews in a .ovr file:」はエラーが発生したが、QGISで閲覧すると十分なスピードが確保できた。

以上

GeoTIFFのExtentを表示

GeoTIFFのExtentはGDALのユーティリティgdalinfoで表示可能。
gdalinfoのサイト

Windows上で動作するコンパイル済みのGDALモジュールはOsgeoのwikiのダウンロードサイトにあるリンクからたどった
Gisinternalsよりダウンロード
d1

今回は1.9.2 vc2008 32bit版(release-1500-gdal-1-9-2-mapserver-6-2-0.zip)をダウンロード
d2

圧縮ファイル内のbinディレクトリにあるdllとbin\gdal\appsにあるgdalinfo.exeをドイツのディレクトリにおいてコマンドからGEOTIFFのパスを渡すとgeotiffのExtenを含めて各種の情報を表示

d3

PythonとQtでListView

VisualStudio等で開発しているとおなじみのListView

clip_8

これをQTで実現するにはQTreeViewを使用する。

QtデザイナでダイアログにTreeViewを配置して以下のコードを実装。

        model = QStandardItemModel(0,3)
        model.setHeaderData( 0, Qt.Horizontal, ('名称').decode('utf-8'))
        model.setHeaderData( 1, Qt.Horizontal, ('都道府県').decode('utf-8'))
        model.setHeaderData( 2, Qt.Horizontal, ('自治体').decode('utf-8'))

        self.ui.treeView.setRootIsDecorated(False)
        self.ui.treeView.setItemsExpandable(False)
        self.ui.treeView.setModel(model)
        # view.setUniformRowHeights(True)
        model.setItem( 0, 0, QStandardItem(("山田花子").decode('utf-8')))
        model.setItem( 0, 1, QStandardItem(("東京都").decode('utf-8')))
        model.setItem( 0, 2, QStandardItem(("豊島区").decode('utf-8')))
        model.setItem( 1, 0, QStandardItem(("斉藤淳").decode('utf-8')))
        model.setItem( 1, 1, QStandardItem(("埼玉県").decode('utf-8')))
        model.setItem( 1, 2, QStandardItem(("所沢市").decode('utf-8')))

clip_10

PythonとQtでダイアログ表示

Pythonを使ってQGISのプラグインを作るにあたり、QTダイアログについて調べる

QTデザイナを起動して「新規作成」→「Dialog without Buttons」を選択。
clip_2

ボタンを配置し、ui_sampleDlg.uiに保存。

clip_4

pyuic4を使用してuiファイルをPythonファイルに変換

pyuic4 ui_sampleDlg.ui -o ui_sampleDlg.py

※pyuic4.batを使うためにC:\OSGeo4W\binにPATHを通す。
環境変数PYTHONHOMEが設定されていなければpyuic4.batに以下の行を追加

SET PYTHONHOME=C:\OSgeo4w\apps\Python27

変換後のui_sampleDlg.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'ui_sampleDlg.ui'
#
# Created: Sat Apr 23 07:01:53 2016
#      by: PyQt4 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(400, 300)
        self.pushButton = QtGui.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(300, 20, 75, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
        self.pushButton.setText(_translate("Dialog", "PushButton", None))

作成したユーザーインターフェイスを呼び出すクラスをQDialogから派生して作成
クラス名はSampleDlg、ファイル名はSampleDlg.pyとする。
※ifaceは

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'DlgTest.ui'
#
# Created: Wed Apr 20 16:59:11 2016
#      by: PyQt4 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from ui_sampleDlg import Ui_Dialog

class SampleDlg(QDialog):

    def __init__(self, iface):
        QDialog.__init__(self)
        self.iface = iface
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

プラグインからSampleDlgクラスの表示

from SampleDlg import SampleDlg
dlg = SampleDlg(self.iface)
dlg.show()
dlg.exec_() 

以上で正しく表示される

clip_5

次はボタンが押されたらダイアログを閉じるように設定

SampleDlgクラスでボタンのシグナル引っ掛けてダイアログのcloseを呼ぶ

class SampleDlg(QDialog):

    def __init__(self, iface):
        ・・・
        QObject.connect(self.ui.pushButton, SIGNAL("clicked()"), self.pushButton)

    @pyqtSlot()
    def pushButton(self):
        self.close()

以上で終了