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での地理プロットについて以下のような記載があります。
地理座標軸へのプロット
geoplot
、geoscatter
、geodensityplot
などの関数はターゲットとして geographic axes オブジェクトを取ります。関数geoaxes
を呼び出し、地理座標軸をプログラムによって作成します。たとえば、地理座標軸をパネルにプロットするには、次のコードを使用します。latSeattle = 47 + 37/60;
Mathworks App Designer でのグラフィックスの表示
lonSeattle = -(122 + 20/60);
gx = geoaxes(app.Panel);
geoplot(gx,latSeattle,lonSeattle)
アプリ上で地理プロットを作成する場合は,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さんのこちらのドキュメントに以下のような図がありました。この図を見るとFigure
とAxes
は親子関係にあります。上記2つ目のエラーで表示された「geoaxesをUIAxesの子にすることはできません。」というエラー文言から推測するに,geoaxes
関数は,指定したコンポーネントの下の階層に地理座標軸を作成するようです。なので,geoaxes
でapp.UIAxes
を指定した場合は,下図のAxes
の下の階層に地理座標軸を作成するように命じていることになるためエラーとなると思われます。app.UIFigure
を指定してうまくいくのは下図のFigure
を指定しているためだと思われます。パネルやタブグループはおそらく,下記Figure
と同列の扱いになるのだと思います。そのためうまくプロットができたのでしょう。
グラフィックス オブジェクトの階層 | Mathworks
まとめ
MATLABのアプリ上で地理プロットを作成する方法を紹介しました。ポイントは以下です。
・geoaxes
を使用して地理プロットのプロット対象を指定する
・指定できるコンポーネントは,タブグループ,パネル,UIFigure