QGISで最近傍探索のプラグインをつくった

この記事では前回記事に引き続き、QGISプラグインをつくっていこうと思います。
ginnannman.hateblo.jp前回の予告通り、ポイントからの最近傍点を計算して出力するプロセシングをつくります。

はじめに

今回はプロセシングプラグインを作成します。理由はGUIをQt Designerで作ることが面倒だからです。2つのレイヤーを入力し、それぞれのレイヤーの入力点のフィールドを取得することさえできれば問題ないはずですし、GUIで複雑なことを仕込む必要はありません。
ということでQGISを立ち上げて、Plugin Builderを開き、適当に設定していきます。今回はClass nameをNearestPointDistanceなどとして適宜埋めていきます。Class nameだけはCamel Caseにするのがお作法と思われます。

内容

Plugin Builderで作成したプラグインディレクトリを開き、

{任意の作成したプラグイン名}_algorithm.py

の編集を行います。詳細はGithubにあげたプラグインのフォルダの通りなのでぜひそちらをごらんください。


今回は初めてのプラグインということもあり非常に冗長かつ処理の重い(割に精度の保証があまりない)実装になっています。
キモは、QgsSpatialIndexのnearestNeighborというメソッドが行っている処理が実は近似最近傍検索で高速だが精度が低い方法を採用しており、そのために最近傍が漏れてしまうことがあるという問題をいかに回避するかにありました。
近似最近傍を採用しない限り、10000程度のオーダーでも計算量が爆発してしまうことは目に見えているので、正解といえば正解なのですが、10m単位で結果がずれることがあるのでどうにかしたいという問題意識があります。
そこで、今回は簡易的にnearestNeighborで10個の最近傍候補を取り出してそこから線形探索を行い、最近傍らしいものを取り出すことにしました。今までの経験から、10個も候補を出せばだいたいの場合で正しい答えにたどり着けることがわかっていたのでこの方法を採用しました(本当はこれを定式化するなりアルゴリズムを読み解いて実用的な精度であることを示すなりしなければならないのですが割愛します)。精度が気になる方は近似最近傍検索の個数を増やすように書き換えるか、そもそものメソッドを書き直すなどして新たにプラグインを作成してみてください。
注意点としては、元ネタのQGISのコアプロセシング、距離行列(distance matrix)とは異なり、入力レイヤーと出力レイヤーは異なるものである必要がある、複数個同じ距離の点があった場合に対応していないなどの甘い点があります。
このような場合も精度の高い処理をしたい場合はご自身でプラグインを作成されることをお勧めします。

ということで完成したプラグインがこちらです。ZIPでダウンロードして追加するのが一番簡単かと思われます。ただし、私は信頼できる人間かわかりませんし、私が仕込んでいなくても何かある場合もありますから、責任は負いかねることをご承知おきください。バグ報告などはGithubにお願いします。

github.com

ということで簡単なご報告でしたが、これからもぼちぼちプラグインをつくっていけたらと思います。