qgisプログラミング入門 2016osaka編
TRANSCRIPT
目次1 本日の内容........................................................................................................................................32 本題に入る前の基礎知識.................................................................................................................4
2.1QGIS とは?................................................................................................................................42.2Qt とは?.....................................................................................................................................42.3Python とは?..............................................................................................................................4
3Python の基本的な文法.....................................................................................................................53.1 変数への代入............................................................................................................................63.2 組み込み型と扱い.....................................................................................................................63.3 制御フロー.................................................................................................................................93.4 関数..........................................................................................................................................103.5 クラス........................................................................................................................................113.6 パッケージ................................................................................................................................13
4Python コンソールから操作..............................................................................................................144.1 すべての基本は QgisInterface から........................................................................................144.2 ユーザインタフェース編..........................................................................................................164.3 ベクトル編(図形にアクセス)....................................................................................................184.4 ベクトル編(描画設定)..............................................................................................................204.5Canvas イベント編.....................................................................................................................21
5Plugin の基本...................................................................................................................................225.1Plugin の基本構成...................................................................................................................225.2Plugin Builder...........................................................................................................................235.3metadata.txt...............................................................................................................................285.4__init__.py................................................................................................................................285.5 処理本体が記載されたファイル..............................................................................................305.6 ダイアログの変更.....................................................................................................................32
6 デバッグ環境...................................................................................................................................377 プロセッシング入門.........................................................................................................................38
7.1 プロセッシングとは?...............................................................................................................387.2Python コンソールからプロセッシング......................................................................................387.3 関数を利用する.......................................................................................................................417.4 プロセッシングスクリプト...........................................................................................................42
8 参考資料.........................................................................................................................................45
2/45
1 本日の内容 このセッションでは、
• QGIS コアライブラリの構成といった前提知識の説明
• 簡単な Python 文法講習
• QGIS Python コンソールからの CUI による QGIS 操作
• QGIS Plugin 構成の説明
• 簡単な Plugin の作成
までを行います。
時間を見ながら、プロセッシングにも触れてみたいと思います。
QGIS 2.0 から API が変更されており、以前のバージョンと共通で使用出来ない部分があります。本セッショ
ンでは、QGIS 2.8 で動作検証を行った内容で行います。使用していただく QGIS は 2.8 以降のものを使用し
てください。
本セッションで使用するデータは、Public Domain でデータを提供している NaturalEarth のものを使用して
います。
http://www.naturalearthdata.com
3/45
2 本題に入る前の基礎知識
2.1 QGISとは?
一般的な説明は抜きにします。
QGIS は C++で書かれており、インタフェース部分については Qt ライブラリを使用しています。QGIS の構成
は、コアライブラリ、アプリケーション本体、プラグインに大別出来ます。コアライブラリは、
• QGIS Core Library
• QGIS GUI Library
• QGIS Analysis Library
• Map Composer
• QGIS Network Analysis Library
• QGIS Server Library
に分かれています。Python コンソールから QGIS にアクセスする際、Plugin から QGIS にアクセスする際は、
これらのライブラリを通して、QGIS の機能を使用することになります。また、これらのライブラリを個別に使用して、
別なアプリケーションを作成することも可能となります。
C++で書かれている QGIS ですが、SIP というツールを使用して、Python 用インタフェースも提供されていま
す。Qt についても同様に Python 用のインタフェースが提供されています。これにより、プラグインを開発する場
合、C++で書く、Python で書く、の2通りの方法を選択出来ます。ただし、Python については全ての機能を使
用出来る訳ではなく、Python 用インタフェースが提供されている機能のみ使用出来るという点で注意が必要で
す。例として、データハンドリングの根幹に関するプラグインについては、アプリケーション全体の実行速度に影
響を与えるため Python での作成は出来なくなっています。C++、Python の使い分けとしては、
• Python はコンパイルの必要が無いが、C++ではコンパイルが必要
• QGIS のどの部分にアクセスするのか
• 配布先の OS を考慮した場合に、C++では OS にあったライブラリの作成が必要
といった点を考慮して決める必要があります。とはいえ、どちらで開発するのがお手軽かといえば、Python を使
用する場合になります。
2.2 Qtとは?
C++で書かれたアプリケーション・ユーザーインタフェースのフレームワークです。GoogleEarth や Skype が
Qt で作られています。Qt の特徴は単一のソースで、Windows、Linux、Mac Os といった様々なプラット
フォーム上で動作するアプリケーションが開発可能なことです。また様々な言語のバインディングが用意されて
おり、Python からも使用することが出来ます。開発環境として QtCreater、GUI 開発環境として Qt Designerといった環境が提供されており、開発が迅速に行えることも特徴です。
2.3 Pythonとは?
Python はプログラムの実行前にコンパイルを必要としないスクリプト言語または軽量言語と呼ばれる種類のプ
ログラミング言語です。他の言語に比べて文法がシンプルで習得がしやすい言語となっています。また、誰が書
いても同じような記述になるような工夫がされています。その一つとしてインデント(字下げ)が重要という点が挙
げられます。例えばループを表す際に、Python ではループ内のブロックのインデントを揃えることで表します。
4/45
QGIS のプラグイン開発にも利用出来ますし、ArcGIS の ArcPy での採用例もありますので、地理情報を扱う
技術者としては押さえておきたいプログラミング言語です。
3 Pythonの基本的な文法 この後の操作をスムーズにするため、Python の基本的な文法を押さえておきます。動作の確認は QGIS の
Python コンソールから行います。
QGIS 2.8 の Python コンソール
5/45
3.1 変数への代入
Python では変数の型をあらかじめ指定しておく必要はなく、
変数名 = 代入する値、オブジェクトなど
を指定した際に変数が作成されます。変数名をタイプすると、変数に代入されている値・クラスを確認出来ます。
>>>test = 'foss4g'
>>>test
'foss4g'
作成済みではない変数がタイプされた際は、エラーとなります。
>>>test2
Traceback (most recent call last):File "<input>", line 1, in <module>NameError: name 'test2' is not defined
3.2 組み込み型と扱い
a) 数値型
数値型は整数型、浮動小数点型、複素数型が用意されています。ただし、ここでは複素数型は使用しないの
で、説明は省きます。
数値に足しては「+」「-」「*」「/」「%」「**」といった演算子を使用して計算を行えます。注意しておく点としては、
計算結果は数値の精度を保とうとして返されることがあげられます。例として整数/整数の計算結果は整数となり
ます。
>>>15/7
2
一方の数値が浮動小数点型の場合は、浮動小数点型の結果が返されます。
>>>15.0/7
2.142857142857143
計算の優先順位は、足し算・引き算より、掛け算・割り算が優先されるというように、通常の四則演算と同様です。
優先順位を明示する場合は、「(」「)」でくくります。
>>>1+2*3
7
>>>(1+2)*3
9
b) 文字列
Python では文字列は「'(シングルコーテーション)」もしくは「”(ダブルコーテーション)」で囲って表現します。
通常はシングルコーテーションを使用します。文字列中のコーテーション記号や、特殊記号はバックスラッシュで
エスケープします。
6/45
>>> 'foss4g'
'foss4g'
>>>'foss4g \'2013\' tokyo'
“foss4g '2013' tokyo”
>>>a = 'foss4g \ntokyo'
>>>print a
foss4g
tokyo
3 重のコーテーション記号を使うと、複数行にまたがった文字列を表現出来ます。
>>>a = '''foss4g
...2013
...tokyo'''
>>>print a
文字列は添字表記で一部を参照することが可能です。最初の文字のインデックスが 0 になります。
>>>a = 'foss4g'
>>>a[0]
'f'
>>>a[1:2]
'o'
ただし文字列の一部を書き換えることは出来ないので、注意しておいて下さい。下記の処理はエラーになりま
す。
>>> a = 'foss4g'
>>>a[1] = 'b'
Python の文字列型は数値・アルファベットといった ASCII 文字を扱うための文字列型(string)と、マルチバイ
ト文字列を扱うためのユニコード文字列(unicode string)型があります。漢字、ひらがなといった日本語を扱う場
合、先頭のコーテーション記号の前に'u'を付けて下さい。下記コードの実行結果を比べてみて下さい。
>>>a = 'とっても簡単'
>>>a
>>>print a
>>>a = u'とっても簡単'
>>>a
>>>print a
文字列は”+”演算子で連結することが出来ます。
>>>a = 'foss4g' + 'osaka'
>>>print a
7/45
foss4gosaka
c) リスト
Python では別々のデータを1まとめにして使う場合の複合型がいくつか用意されています。そのうちもっとも
汎用的なのがリストになります。カンマで区切られた値を「[」「]」角括弧で囲んで表します。文字列と同様に添字
で各要素にアクセスすることが出来ます。
>>>a = ['osaka', 2016, u'大坂', u'市大']
>>>a
['osaka', 2016, u'\u5927\u5742', u'\u5e02\u5927']
>>>a[1]
2016
>>>a[0:2]
['osaka', 2016]
リストは連結することも出来ますし、要素を指定して入れ替えることも出来ます。
>>>a = ['osaka', 'city'] + [2016]
>>>a
['osaka', 'city', 2016]
>>>a[2] = 'university'
>>>a
['osaka', 'city', 'university']
d) 辞書
辞書は他の言語において、”連想配列”として実装されているものです。辞書はキーと値のペアの集合になりま
す。キー:値のペアをカンマで区切り、「{」「}」波括弧で囲んで表します。
>>>a = {'place':'osaka', 'year':2016}
>>>a['place']
'osaka'
辞書中に特定のキーが存在しているかを調べる場合は、in を使用します。
>>>'place' in a
True
8/45
3.3 制御フロー
a) if文
他の言語と同様の if 文が用意されています。インデント(字下げ)には気をつけてください。
条件文
実行する処理 1
実行する処理 2
>>>x = 130
>>>if x < 130:
… print 'small'
…elif x == 130:
… print 'equal'
...else:
… print 'big'
…
b) for文
Python の for 文が他の言語と違うところとして、任意のシーケンス(リスト、文字列)にわたって反復を行います。
>>>a = ['osaka', 'city', 2016]
>>>for x in a:
… print x
…
osaka
city
2016
数列にわたって反復を行う場合は、range()を使用します。range(10)は 0 から始まり、0 から始まる 10 個の値
からなるリストを生成します。開始数値を指定したり、増加数(減少数)を指定することも出来ます。
>>>range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>for i in range(2,10,2):
… print i
…
9/45
スペースの数を揃える
2
4
6
8
c) while文
while 文の使用方法は他の言語と変わりません。指定の条件を満たす間処理を繰り返します。
>>>cnt = 0
>>>while cnt < 10:
… print cnt
… cnt += 1
…
3.4 関数
a) 関数を利用する
for 文ですでに出てきていますが、range()は標準で用意されている組み込み関数です。関数を使用する場
合は、関数名に続き「(」「)」丸括弧で引き数を添えて関数を呼び出します。以下は引き数として文字列を渡すと、
文字数を返す len()の例になります。
>>>len('foss4g')
6
b) 関数を作る
関数の定義は def の後に関数名と引き数を丸括弧で囲んで行います。関数の処理本体は、行を変えてインデ
ントをして記述します。
>>>def test(a):
… print a
…
>>>test(10)
10
関数に戻り値がある場合は、処理本体内で return の後に記述します。
>>>def test(a):
… return a+10
…
>>>test(10)
20
引き数に省略可能なデフォルト値を指定しておくことも出来ます。
10/45
>>>def test(a=0):
… print a
…
>>>test()
0
c) 変数のスコープ
Python では関数内で定義された変数は関数の内部でしか使用出来ません。下記の例では関数の内部で変
数 a を、関数の外で変数 a が定義されていますが、別なものになります。
>>>def test(a):
… a += 10
… print a
…
>>>a = 100
>>>test(10)
20
>>>a
100
リストや辞書のような書き換え可能なオブジェクトを引き数として渡す場合は参照渡しになりますので、注意が
必要になります。
>>>def test(a):
… a += ['osaka]
… print a
…
>>>b = ['foss4g']
>>>test(b)
['foss4g', 'osaka']
>>>b
['foss4g', 'osaka']
3.5 クラス
a) クラスを作る
クラスの定義は class の後にクラス名を記述して行います。ラクスの内部には関数定義、クラス変数を記述しま
す。
>>>class test:
11/45
… def output(self):
… print 10
…
>>>a = test()
>>>a.output()
10
インスタンス生成時に実行される特別なメソッドとして__init__()を定義しておくことが出来ます。
>>>class test():
… def __init__(self):
… self.a = 10
… def output(self, c):
… print self.a + c
…
>>>b = test()
>>>b.output(10)
20
12/45
b) self
a)クラスを作るで作成したクラス中に定義されている関数の第一引数には”self”が指定されています。self を
指定しておくと、各関数内から自身のインスタンスへのアクセスが可能となります。
c) 継承
あるクラスをベースとして派生クラスを作成する場合は、下記のような記述をします。
>>>class 派生クラス名(ベースクラス名):
… クラスの記述
多重継承も行え、その場合はベースクラスを列挙します。
>>>class 派生クラス名(ベースクラス名 1, ベースクラス名2):
… クラスの記述
3.6 パッケージ
a) パッケージ
プログラムが長くなってきた場合、また再利用可能な部品に分けて管理しておく場合、ファイルに分割しておき
ます。その際に、ドット付きのモジュール名を使って構造化しておきます。A.B というモジュール名は、A という
パッケージの B というモジュールを表します。モジュール名と実体のディレクトリ、ファイルの関係は下記のように
なります。
A/ ------ ディレクトリ A
B.py --- ファイル B
b) import
import の構文として 1 パターンだけ紹介しておきます。
from A.B import *
上記の構文は、A/B.py からファイル内のクラス、関数全てを import することになります。
13/45
4 Pythonコンソールから操作
4.1 すべての基本はQgisInterfaceから
QGIS を起動して、Python コンソールを立ちあげて下さい。
## 詳しい情報とメソッドのリストが必要な場合は help(iface)とタイプして下さい.という記述が最初に書かれています。iface が QgisInterface クラスのインスタンスになります。QgisInterface ク
ラスは、Python コンソールや、Plugin から QGIS アプリケーションにアクセスする際に窓口になるクラスです。こ
こから、各GUI パーツ、読み込み済みのレイヤ等にアクセスすることになります。
クラスの定義はドキュメントが公開されていますので、確認しましょう。
QGIS API Documentation http://www.qgis.org/api/index.html
14/45
ドキュメントのバージョンには注意してください。”QGIS API Documentation”の対応するバージョンが書か
れています。最新(開発版)のドキュメントになっていますので、対応するバージョンを選択して参照するようにし
てください。
QgisInterface クラスの定義を見てみましょう。2.8版のドキュメントはこちらになります。
http://qgis.org/api/2.8/classQgisInterface.html
signal と slot という記述が出てきます。これは Qt の特長的な機能になります。メニューが選択される、ファイ
ルが選択されるといったある動作(signal)が発生した際に、その動作に関連付けられて実行される関数が slotになります。プログラム中では、signal と slot の関連付けは下記のような記述で行います。
QObject.connect(イベント発生元インスタンス、SIGNAL('メソッド名')、イベント受け取り先インスタン
ス、SLOT('メソッド名'))
では、実際に操作を行なって行きましょう。
15/45
こちらを選択
4.2 ユーザインタフェース編
QGIS のユーザインタフェースを、そのクラスから大別してみます。
1. 各メニューは QMenu クラスで出来ています
例えば、”プラグイン”メニューにアクセスして表示させることは、
>>>pluginMenu =iface.pluginMenu()
>>>pluginMenu.show()
のように行えます。また、”プラグイン”メニューへのメニュー追加/削除メソッドとして、
QgisInterface.addPluginToMenu()
QgisInterface.removePluginMenu()
が用意されていることが、ドキュメントからわかります。すでに用意されているメニューに関しては、用意さ
れているメソッドを通して操作を行えます。
2. 各ツールバーは QToolBar クラスで出来ています。
例えば、”プラグイン”ツールバーにアクセスして、表示/非表示を切り替えることは、
>>>pluginToolBar = iface.pluginToolBar()
>>>pluginToolBar.hide()
>>>pluginToolBar.show()
のように行えます。また、”プラグイン”ツールバーへのアイコン追加/削除メソッドとして、
QgisInterface.addToolBarIcon()
16/45
2
34
1
QgisInterface.removeToolBarIcon()
が用意されていることが、ドキュメントからわかります。
3. 読み込み済みのレイヤー一覧には QgisLegendInterface クラスのインスタンスからアクセス出来ます。
>>>legend = iface.legendInterface()
>>>legend.layers()
[]
データの読み込みがされていない状態では空のリストが帰ってきます。メニューから手動で、いくつかベ
クトルデータを追加してみて下さい。追加後に QgisLegendInterface にアクセスしてみると、レイヤが
追加されていることが確認出来ます。下記の例では、ベクトルレイヤを 1 つだけ追加してあります。
>>>legend.layers()
[<qgis.core.QgsVectorLayer object at 0x0CC376A8>]
リストの最初のレイヤについて、表示/非表示を切り替えてみましょう。
>>>layers = legend.layers()
>>>legend.setLayerVisible(layers[0], False)
>>>legend.setLayerVisible(layers[0], True)
4. QMapCanvas クラスのインスタンスからアクセス出来ます。スケールを変更してみましょう。
>>>canvas = iface.mapCanvas()
>>>canvas.zoomScale(100000000)
17/45
4.3 ベクトル編(図形にアクセス)
ne_50m_admin_0_countries.shp を読み込み、各要素にアクセスしてみましょう。
C:\work\ne_50m_admin_0_countries.shp
を読み込むことを想定します。
1. ベクトルデータの読み込み
>>>iface.addVectorLayer(r'C:\work\ne_50m_admin_0_countries.shp', 'countries', 'ogr')
最初の引き数は読み込むファイル名、2番目はレイヤ名称として使用されます、3番目の引き数は使用
する QgisDataProvider へのキーになります。QgisDataProvider はデータソースからの読み込み、書
き込み、ハンドリング全般を行うクラスです。通常、ベクトルデータを扱う場合は ogr を使用することで足
りるはずです。もしオリジナルのデータフォーマット等に対応して QgisDataProvider を用意した場合な
どは指定が必要になります。
2. 選択されているレイヤを取得します。いまは 1 つのレイヤしか開いていませんので、先ほど読み込んだ
レイヤが返ってきます。
>>>layer = iface.activeLayer()
名称を表示して確認してみましょう。
>>>layer.name()
3. 全ての図形要素に順次アクセスしてみます。
QgsFeatureIterator クラスを通して各図形に順次アクセス出来るようになっています。
>>>features = layer.getFeatures()
>>>for feature in features:
… feature.geometry()
...
例では、各ベクトル要素に順次アクセスを行い、その図形クラス(QgsGeometry)を書き出しています。
4. 次に特定の属性をもったベクトル要素を選択しましょう。国名は'name'属性に入っていることがわかって
いるとします。下記のように各図形へ属性名を指定して直接参照できます。
>>>feature['name']
レイヤ内の図形に順次アクセスを行い、属性を書きだしてみます。
>>>features = layer.getFeatures()
>>>for feature in features:
… feature['name']
...
5. 次に属性'name'が'Japan'のベクトル要素を選択して、その要素の範囲にズームしてみましょう。
>>>features = layer.getFeatures()
>>>for feature in features:
18/45
… if feature['name'] == u'Japan':
… break
…
>>>canvas = iface.mapCanvas()
>>>canvas.setExtent(feature.geometry().boundingBox())
>>>canvas.refresh()
19/45
4.4 ベクトル編(描画設定)
レイヤ全体の描画設定を変更してみましょう。描画で設定する色や塗りつぶし種別の指定に、PyQt のクラスが
必要になるので、読み込みます。
>>>from PyQt4.QtCore import *
>>>from PyQt4.QtGui import *
Python コンソールの”クラスのインポート”から入力することもできます。
QgsSymbolV2 というシンボル設定を作成しておき、それを layer の描画指定(renderer)に入れてあげるという手
順で行います。
>>>layer = iface.activeLayer()
>>>symbol = QgsSymbolV2.defaultSymbol(QGis.Polygon)
>>>fillLayer = QgsSimpleFillSymbolLayerV2(QColor(255, 0, 0), Qt.SolidPattern)
>>>symbol.appendSymbolLayer(fillLayer)
>>>renderer = QgsSingleSymbolRendererV2(symbol)
>>>layer.setRendererV2(renderer)
>>>iface.mapCanvas().refresh()
描画設定については、GUI と見比べながらクラスを探していくと、わかりやすいと思います。
20/45
4.5 Canvas イベント編
canvas 上で発生するイベントを拾ってみましょう。canvas 上でクリックされた位置と、その位置の地理座標を
QGIS で用意しているメッセージビューワに表示します。QMapCanvas クラスではマウスクリックのイベントを拾
うことが出来ません。QgsMapTool というクラスを継承した新しいクラスを作成しておき、イベント発生時の動作
を追加します。新しく作成したクラスを QMapCanvas クラスに設定することでイベントに対応させます。
>>>from qgis.gui import *
>>>class QgsMapToolClick(QgsMapTool):
... def canvasPressEvent(self, event):
… dPos = event.pos()
… mPos = self.toMapCoordinates(dPos)
… view = qgis.gui.QgsMessageViewer()
… view.setMessageAsHtml('<p>' + str(dPos.x()) + ',' + str(dPos.y()) + '</p><p>' + str(mPos.x()) + ',' + str(mPos.y()) + '</p>')
… view.showMessage(True)
…
>>>canvas = iface.mapCanvas()
>>>toolClick = QgsMapToolClick(canvas)
>>>canvas.setMapTool(toolClick)
21/45
5 Pluginの基本 この章では Python コンソールから一旦離れて、Plugin に必要なファイルをテキストエディタを使用して編集し
て頂きます。
5.1 Pluginの基本構成
QGIS の起動時に読み込まれる python プラグインは、
QGIS インストールディレクトリ/python/plugins
ユーザーのホームディレクトリ/.qgis2/python/plugins
に入れておきます。通常、オリジナルのプラグインを作成した場合は、後者に配置することになります。windowsを想定しますが、
C:\Users\ユーザ名\.qgis\python\plugins\test
というような形で、plugin毎のディレクトリを作成することになります。
QGIS は plugins ディレクトリ内の各ディレクトリを見ていき、
metadata.txt
というファイルからプラグインの情報を読み取ります。また、各プラグインの qgis への追加は、
__init__.py
から行われます。__init__.py 内には、処理本体が記述されたクラスを返す関数を記載しておきます。通常、処
理本体は別なファイルに記述する方が判りやすいので、名前はなんでもいいですが、最低もう1ファイル作成す
ることになります。
22/45
5.2 Plugin Builder
プラグインに必要なファイルを個別に用意していくことも可能ですが、”Plugin Builder”プラグインを使用する
と、最低限必要な内容を揃えてくれるので便利です。「プラグイン」「プラグインの管理とインストール」か
ら”Plugin Builder”をインストールしましょう。
23/45
インストールが終了したら、早速 plugin builder を起動しましょう。必要な情報を入れると、プラグインの雛形を
作成してくれます。
まずはプラグインの基本情報として、Class name:
プラグインのクラス名です。python ファイル内で使用されます。キャメルケース(複合語をひと綴
りとして、要素語の最初を大文字)で記述します。
Plugin name: プラグインマネージャー等で表示されるプラグイン名
Description: プラグインマネージャー等で表示されるプラグインの説明文
Module name: python のモジュール名
Version number: プラグインのバージョン
Minimum QGIS version: プラグインが動作する QGIS の最低バージョン
Author/Company: プラグイン作者名
Email address: 作者メールアドレス
を入力します。
24/45
続いてプラグインの詳細な説明を記述します。ここでは適当な文を入れておくだけにしましょう。
作成するプラグインのテンプレートとして 3 種類用意されています。”Tool Button with dialog”を選択してお
いてください。UI としてプラグイン実行時に表示される dialog も一緒に作成してくれます。メニューへ表示する
文字列と、どのメニューに表示するかも設定しておきます。
25/45
多言語対応やヘルプ等の雛形も一緒に作成することができます。ただし、ここでは最小限のプラグインを作成
してみることを目的としますので、すべてのチェックを外しておきましょう。
プラグインの不具合報告先を明確にしておくため、Bug tracker、Repository の Url 入力を求められます。
ここでは適当な文字列を入れておくだけにしましょう。ただし、きちんとしたプラグインを公開する場合は、github等で公開することが推奨されていることは覚えておくべきです。
26/45
ここまでの入力が終わると、プラグイン書き出し先のディレクトリの指定になります。
ユーザーのホームディレクトリ/.qgis2/python/pluginsに書き出してください。
ユーザーのホームディレクトリ/.qgis2/python/plugins/PluginTestを開き、plugin buider によりファイルが作成されていることを確認してください。
さて、書きだされたプラグインを実行してみたいところですが、その前にもう一手間必要です。メニュー、ツール
バーで表示されるアイコン画像は、 icon として使用する画像ファイルへのパスを記述した、Qt のリソースファイ
ルの中にファイル名が記述されています。ファイル名は、resources.qrc
となっています。リソースファイルは xml で記述されており、内容は下記になります。
このファイル を Python のコードへ変換しておく必要がありますので、pyrcc4 コマンドで変換を行います。
Windows で OSGeo4W を使用している場合、OSGeo4W の command shell を起動して、プラグインを作成
しているディレクトリに移動してください。移動した後、
> pyrcc4 -o resources.py resources.qrc
を実行して resources.py が作成されたことを確認します。
27/45
<RCC> <qresource prefix="/plugins/PluginTest" > <file>icon.png</file> </qresource></RCC>
これで最小限のプラグイン作成は終了です。qgis を立ち上げてみましょう。「プラグイン」「プラグインの管理とイ
ンストール」の中から”plugin test”を探してインストールしてみてください。
空の dialog が表示されるだけのプラグインですが、実行を確認できます。
5.3 metadata.txt
必須となる幾つかのファイルの内容を見ていきましょう。metadata.txt はプラグインに関する情報が記載されて
います。テキストエディタで開いてみましょう。
決められた変数に”=”で繋いで値を代入していることがわかります。plugin builder で入れた情報が記載され
ていますが、必要に応じて書き換えることができます。
5.4 __init__.py
プラグイン読み込みの際に最初に読み込まれるファイルです。classFactory()という関数を記載しておきます。
この中で処理の本体となるモジュールを読み込み、必要なインスタンスを返しています。 QgisInterface のイン
スタンスである iface が渡されていることを確認しておきましょう。プラグイン内でも iface を通して qgis を操作す
ることになります。
28/45
[general]name=plugin testqgisMinimumVersion=2.0description= てすとですversion=0.1author=asahiemail=waigania13@gmail
29/45
def classFactory(iface): # pylint: disable=invalid-name """Load PluginTest class from file PluginTest.
:param iface: A QGIS interface instance. :type iface: QgsInterface """ # from .plugin_test import PluginTest return PluginTest(iface)
5.5 処理本体が記載されたファイル
処理が記載されたクラスが最低限持つ必要があるメソッドは、
initGui(): プラグインが使用可になった場合に実行されるメソッド
unload(): プラグインが使用不可になった場合に実行されるメソッド
の2つになります。
plugin_test.py の内容を見てみましょう。まずは initGui()です。
メニューやツールバーへのプラグインの追加自体は、self.add_action()で行われています。add_action()の中の下記の行を見てみましょう。
QAction は、メニューやツールバーに追加されるユーザインタフェース部品になります。action の triggerd が
callback(引数で self.run が渡されています)に connect されています。
作成された QAction がツールバーとメニューに追加されているのがわかります。
実際に行われる処理は、run()に書かれています。
ここでは、作成済みのダイアログの表示を行っているだけになります。もし何か単一の処理をメニュー/ツール
バーから選択された際に行いたいだけであえば、ダイアログの表示部分を削除して、この中に処理を書けばい
いことになります。self.iface から qgis にアクセスもできます。
30/45
def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI."""
icon_path = ':/plugins/PluginTest/icon.png' self.add_action( icon_path, text=self.tr(u'plugin test'), callback=self.run, parent=self.iface.mainWindow())
action = QAction(icon, text, parent) action.triggered.connect(callback)
if add_to_toolbar: self.toolbar.addAction(action)
if add_to_menu: self.iface.addPluginToMenu( self.menu, action)
def run(self): """Run method that performs all the real work""" # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. pass
unload()も見てみましょう。
initGui()、add_action()で作成した QAction をツールバー、メニューから削除しています。
31/45
def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu( self.tr(u'&plugin test'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar
5.6 ダイアログの変更
plugin builder を使用すると、空のダイアログは作成してくれます。このダイアログを変更する方法を見てみま
しょう。
ダイアログの作成/変更には、QtCreator を利用します。qt のホームページ(http://www.qt.io/download/ )から、環境にあった Qt Creator のダウンロードを行い、インストールを行います。
Commercial版と OpenSource版がありますので、OpenSource版に進んでください。”Get Started”を選択
します。
必要なのは QtCreater になりますので、Qt Offline Installer から”Qt Creator”を選択してください。環境に
あった Qt Creator のダウンロードを行い、インストール行ってください。
32/45
インストールが正常に行われると、QtCreator が windows のスタートメニューに加わっています。
QtCreator を起動してください。「ファイル」「ファイル/プロジェクトを開く」から plugin builder で作成された
plugin_test_dialog_base.ui を開きます。
画面左のウィジェットボックスから、”Text Edit”をドラッグしながら、Dialog 上に配置してください。 配置し
た”Text Edit”にプログラムからアクセスする場合には、プロパティに表示される”objectName”で識別します。
判りやすいものに変えておいた方が良いですが、今回は作成時に入れられる名前のままで進みます。
33/45
Dialog自体の大きさも変更して、適当な大きさにしておきましょう。
レイアウトを整えたら、次にボタンの signal が、どの slot に connect されているか確認しておきましょう。下段
の”Signals & Slots Editor”から確認することができます。
button_box からの accepted() (OKボタンの signal)が、dialog の accept()に、rejected()が dialog の
reject()に、それぞれ connect されていることがわかります。button_box からの signal を別な slot に connectする、もしくは dialog の slot を上書きしてあげれば処理を変更することができます。
作成の終了したダイアログは、「Save “plugin_test_dialog_base.ui”」で上書きしておきましょう。
dialog の accept()を書き換えれば、”OK”ボタンが押された際に処理を追加することができることがわかりまし
た。plugin builder で書きだされている”plugin_test_dialog.py”を書き換えて処理を加えましょう。
34/45
PluginTestDialog クラスは、先ほど変更した plugin_test_dialog_base.ui を継承しています。 PluginTestDialog
で accept()を定義して上書きしましょう。ここでは少し回りくどいやり方ですが、accept()の内容を空にしてしまいま
す。
次に、plugin_test.py の内容を書き換えます。dialog を作成した際に、dialog の button_box の accepted()に別な処理を connect してしまいます。connect されたメソッドには、レイヤ数を dialog の textEdit に書き出す
処理を記述してあります。
35/45
FORM_CLASS, _ = uic.loadUiType(os.path.join( os.path.dirname(__file__), 'plugin_test_dialog_base.ui'))
class PluginTestDialog(QtGui.QDialog, FORM_CLASS): def __init__(self, parent=None): """Constructor.""" super(PluginTestDialog, 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)
FORM_CLASS, _ = uic.loadUiType(os.path.join( os.path.dirname(__file__), 'plugin_test_dialog_base.ui'))
class PluginTestDialog(QtGui.QDialog, FORM_CLASS): def __init__(self, parent=None): """Constructor.""" super(PluginTestDialog, 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)
def accept(self): pass
36/45
class PluginTest: """QGIS Plugin Implementation."""
def __init__(self, iface):
– 省略 -
# Create the dialog (after translation) and keep reference self.dlg = PluginTestDialog() self.dlg.button_box.accepted.connect(self.set_text)
– 省略 - def set_text(self): self.dlg.textEdit.setText(str(self.iface.mapCanvas().layerCount()))
プラグインを実行して、ダイアログにレイヤ数が表示されるか確認してみましょう。
6 デバッグ環境 スクリプトが短いうちは、エラーの際に表示されるメッセージを見ながら修正を行なっていくことも可能です。た
だし複雑な処理になってくると、スクリプトを実行させながらのデバックが欠かせなくなります。Eclipse+PyDevでデバッグに必要な環境を構築することが出来ます。
環境の構築は時間がかかるためここでは行いませんが、参考資料だけあげておきます。バージョン等古くなっ
ていますので、適時読み替えてください。
• http://www.areanine.gr.jp/~banjo/QGIS/plugin/lesson3.html
• http://linfiniti.com/2011/12/remote-debugging-qgis-python-plugins-with-pydev/
• QGIS でアプリケーションを作成する/QGIS でプラグインを作成する
http://d.hatena.ne.jp/waigani/20101130
http://d.hatena.ne.jp/waigani/20101229
37/45
7 プロセッシング入門
7.1 プロセッシングとは?
プロセッシングは QGIS で使える様々な解析機能をまとめるためのフレームワークです。GRASS,SAGA な
どで提供される解析機能を、プロセッシングを通して統合してシームレスに使用することが出来ます。注意する
点としては、プロセッシング自体はフレームワークなので、各々の解析機能(SAGA など)は別にインストールさ
れている必要があります。
初期状態で「プロセッシングツールボックス」が表示されています。表示されていない場合は、メニューの「プロ
セッシング」から「ツールボックス」を選択することで表示させることができます。通常はこの「ツールボックス」から
プロセッシングの機能を使います。
7.2 Pythonコンソールからプロセッシング
プロセッシングは用意されている機能以外にも、Python で記述したスクリプトを追加登録することが出来ます。
まずは Python コンソールからプロセッシングを使用して、どのような記述を行うのか、その仕組みを学習してみ
ましょう。
ne_50m_admin_0_countries.shp のみ 1 レイヤが読み込まれており、ここから”name”属性 = “Japan”の図
形を select、select した図形を別ファイルとして書き込みという一連の流れを行なってみます。
Python コンソールを開いて下さい。最初に行うおこなうことはプロセッシングの import です。
>>>import processing
Python コンソールの”クラスのインポート”から入力することもできます。
38/45
使用出来る機能の一覧を表示してみましょう。
>>>processing.alglist()
を実行すると、機能の説明----->機能名というフォーマットで機能の一覧が表示されます。
processing.alglist()は文字列を引数として渡すことも出来ます。この場合、機能の説明に対して指定した文
字列でフィルターをかけることができます。”select”を含む機能を探しているとして、
>>>processing.alglist('select')
を実行してみて下さい。qgis:selectbyattribute という機能を見つけることが出来ます。
39/45
この機能の使用方法を確認します。
>>>processing.alghelp('qgis:selectbyattribute')
表示された使用方法から、引数が4つ必要なこと(最後の引数 OUTPUT は返り値の添字を表しているので指
定の必要はありません。)がわかります。
INPUT : 入力するベクトルレイヤ(QgsVectorLayer もしくはファイル名)
FIELD : 属性フィールド名
OPERATOR : 比較演算子
VALUE : 比較値
を引数で指定します。OPERATOR に指定できる比較演算子のリストも表示されます。比較演算子はこの中か
ら、対応する数字で指定することになります。
qgis:selectbyattribute を実行してみましょう。
>>>layer = iface.activeLayer()
>>>selectedResult = processing.runalg('qgis:selectbyattribute', layer, 'name', 0, 'Japan')
実行には processing.runalg()を使用します。最初の引数として機能名を、次の引数からは機能毎に必要とさ
れる引数を列挙します。返り値は、実行結果を反映したファイル名が入った辞書になります。
>>>selectedResult
{'OUTPUT': u'C:\work\ne_50m_admin_0_countries.shp',}
qgis:selectbyattribute の場合、新しいファイルは作らず入力として指定したファイルを操作する機能ですの
で、入力ファイル名がそのまま返ってきます。
次に、gdal の機能を利用してベクトルデータを、フォーマットを指定して保存してみましょ
う。”gdalogr:convertformat”の Help を確認します。
40/45
>>>processing.alghelp('gdalogr:convertformat')
入力するベクトルレイヤ(もしくファイル名)とフォーマットを指定することがわかります。ただしオプション、出力
ファイルは”None”としておいてください。出力ファイルはテンポラリファイルとして作成してくれます。実行して、
作成されたテンポラリファイルを読み込みます。
>>>saveResult = processing.runalg('gdalogr:convertformat', selectedResult['OUTPUT'], 1,None, None)
>>>processing.load(saveResult['OUTPUT_LAYER'])
このようにプロセッシングを使うことで、qgis 本体の機能、その他のライブラリ・アプリケーションで用意された機
能といった、別々に提供された解析機能を同一のインタフェースから使用することが出来るようになります。
7.3 関数を利用する
プロセッシングは解析機能を統一の手順で使えるようにしたフレームワークですが、その過程で用意された各
種便利クラスも使用することが出来ます。例えば、QGIS を OSGeo4W でインストールしたとして、
C:\OSGeo4W\apps\qgis\python\plugins\processing\tools\dataobjects.py
を覗いてみましょう。
レイヤへのアクセスクラスなどが用意されていて、QGIS Python API の使用方法としてとても参考になります。
読み込み済みのラスタレイヤ一覧を得る関数は、
41/45
のように用意されています。一度見てみることをおすすめします。
7.4 プロセッシングスクリプト
プロセッシングには決まったルールで入力・出力を定義してあげることで、自分で書いたスクリプトを追加するこ
とができます。また、ネットで公開されているスクリプトをダウンロードしてきて追加することもできます。
スクリプトの中身を見ることが出来ますので、見てみましょう。「スクリプト」「ツール」の「オンラインスクリプト集から
スクリプトを入手」を選択します。
42/45
def getRasterLayers(sorting=True): layers = QgsProject.instance().layerTreeRoot().findLayers() raster = []
for layer in layers: mapLayer = layer.layer() if mapLayer.type() == QgsMapLayer.RasterLayer: if mapLayer.providerType() == 'gdal': # only gdal file-based layers raster.append(mapLayer) if sorting: return sorted(raster, key=lambda layer: layer.name().lower()) else: return raster
“Hex grid from layer bounds”をダウンロードしてみましょう。
「スクリプト」「Polygons」に追加されますので、右クリックして「スクリプトを編集」を選択します。スクリプトの内容
が表示され、下記の内容となっています。
機能を Excute した際のダイアログと比較すると、冒頭の”##”の部分で入力/出力に関するフォームを指定し
ていることがわかります。このような簡単な指定でフォームを作成することが出来ますので、対話的な操作が必要
になる機能以外は、プロセッシングを利用して組み込む事が今後標準になると思われます。
43/45
##Polygons=group##input=vector##cellsize=number 1000.0##grid=output vector
input = processing.getObject(input)
extent = input.extent()extent = '%f,%f,%f,%f' %(input.extent().xMinimum()-cellsize/2, input.extent().xMaximum()+cellsize/2, input.extent().yMinimum()-cellsize/2, input.extent().yMaximum()+cellsize/2)
processing.runalg('qgis:creategrid', 3, extent, cellsize, cellsize, input.crs().authid(),grid)
8 参考資料 わからないクラス、関数が出てきたら、基本は QGIS API Documentation から調べます。
http://www.qgis.org/api/
PyQt も必要な知識になります。
http://pyqt.sourceforge.net/Docs/PyQt4/classes.html
公式なテキストとして cookbook があります。
http://www.qgis.org/pyqgis-cookbook/
プロセッシングに関する情報は、マニュアルを読むことが基本です。
https://docs.qgis.org/2.8/en/docs/user_manual/processing/console.html
下記の書籍もとても参考になります。
https://www.packtpub.com/application-development/qgis-python-programming-cookbook
日本語で得られる情報はまだまだ少ないです。
月の杜工房 http://mf-atelier.sakura.ne.jp/
waigani's dialy http://waigani.hatenablog.jp/
合同会社 緑IT事務所 http://midoriit.com/blog.html
真田工務店 http://blog.livedoor.jp/sanakazu/
だら$らいぶらりぃ~ http://www.areanine.gr.jp/~banjo/QGIS/plugin/index.html
45/45