「メインページ/QGIS/coding-compilation guide/creating cpp applications/」の版間の差分

提供: OSGeo.JP Wiki
移動: 案内検索
(ページの作成: <source lang="latex"> \section{Creating C++ Applications} Not everyone wants a full blown GIS desktop application. Sometimes you want to just have a widget inside your applicati…)
 
 
(同じ利用者による、間の6版が非表示)
行1: 行1:
 
<source lang="latex">
 
<source lang="latex">
 
\section{Creating C++ Applications}
 
\section{Creating C++ Applications}
 +
\section{C++アプリケーションの作成}
  
Not everyone wants a full blown GIS desktop application. Sometimes you want
+
全ての人が完璧なデスクトップGISアプリケーションを求めているわけではありません。
to just have a widget inside your application that displays a map while the
+
時には、別の目的で作成されたアプリケーションの中に地図を表示するウィジェットを埋め込みたいだけ、ということもあるでしょう。
main goal of the application lies elsewhere. Perhaps a database frontend with
+
おそらく、地図表示を備えたデータベースフロントエンドなどでしょうか。
a map display? This Section provides two simple code examples by Tim Sutton,
+
このセクションでは、Francis Bolduc氏の以前の成果に基づいて作成された、Tim Sutton氏による2つのシンプルなコードの例を取り上げます。
based on earlier work by Francis Bolduc. They are available in the qgis
+
これらはその他の興味深いチュートリアルとともにQGIS subversionリポジトリにあります。
subversion repository together with more interesting tutorials. Check out
+
\filename{https://svn.osgeo.org/qgis/trunk/code\_examples/}からリポジトリ全体を調べてみてください。
the whole repository from: \filename{https://svn.osgeo.org/qgis/trunk/code\_examples/}
+
  
\subsection{Creating a simple mapping widget}\label{subsec:simple_widget}
+
\subsection{シンプルなマッピングウィジェットの作成}\label{subsec:simple_widget}
  
With this tutorial we will create a simple mapping widget. It won't do
+
このチュートリアルではシンプルなマッピングウィジェットを作成します。
anything much - just load a shape file and display it in a random colour.
+
ウィジェットには特段の機能はありません。単にshapeファイルを読み込んで、ランダムに色を割り振って表示するだけのものです。
This should give you an idea of the potential for using QGIS as an embedded
+
しかしながら、QGISをマッピングコンポーネントを埋め込むために利用する、ということを理解するのには役に立つでしょう。
mapping component.
+
  
We start by adding the neccessary includes for our app:
+
まずはアプリケーションに必要なインクルードファイルを追加しましょう:
  
 
\begin{verbatim}
 
\begin{verbatim}
行37: 行36:
 
\end{verbatim}
 
\end{verbatim}
  
We use QgsApplication instead of Qt's QApplication, to take advantage of
+
まず、QtのQApplicationの代わりにQgsApplicatinoを使います。これはライブラリパスの位置を検索するなどの機能を持つスタティックメソッドを利用するためです。
various static methods that can be used to locate library paths and so on.
+
  
The provider registry is a singleton that keeps track of vector data provider
+
provider registryとはシングルトン(訳注:アプリケーション内で唯一のインスタンスを生成するクラス)で、
plugins. It does all the work for you of loading the plugins and so on. The
+
vecto data providerプラグインを記録します。このクラスはプラグインをロードするなどの作業を全て行ってくれます。
single symbol renderer is the most basic symbology class. It renders points,
+
single symbol rendererは最も基本的なsymbologyクラスで、デフォルトではランダムに選択された色(指定することも可能)を用いて点、線、
lines or polygons in a single colour which is chosen at random by default
+
ポリゴンを描画します。
(though you can set it yourself). Every vector layer must have a symbology
+
全てのベクタレイヤーはこのクラスに関連付けられたsymbologyを持っていなければなりません。
associated with it.
+
  
The map layer registry keeps track of all the layers you are using. The
+
map layer registryは利用する全てのレイヤーを記録します。
vector layer class inherits from maplayer and extends it to include
+
vector layerクラスはmaplayerクラスを継承しており、ベクタレイヤー固有の機能拡張がなされています。
specialist functionality for vector data.
+
  
Finally, the mapcanvas is our main map area. Its the drawable
+
最後に、mapcanvasはメインのマップ領域で、マップデータを表示する描画可能ウィジェットです。
widget that our map will be dispalyed on.
+
  
Now we can move on to initialising our application....
+
それではアプリケーションの初期化に進みましょう。。。
  
 
\begin{verbatim}
 
\begin{verbatim}
行69: 行64:
 
\end{verbatim}
 
\end{verbatim}
  
We now have a qgsapplication and we have defined several variables. Since this
+
まず、qgsapplicationオブジェクトを作成し、いくつかの変数を定義しています。
tutorial was initially tested on Ubuntu Linux 8.10, we have specified the
+
このチュートリアルがもともとUbuntu Linux 8.10でテストしたものなので、
location of the vector provider plugins as being inside our development install
+
ベクタプロバイダプラグインの場所に開発用インストールディレクトリが指定されています。
directory. It would probaby make more sense in general to keep the QGIS libs in one of the
+
一般的には、読者のシステムにおける標準的なライブラリパス(/usr/lib等)にQGISのライブラリ群を保存してあるほうが理にかなっているものと思われますが、
standard library search paths on your system (e.g. /usr/lib) but this way
+
ここではとりあえずこうしておきます。
will do for now.
+
  
The next two variables defined here point to the shapefile that is going to
+
次の2つの変数定義(訳注:myLayerPathとmyLayerBaseName)では、これから読み込むShapeファイルを指定しています
be used (though you will likely want to substitute your own data here).
+
(ただし、独自のデータをここで代入する必要があるかもしれません)。
  
The provider name is important - it tells qgis which data provider to use to
+
プロバイダ名は重要で、これはQGISにどのデータプロバイダを利用するかを指定します。
load the file. Typically you will use 'ogr' or 'postgres'.
+
通常’ogr’もしくは’postgres’を指定します。
  
Now we can go on to actually create our layer object.
+
それでは実際にレイヤーオブジェクトを作成してみましょう。
  
 
\begin{verbatim}
 
\begin{verbatim}
行89: 行83:
 
\end{verbatim}
 
\end{verbatim}
  
First we get the provider registry initialised. Its a singleton class so we
+
まずprovider registryを初期化しています。
use the static instance call and pass it the provider lib search path. As it
+
シングルトンクラスなので静的なインスタンスの呼び出しを使用しており、引数にプロバイダライブラリ群へのパスを渡しています。
initialises it will scan this path for provider libs.
+
初期化されると、このパスからプロバイダライブラリ群をスキャンします。
  
Now we go on to create a layer...
+
続いてレイヤーを作成します。
  
 
\begin{verbatim}
 
\begin{verbatim}
行119: 行113:
 
\end{verbatim}
 
\end{verbatim}
  
The code is fairly self explanatory here. We create a layer using the
+
このコードは極めて自明的です。以前に定義した変数を用いてレイヤーを作成したら、レイヤーにレンダラを割り付けます。
variables we defined earlier. Then we assign the layer a renderer.
+
レンダラを作成する場合はジオメトリの種別を定義する必要がありますが、これはベクタレイヤーにジオメトリタイプを問い合わせることで行います。
When we create a renderer, we need to specify the geometry type, which
+
次に、レイヤーをレイヤーセットと(これはどのレイヤーを描画するかや、レイヤーの順番をQgsMapCanvasが追跡するのに使用されます)
we do by asking the vector layer for its geometry type. Next we add
+
マップレイヤーレジストリに追加します。
the layer to a layerset (which is used by the QgsMapCanvas to keep
+
最後に、レイヤーが表示されていることを確認します。
track of which layers to render and in what order) and to the maplayer
+
registry. Finally we make sure the layer will be visible.
+
  
Now we create a map canvas on to which we can draw the layer.
+
それでは、レイヤーを描画するマップキャンバスを作成しましょう。
  
 
\begin{verbatim}
 
\begin{verbatim}
行143: 行135:
 
\end{verbatim}
 
\end{verbatim}
  
Once again there is nothing particularly tricky here. We create the canvas
+
ここでも特に手の込んだことはありません。
and then we set its extents to those of our layer. Next we tweak the canvas a bit
+
まず、キャンバスを作成し、キャンバスの範囲にレイヤーの範囲を割り当てています。
to draw antialiased vectors. Next we set the background colour, unfreeze the
+
次に、ベクタレイヤーの描画にアンチエイリアスを使用するように設定します。
canvas, make it visible and then refresh it.
+
さらに、背景色の設定、キャンバスの凍結の解除、キャンバスを表示するようにした後、キャンバスを更新します。
  
 
\begin{verbatim}
 
\begin{verbatim}
行155: 行147:
 
\end{verbatim}
 
\end{verbatim}
  
In the last step we simply start the Qt event loop and we are done. You
+
最後のステップは、単にQtのイベントループを開始して終了です。
can check out, compile and run this example using cmake like this:
+
確認後、以下のようにcmakeを使ってこのコードをコンパイルし、実行することができます:
  
 
\begin{verbatim}
 
\begin{verbatim}
行173: 行165:
 
\end{verbatim}
 
\end{verbatim}
  
When we compile and run it here is what the running app looks like:
+
コンパイルして実行すると以下のように表示されます。
  
 
\begin{figure}[ht]
 
\begin{figure}[ht]

2009年11月10日 (火) 03:34時点における最新版

\section{Creating C++ Applications}
\section{C++アプリケーションの作成}
 
全ての人が完璧なデスクトップGISアプリケーションを求めているわけではありません。
時には、別の目的で作成されたアプリケーションの中に地図を表示するウィジェットを埋め込みたいだけ、ということもあるでしょう。
おそらく、地図表示を備えたデータベースフロントエンドなどでしょうか。
このセクションでは、Francis Bolduc氏の以前の成果に基づいて作成された、Tim Sutton氏による2つのシンプルなコードの例を取り上げます。
これらはその他の興味深いチュートリアルとともにQGIS subversionリポジトリにあります。
\filename{https://svn.osgeo.org/qgis/trunk/code\_examples/}からリポジトリ全体を調べてみてください。
 
\subsection{シンプルなマッピングウィジェットの作成}\label{subsec:simple_widget}
 
このチュートリアルではシンプルなマッピングウィジェットを作成します。
ウィジェットには特段の機能はありません。単にshapeファイルを読み込んで、ランダムに色を割り振って表示するだけのものです。
しかしながら、QGISをマッピングコンポーネントを埋め込むために利用する、ということを理解するのには役に立つでしょう。
 
まずはアプリケーションに必要なインクルードファイルを追加しましょう:
 
\begin{verbatim}
//
// QGIS Includes
//
#include <qgsapplication.h>
#include <qgsproviderregistry.h>
#include <qgssinglesymbolrenderer.h>
#include <qgsmaplayerregistry.h>
#include <qgsvectorlayer.h>
#include <qgsmapcanvas.h>
//
// Qt Includes
//
#include <QString>
#include <QApplication>
#include <QWidget>
\end{verbatim}
 
まず、QtのQApplicationの代わりにQgsApplicatinoを使います。これはライブラリパスの位置を検索するなどの機能を持つスタティックメソッドを利用するためです。
 
provider registryとはシングルトン(訳注:アプリケーション内で唯一のインスタンスを生成するクラス)で、
vecto data providerプラグインを記録します。このクラスはプラグインをロードするなどの作業を全て行ってくれます。
single symbol rendererは最も基本的なsymbologyクラスで、デフォルトではランダムに選択された色(指定することも可能)を用いて点、線、
ポリゴンを描画します。
全てのベクタレイヤーはこのクラスに関連付けられたsymbologyを持っていなければなりません。
 
map layer registryは利用する全てのレイヤーを記録します。
vector layerクラスはmaplayerクラスを継承しており、ベクタレイヤー固有の機能拡張がなされています。
 
最後に、mapcanvasはメインのマップ領域で、マップデータを表示する描画可能ウィジェットです。
 
それではアプリケーションの初期化に進みましょう。。。
 
\begin{verbatim}
int main(int argc, char ** argv)
{
  // Start the Application
  QgsApplication app(argc, argv, true);
 
  QString myPluginsDir        = "/home/timlinux/apps/lib/qgis";
  QString myLayerPath         = "/home/timlinux/gisdata/brazil/BR_Cidades/";
  QString myLayerBaseName     = "Brasil_Cap";
  QString myProviderName      = "ogr";
 
\end{verbatim}
 
まず、qgsapplicationオブジェクトを作成し、いくつかの変数を定義しています。
このチュートリアルがもともとUbuntu Linux 8.10でテストしたものなので、
ベクタプロバイダプラグインの場所に開発用インストールディレクトリが指定されています。
一般的には、読者のシステムにおける標準的なライブラリパス(/usr/lib等)にQGISのライブラリ群を保存してあるほうが理にかなっているものと思われますが、
ここではとりあえずこうしておきます。
 
次の2つの変数定義(訳注:myLayerPathとmyLayerBaseName)では、これから読み込むShapeファイルを指定しています
(ただし、独自のデータをここで代入する必要があるかもしれません)。
 
プロバイダ名は重要で、これはQGISにどのデータプロバイダを利用するかを指定します。
通常’ogr’もしくは’postgres’を指定します。
 
それでは実際にレイヤーオブジェクトを作成してみましょう。
 
\begin{verbatim}
  // Instantiate Provider Registry
  QgsProviderRegistry::instance(myPluginsDir);
\end{verbatim}
 
まずprovider registryを初期化しています。
シングルトンクラスなので静的なインスタンスの呼び出しを使用しており、引数にプロバイダライブラリ群へのパスを渡しています。
初期化されると、このパスからプロバイダライブラリ群をスキャンします。
 
続いてレイヤーを作成します。
 
\begin{verbatim}
  QgsVectorLayer * mypLayer =
      new QgsVectorLayer(myLayerPath, myLayerBaseName, myProviderName);
  QgsSingleSymbolRenderer *mypRenderer = new
QgsSingleSymbolRenderer(mypLayer->geometryType());
  QList <QgsMapCanvasLayer> myLayerSet;
 
  mypLayer->setRenderer(mypRenderer);
  if (mypLayer->isValid())
  {
    qDebug("Layer is valid");
  }
  else
  {
    qDebug("Layer is NOT valid");
  }
 
  // Add the Vector Layer to the Layer Registry
  QgsMapLayerRegistry::instance()->addMapLayer(mypLayer, TRUE);
  // Add the Layer to the Layer Set
  myLayerSet.append(QgsMapCanvasLayer(mypLayer, TRUE));
 
\end{verbatim}
 
このコードは極めて自明的です。以前に定義した変数を用いてレイヤーを作成したら、レイヤーにレンダラを割り付けます。
レンダラを作成する場合はジオメトリの種別を定義する必要がありますが、これはベクタレイヤーにジオメトリタイプを問い合わせることで行います。
次に、レイヤーをレイヤーセットと(これはどのレイヤーを描画するかや、レイヤーの順番をQgsMapCanvasが追跡するのに使用されます)
マップレイヤーレジストリに追加します。
最後に、レイヤーが表示されていることを確認します。
 
それでは、レイヤーを描画するマップキャンバスを作成しましょう。
 
\begin{verbatim}
  // Create the Map Canvas
  QgsMapCanvas * mypMapCanvas = new QgsMapCanvas(0, 0);
  mypMapCanvas->setExtent(mypLayer->extent());
  mypMapCanvas->enableAntiAliasing(true);
  mypMapCanvas->setCanvasColor(QColor(255, 255, 255));
  mypMapCanvas->freeze(false);
  // Set the Map Canvas Layer Set
  mypMapCanvas->setLayerSet(myLayerSet);
  mypMapCanvas->setVisible(true);
  mypMapCanvas->refresh();
 
\end{verbatim}
 
ここでも特に手の込んだことはありません。
まず、キャンバスを作成し、キャンバスの範囲にレイヤーの範囲を割り当てています。
次に、ベクタレイヤーの描画にアンチエイリアスを使用するように設定します。
さらに、背景色の設定、キャンバスの凍結の解除、キャンバスを表示するようにした後、キャンバスを更新します。
 
\begin{verbatim}
  // Start the Application Event Loop
  return app.exec();
}
 
\end{verbatim}
 
最後のステップは、単にQtのイベントループを開始して終了です。
確認後、以下のようにcmakeを使ってこのコードをコンパイルし、実行することができます:
 
\begin{verbatim}
svn co
https://svn.osgeo.org/qgis/trunk/code_examples/1_hello_world_qgis_style
cd 1_hello_world_qgis_style
mkdir build
#optionally specify where your QGIS is installed (should work on all
platforms)
#if your QGIS is installed to /usr or /usr/local you can leave this next step
out
export LIB_DIR=/home/timlinux/apps
cmake ..
make
./timtut1
\end{verbatim}
 
コンパイルして実行すると以下のように表示されます。
 
\begin{figure}[ht]
   \begin{center}
   \caption{Simple C++ Application \osxcaption}\label{fig:cpp1_application}\smallskip
   \includegraphics[clip=true]{cpp1_application}
\end{center}
\end{figure}
 
\subsection{Working with QgsMapCanvas}
 
In the previous Section (Section~\ref{subsec:simple_widget}) we showed you how to use 
the QgsMapCanvas API to create a simple application that loads a shapefile and
displays the points in it. But what good is a map that you can't interact
with? 
 
In this second tutorial we will extend the previous tutorial by making it a
QMainWindow application with a menu, toolbar and canvas area. We show you how
to use QgsMapTool - the base class for all tools that are used to interact with
the map canvas. The project will provide 4 toolbar icons for
 
\begin{itemize}
 \item loading a map layer (layer name is hard coded in the application
 \item zooming in
 \item zooming out
 \item panning
\end{itemize}
 
In the working directory for the tutorial code you will find a number of files
including c++ sources, icons and a simple data file under data. There is also
the .ui file for the main window.
 
\textbf{Note:} You will need to edit the .pro file in the above svn directory to
match your system.
 
Since much of the code is the same as the previous tutorial, we will focus on
the MapTool specifics - the rest of the implementation details can be
investigated by checking out the project form SVN. A QgsMapTool is a class that
interacts with the MapCanvas using the mouse pointer. QGIS has a number of
QgsMapTools implemented, and you can subclass QgsMapTool to create your own. In
mainwindow.cpp you will see we have included the headers for the QgsMapTools near the
start of the file:
 
\begin{verbatim}
     //
     // QGIS Map tools
     //
     #include "qgsmaptoolpan.h"
     #include "qgsmaptoolzoom.h"
     //
     // These are the other headers for available map tools 
     // (not used in this example)
     //
     //#include "qgsmaptoolcapture.h"
     //#include "qgsmaptoolidentify.h"
     //#include "qgsmaptoolselect.h"
     //#include "qgsmaptoolvertexedit.h"
     //#include "qgsmeasure.h"
\end{verbatim}
 
As you can see, I am only using two types of MapTool subclasses for this
tutorial, but there are more available in the QGIS library. Hooking up our
MapTools to the canvas is very easy using the normal Qt4 signal/slot mechanism:
 
\begin{verbatim}
     //create the action behaviours
     connect(mActionPan, SIGNAL(triggered()), this, SLOT(panMode()));
     connect(mActionZoomIn, SIGNAL(triggered()), this, SLOT(zoomInMode()));
     connect(mActionZoomOut, SIGNAL(triggered()), this, SLOT(zoomOutMode()));
     connect(mActionAddLayer, SIGNAL(triggered()), this, SLOT(addLayer()));
\end{verbatim}
 
Next we make a small toolbar to hold our toolbuttons. Note that the mpAction*
actions were created in designer.
 
\begin{verbatim}
     //create a little toolbar
     mpMapToolBar = addToolBar(tr("File"));
     mpMapToolBar->addAction(mpActionAddLayer);
     mpMapToolBar->addAction(mpActionZoomIn);
     mpMapToolBar->addAction(mpActionZoomOut);
     mpMapToolBar->addAction(mpActionPan);
\end{verbatim}
 
Now we create our three map tools:
 
\begin{verbatim}
     //create the maptools
     mpPanTool = new QgsMapToolPan(mpMapCanvas);
     mpPanTool->setAction(mpActionPan);
     mpZoomInTool = new QgsMapToolZoom(mpMapCanvas, FALSE); // false = in
     mpZoomInTool->setAction(mpActionZoomIn);
     mpZoomOutTool = new QgsMapToolZoom(mpMapCanvas, TRUE ); //true = out
     mpZoomOutTool->setAction(mpActionZoomOut);
\end{verbatim}
 
Again nothing here is very complicated - we are creating tool instances, each
of which is associated with the same mapcanvas, and a different QAction. When
the user selects one of the toolbar icons, the active MapTool for the canvas is
set. For example when the pan icon is clicked, we do this:
 
\begin{verbatim}
    void MainWindow::panMode()
    {
       mpMapCanvas->setMapTool(mpPanTool); 
    }
\end{verbatim}
 
\begin{figure}[ht]
   \begin{center}
   \caption{QMainWindow application with a menu, toolbar and canvas area
\osxcaption}\label{fig:cpp2_application}\smallskip
   \includegraphics[clip=true, width=12cm]{cpp2_application}
\end{center}
\end{figure}
 
\minisec{Conclusion}
 
As you can see extending our previous example into something more functional
using MapTools is really easy and only requires a few lines of code for each
MapTool you want to provide.
 
You can check out and build this tutorial using SVN and CMake using the following steps:
 
\begin{verbatim}
svn co https://svn.osgeo.org/qgis/trunk/code_examples/2_basic_main_window
cd 2_basic_main_window
mkdir build
#optionally specify where your QGIS is installed (should work on all platforms)
#if your QGIS is installed to /usr or /usr/local you can leave this next step out
export LIB_DIR=/home/timlinux/apps
cmake ..
make
./timtut2
\end{verbatim}