embeddedなブログ

組み込みシステムに関することや趣味に関することをダラダラと書いていきます(^^)

QGISプラグインをVisual Studio 2017でデバッグする(その2)

2019-04-07 15:43:08 | Windows Embedded Standard

今度はもう少し形として動くサンプルプラグインを作成してVisual Studioでデバッグしてみました。

サンプルプラグインとしては、QGIS上に表示されたシェイプファイルの画面上をクリックすると、クリックした場所に四角形のポリゴンを描画する簡単なプラグインです。

表示するデータ(シェイプファイル)の準備をします。国土地理院の基盤地図情報サイトからデータをダウンロードします。基盤地図情報サイトの[基盤地図情報のダウンロード]をクリックします。

地図上でダウンロードしたい区域をクリックして選択して、[ダウンロードファイル選択へ]をクリックします。

ダウンロードするファイルの右横の[ダウンロード]をクリックするか、左側にチェックを入れて[まとめてダウンロード]をクリックします。上記ではFG-GML-523502-ALL-20181001.zipをダウンロードしました。ダウンロードしたZIPファイルを適当なフォルダに展開しておきます。

次にQGISで読み込める形式にデータ変換が必要となります。基盤地図情報サイトのダウンロードサービスのページから、表示ソフトウェアの項目にある「基盤地図情報ビューア」をダウンロードします。FGDV.zipというファイルがダウンロードされるので、適当なフォルダに展開します。展開した中のFGDV.exeを実行すると基盤地図情報ビューアが起動します。基盤地図情報ビューアのメニューから[ファイル]-[新規プロジェクト作成]で新規プロジェクト作成画面を表示します。

新規プロジェクト作成画面で[追加]をクリックして先ほど基盤地図情報サイトからダウンロードして展開したファイルの中からFG-GML-523502-RdEdg-20181001-0001.xmlを選択、また、ここでは、保存先フォルダにC:\QGIS\data\FGDVを指定しました。今回の例では、道路のシェイプファイルを表示したいので FG-GML-523502-RdEdg-20181001-0001.xml を選択しました。道路以外に家屋の形状などのデータがあるので、適宜必要なファイルを選択してください。

[OK]をクリックすると画面にファイルの内容が表示されます。

それでは次にこの内容をQGISで読み込めるようにシェイプファイルにデータ変換します。基盤地図情報ビューアのメニューから[エクスポート]-[エクスポート]を選択して、エクスポート画面を表示します。

 上図のように変換種別で「シェイプファイル」、変換する領域で「全データ領域を出力」を選択し、出力先フォルダを指定して[OK]をクリックします。出力先フォルダに20181001-道路縁.shpのようなファイルが4種類ほど出力されていることを確認します。

それでは、ここからはQGISでの作業となります。まず、この例ではプラグインを "C:\QGIS\plugin"フォルダに作成するので、事前に環境変数にQGIS_PLUGINPATH に "C:\QGIS\plugin"に設定しておきます。これでQGISがこのフォルダ以下にあるフォルダの内容をプラグインとして自動的に登録します。

QGISを起動して、Plugin Builderを起動します。ここでは、主な画面だけを紹介しますので、詳細な手順はここを参考にしてください。プラグイン名は"Draw Polygon"、モジュール名は "draw_polygon"としました。

Templateは"Tool button with dock widget"を、メニュー名は"Draw polygon"としました。

モジュールを配置する場所は C:\QGIS\plugin です。

モジュール生成後、下記でリソースを変換します。詳細な手順はここを参考にしてください。

pyrcc5 -o resources.py resources.qrc
pyuic5 -o draw_polygon_dockwidget_base.py draw_polygon_dockwidget_base.ui

 ソースコードを修正します。draw_polygon.py に下記赤文字の部分を追記します。

