QGIS :QgsMapTool

今回はQgsMapToolの紹介です。
マップツールは地図の移動や地物の選択など地図にマウスで操作するときに使われています。

プラグインでも座標を指定してほしいときに使います。
前回紹介したrubberBandを書くときも使います。
測定ツールや地物選択などはMapToolとRubberBandの組み合わせですね。

APIドキュメントQgsMapTool

子クラスが以下のように存在します。軽く紹介していきます。
1,QgsMapToolEdit
レイヤのジオメトリの編集時に使うマップツール。編集モードで使うノードツールに使われています。
Pythonでは使用できない。

2,QgsMapToolEmitPoint
クリックしたPointを返すマップツール。座標がほしいだけなら素のままで使える。
3,QgsMapToolIdentify
地物の情報参照のマップツール。
4,QgsMapToolPan
地図移動のマップツール。
5,QgsMapToolTouch
タッチ系の操作に関するマップツール。
6,QgsMapToolZoom
ズーム系のマップツール。

基本的にはQGISにある標準のマップツールのクラスです。

今回はQgsMapToolでQgsRubberaBandを描くマップツールを作っていきます。

QgsMapToolEmitPointを使う場合はsignalに座標とクリックした時のButtonの種類を返してくれるので
関数の継承はしなくていいです。
カーソルの移動時に形を変形をしなくていいなら、QgsMapToolEmitPointの方が非常に簡単に作れます。
右クリックと左クリック判断するだけなので。

今回は継承して作っていきます。

QgsMapToolの関数と座標の入手を軽くオーバーライド

maptool.py
# -*- coding: utf-8 -*-
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QColor
from qgis.core import QGis
from qgis.gui import QgsMapTool, QgsRubberBand


class SelectTool(QgsMapTool):
    def __init__(self, iface, canvas):
        QgsMapTool.__init__(self, canvas)
        self.iface = iface
        self.canvas = canvas
        self.rubber = QgsRubberBand(canvas, QGis.Polygon)
        self.rubber.setColor(QColor(255, 0, 0, 100))
        # ラバーバンドの作成と色を決定
        self.last_point = None
        # ダブルクリックなどで点を二重に入力しないための変数

    def canvasPressEvent(self, event):
        # 地図を押した時に呼び出される
        pos = event.pos()
        # UI上の座標を取得
        point = self.get_canvas_point(pos)
        # 地図上の座標を取得
        # point = event.mapPoint()
        # APIドキュメントでは上記で地図上の座標を取得できるが
        # Pythonでは、返り値がQMouseEventのためできない
        # ドキュメントではQgsMapMouseEventが返り値

        button_type = event.button()
        # 押したボタンの種類
        point_count = self.rubber.numberOfVertices()
        # ポイントの数取得
        if button_type == Qt.LeftButton and self.last_point != point:
            # 左クリックで、最後に入力したポイントと同じで無ければ
            self.rubber.addPoint(point)
            # ラバーバンドにポイントを追加
            self.last_point = point
        if button_type == Qt.RightButton and point_count < 2:
            # 右クリックの場合
            self.last_point = None
            # 最終入力ポイントのリセット
            self.rubber.reset(QGis.Polygon)
            # ラバーバンドのリセット

    def canvasMoveEvent(self, event):
        # カーソルが地図上を移動すると呼び出される関数
        pos = event.pos()
        point = self.get_canvas_point(pos)
        point_count = self.rubber.numberOfVertices()
        if point_count == 0:
            # ポイントが一点もない場合落とす
            return
        self.rubber.movePoint(point)
        # 最後に追加したポイントをカーソルの位置に移動させる

    def get_canvas_point(self, position):
        # 地図上のポイントに変換する関数
        x = position.x()
        y = position.y()
        trans = self.canvas.getCoordinateTransform()
        return trans.toMapCoordinates(x, y)
# -*- coding: utf-8 -*-
from maptool import SelectTool
from PyQt4.QtGui import QIcon, QAction
import os


class plugin(object):
    def __init__(self, iface):
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.select_tool = SelectTool(self.iface, self.canvas)
        self.action  = None

    def initGui(self):
        icon_path = os.path.dirname(__file__) + u'/icon/qgis-icon.png'
        self.action = QAction(QIcon(icon_path),
                              u'選択', self.iface.mainWindow())
        self.action.triggered.connect(self.run)
        self.iface.addToolBarIcon(self.action)

    def unload(self):
        self.iface.removeToolBarIcon(self.action)

    def run(self):
        self.canvas.setMapTool(self.select_tool)
        # mapCanvasにマップツールをセットして使えるようにする
        # セットを解除する場合は
        # self.casnvas.unsetMapTool(self.select_tool)

本当はRubberBandの作成ではなく、レイヤーの選択ツールの予定でしたがポリゴンでの地物選択で詰まってしまい予定を変更しました。
プラグインとするなら、しなければいけないことをやってません。
プラグインとしてみると、残念な部分があるのでMapToolのクラスとして見てください。

プラグインとして足りない点:
Actionが押し込み式になってない
MapToolのunset時にRubberBandのリセット・押しこみ解除
押しこみ解除時にRubberBandのリセット・MapToolのunset
unload時にRubberBandのリセット・MapToolのunset

コメントを残す

メールアドレスが公開されることはありません。