MATLAB

【MATLAB】App Designerのアプリに地理プロットを作成する

App Designerで作成するアプリ内に地理プロットを作成するときに躓いたので備忘録として残しておきます。

MATLABでの地理プロット

MATLABでは,緯度・経度の位置情報を簡単に地図上にプロットすることができます。また,データをプロットするベースの地図も様々な種類があり,用途に合わせて適切なプロットを作成することができます。詳しくはMathworksさんのこちらのページにまとまっています。基本的には geoplot関数geoscatter関数に緯度・経度の情報を渡してあげれば簡単に地理プロットを作成することができます。

アプリ内にプロットを作成する

ただ,この地理プロットをアプリ内で作成する場合は少し注意が必要です。アプリ内で作成しようとして解決するのに結構時間を使ってしまったので参考になれば幸いです。

通常のプロットを作成する場合

まず,比較用にApp Dsignerで通常のプロットを作成する場合について説明します。例として,アプリを起動をしたらsin カーブがプロットされるというシンプルなアプリを作成することにします。通常のプロットの場合は,コンポーネントライブラリから「座標軸」を選びます。それをアプリ内に任意の大きさで配置します。

次に,アプリ起動時に実行されるstartupFcnを指定します。sinカーブを作成するためのデータの作成,plotするコードを書きます。plotの引数の1番目で,プロットを作成する対象に設計ビューで作成したapp.UIAxesを指定します。普段エディターでplotを作成する際には,私はあまりplotをする対象のAxesをあまり気にせず指定はしていないのですが,アプリでplotを作成する場合は,このように描画するAxesを指定する必要があります。

function startupFcn(app)
    x = 0:pi/100:2*pi;
    y = sin(x);
    plot(app.UIAxes,x,y)
end
MATLAB

これでアプリを実行すると以下のようにsinカーブのPlotが以下のように作成されます。

地理プロットを作成する場合

しかし,地理プロットを作成する場合に同様のアプローチでプロットを作成してもうまくいきませんでした。下記のコードは,以下の記事で作成したように,愛知県豊田市の任意の位置情報100点をランダムに作成したものをgeoscatter関数で地図上にマッピングしようとするコードです。

先ほどの通常のプロットと同様に,プロットする対象に「座標軸」で作成したapp.UIAxesを指定します。

function startupFcn(app)
    lat = 34.9 + (35.4-34.9).*rand(100,1);
    long = 137.0 + (137.7-137.0).*rand(100,1);
    geoscatter(app.UIAxes,lat,long)
end
MATLAB

しかし,これを実行すると以下のようなエラーが出ます。

MathworksのこちらのドキュメントにはApp designerでの地理プロットについて以下のような記載があります。

地理座標軸へのプロット

geoplotgeoscattergeodensityplot などの関数はターゲットとして geographic axes オブジェクトを取ります。関数 geoaxes を呼び出し、地理座標軸をプログラムによって作成します。たとえば、地理座標軸をパネルにプロットするには、次のコードを使用します。

latSeattle = 47 + 37/60;
lonSeattle = -(122 + 20/60);
gx = geoaxes(app.Panel);
geoplot(gx,latSeattle,lonSeattle)

Mathworks App Designer でのグラフィックスの表示

アプリ上で地理プロットを作成する場合は,geoaxesでプロット対象を指定する必要がありそうです。ここで,先ほどと同様に「座標軸」を使用してapp.UIAxesを指定します。

function startupFcn(app)
    lat = 34.9 + (35.4-34.9).*rand(100,1);
    long = 137.0 + (137.7-137.0).*rand(100,1);
    gx = geoaxes(app.UIAxes);
    geoscatter(gx,lat,long)
end
MATLAB

しかし,またエラーが出ます。どうやら地理プロットには「座標軸」を指定できないようです。

そこで,Mathworksの例にならって,「座標軸」ではなく「パネル」を指定してプロットしてみます。

データの部分は同じで,geoaxesの指定先をパネルにします。

function startupFcn(app)
    lat = 34.9 + (35.4-34.9).*rand(100,1);
    long = 137.0 + (137.7-137.0).*rand(100,1);
    gx = geoaxes(app.Panel);
    geoscatter(gx,lat,long)
end
MATLAB

するとうまくプロットできました。

ちなみに,タブグループ,UIFigureでもうまくプロットすることができました。

この理由についてですが,Mathworksさんのこちらのドキュメントに以下のような図がありました。この図を見るとFigureAxesは親子関係にあります。上記2つ目のエラーで表示された「geoaxesをUIAxesの子にすることはできません。」というエラー文言から推測するに,geoaxes関数は,指定したコンポーネントの下の階層に地理座標軸を作成するようです。なので,geoaxesapp.UIAxesを指定した場合は,下図のAxesの下の階層に地理座標軸を作成するように命じていることになるためエラーとなると思われます。app.UIFigureを指定してうまくいくのは下図のFigureを指定しているためだと思われます。パネルやタブグループはおそらく,下記Figureと同列の扱いになるのだと思います。そのためうまくプロットができたのでしょう。

グラフィックス オブジェクトの階層 | Mathworks

まとめ

MATLABのアプリ上で地理プロットを作成する方法を紹介しました。ポイントは以下です。

geoaxes を使用して地理プロットのプロット対象を指定する
・指定できるコンポーネントは,タブグループ,パネル,UIFigure

-MATLAB
-, ,