# -*- coding: utf-8 -*-
"""
/***************************************************************************
 DrawPolygon
                                 A QGIS plugin
 Draw a polygon where you click the mouse.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2019-03-09
        git sha              : $Format:%H$
        copyright            : (C) 2019 by https://blog.goo.ne.jp/yoossh
        email                : https://blog.goo.ne.jp/yoossh
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""
from PyQt5.QtCore import QSettings, QTranslator, qVersion, QCoreApplication, Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QAction
# Initialize Qt resources from file resources.py
from .resources import *
from qgis.gui import QgsMapTool
from qgis.gui import QgsRubberBand
from qgis.core import QgsPoint
from qgis.core import QgsGeometry

# Import the code for the DockWidget
from .draw_polygon_dockwidget import DrawPolygonDockWidget
import os.path

class PolygonTool(QgsMapTool):  
    def __init__(self, canvas):
        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas   

    def canvasPressEvent(self, event):
        pass

    def canvasMoveEvent(self, event):
        pass

    def canvasReleaseEvent(self, event):
        # Get clicked coordinate on the canvas
        x = event.pos().x()
        y = event.pos().y()
        # Conver to the world coordinate of clicked point
        point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)
        # Create polygon
        polyline = QgsRubberBand(self.canvas, False)
        x = point[0]
        y = point[1]
        points =[QgsPoint(x-10,y-10), QgsPoint(x+10,y-10), QgsPoint(x+10,y+10),QgsPoint(x-10,y+10),QgsPoint(x-10,y-10)]
        # Draw polygon
        polyline.setToGeometry(QgsGeometry.fromPolyline(points), None)
        polyline.setColor(QColor(0, 0, 255))
        polyline.setWidth(3)

    def activate(self):
        pass

    def deactivate(self):
        pass

    def isZoomTool(self):
        return False

    def isTransient(self):
        return False

    def isEditTool(self):
        return True

class DrawPolygon:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface

        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'DrawPolygon_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&Draw Polygon')
        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'DrawPolygon')
        self.toolbar.setObjectName(u'DrawPolygon')

        #print "** INITIALIZING DrawPolygon"

        self.pluginIsActive = False
        self.dockwidget = None

...中略...

    #--------------------------------------------------------------------------

    def run(self):
        """Run method that loads and starts the plugin"""

        if not self.pluginIsActive:
            self.pluginIsActive = True

            #print "** STARTING DrawPolygon"

            # dockwidget may not exist if:
            #    first run of plugin
            #    removed on close (see self.onClosePlugin method)
            if self.dockwidget == None:
                # Create the dockwidget (after translation) and keep reference
                self.dockwidget = DrawPolygonDockWidget()

            # connect to provide cleanup on closing of dockwidget
            self.dockwidget.closingPlugin.connect(self.onClosePlugin)

            # show the dockwidget
            # TODO: fix to allow choice of dock location
            self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockwidget)
            self.dockwidget.show()
        tool = PolygonTool(self.iface.mapCanvas())
        self.iface.mapCanvas().setMapTool(tool)

 QGISを起動します。まだ上記で作成したプラグインはロードしない(プラグイン管理画面でチェックを入れない)でください。 上記でデータ変換した Shape  20181001-道路縁.shp を読み込んで表示します。

QGISはそのままとしておき、ここからVisual Studio側での作業です。新しいPythonプロジェクトを作成します。既存コードとして、QGISのPlugin Builderで生成したコードを参照させます。

[次へ]をクリックします。

プラグインファイルが参照されていることを確認して[次へ]をクリックします。

プロジェクトの保存先を指定して[完了]します。Visual Studioメニューのメニュー[デバッグ]-[プロセスにアタッチ]を実行してプロセスにアタッチ画面を開きます。

使用可能なプロセス一覧から "qgis-bin.exe"を選択して[アタッチ]をクリックします。

再びQGISに戻って、メニュー[プラグイン]-[プラグインの管理とインストール]を実行します。プラグイン一覧の「Draw Polygon」の右側のチェックボックスをチェックします。

そのままQGISメニューで[プラグイン]-[Draw Polygon]でDraw Polygonプラグインを実行します。

Visual Studioでの作業になります。下図のように PointToolクラスのcanvasReleaseEvent関数内にブレークポイントを設定します。

ブレークポイントを設定したら、今度はQGIS画面上に表示されたシェイプファイル(ここでは道路図)の適当な場所をマウスの左ボタンでクリックします。すると、下図のようにブレークポイントで止まるはずです。

上図では、point 変数をウォッチに追加して、変数の中身、つまりマウスでクリックした位置の実座標を確認しています。F5キーを押下してプラグインの実行を継続させると、下図のようにクリックした位置に四角形のポリゴンが表示されています。

以上で終了です。


最新の画像もっと見る