%% R2021a 一押し MATLAB 新機能
% こんにちは。道家です。来月はいよいよ MATLAB EXPO ですね！それについてはまた後日書きますね。
% R2021aがリリースされて既に2ヶ月が経ちましたが、新機能満載であるリリースの中から私のお気に入りMATLAB新機能について紹介します。Simulinkの新機能については新帯さんが書いた【Simulinkユーザー向け】R2021aの便利な新機能をご覧ください。
%
% Run in your browser で試してみよう！
% このブログのコードを実際にブラウザー上で実行することが出来ます。
% この記事の終りに「Run in your browser」というボタンがありますが、これをクリックするとこの記事がライブ スクリプトとしてブラウザー上のMATLABで開きます。実際に実行してみて体験してみてください。※スマホのブラウザーには対応していません。パソコン上のChromeでお試しください。
%
%
% 目次
% Name=Value 構文
% アニメーション再生
% ライブ エディターのフォントをプログラムで変更
% uilabel でHTMLマークアップ
% "プロットの作成" ライブ エディター タスク
% tick label の自動回転
% Class Diagram Viewer
% おわりに
% 補助関数
%
%% Name=Value 構文
% やはり、最初に取り上げたいのは、プロパティーを定義する新しい構文 Name=Value です。新しい関数は毎リリースたくさんありますが、新しい構文というのは珍しいです。
% 他の言語で目にしたことのある構文かもしれませんが、MATLABでは新鮮ですね。特に設定するプロパティーが多い場合、可読性が上がります。もちろん、今までの "Name", Value 構文はそのまま使えます。参考までに、従来の構文はコメントとして残しています。

figure
plot((1:10)+randn(1,10), ...
  Marker = "o", ...                 % "Marker", "o", ...
  MarkerSize = 10, ...              % "MarkerSize", 10, ...
  MarkerFaceColor = "red", ...      % "MarkerFaceColor", "red", ...
  MarkerEdgeColor = "black", ...    % "MarkerEdgeColor", "black", ...
  LineStyle = "-.", ...             % "LineStyle", "-.", ...
  LineWidth = 2)                    % "LineWidth, 2)

%
%
%% アニメーション再生
% 次は、ライブ エディター内のお気に入り機能の一つです。
% ライブ エディターの中で for ループなどを使ったアニメーションを表示するのは前からできましたが、R2021aではそのアニメーションを再生することができる様になりました。つまり、アニメーションのコードを再実行する必要がなくなったのです。
% ここでは跳ねるボールをシミュレーションしてみました。ご覧の通り、コードを実行したあと、再生ボタンが表示されます。再生速度も調整可能です。"Run in your browser" で是非試してみてください。
%
%
%

XLimits = [0 3];  % 壁の位置
init_cond = [0 2 0 10];  % [x0 vx0 y0 vy0]
opt = odeset(Events = @(t,y) hitEvent(t,y,XLimits));
T = 0; Y = 0; X = 0;
for id = 1:20
  [t,y,~,~,ie] = ode45(@projectile,0:0.05:5,init_cond,opt);
  [T,X,Y] = appendData(T,X,Y,t,y);
  init_cond = calcNewInit(y,init_cond,ie);
end

figure
h = plot(X(1),Y(1),'o');
h2 = animatedline(X(1),Y(1),MaximumNumPoints = 20);
axis equal
axis([min(X) max(X) min(Y) max(Y)])
box on
for id = 3:2:length(X)
  h.XData = X(id);
  h.YData = Y(id);
  addpoints(h2,X(id-1:id),Y(id-1:id));
  drawnow
end

%
%
%% ライブ エディターのフォントをプログラムで変更
% 少しマニアックな機能ですが、ライブ エディターで使われているフォントをプログラムで変更できるようになりました。
% 実は2018年ころからプログラムでMATLABのフォント（codefontなど）を変更することが可能になりました。今回はライブ エディターのフォントもいじれるようになったという事です。
% 例えば、見出し１のフォント カラーとサイズを変えるには

s = settings;
s.matlab.fonts.editor.heading1.Color.PersonalValue = [0 0 255 1];
s.matlab.fonts.editor.heading1.Size.PersonalValue = 25;

% 元に戻すには

s.matlab.fonts.editor.heading1.Color.clearPersonalValue
s.matlab.fonts.editor.heading1.Size.clearPersonalValue

%
%
%
%% uilabel でHTMLマークアップ
% ちょっと地味目の新機能ですが、ラベル（uilabel）のテキストで HTML マークアップが使える様になりました。私個人的には HTML の方がいろいろカスタマイズしやすいので気に入っています。uilabel は uifigure でしか使えないのでご注意。figure では使えません。これを機に uifigure に移行してみませんか？
% txt = "ついにラベルにHTMLタグが使える様になりました！" + ...
%     "<ul>" + ...
%     "<li>この様にリストを作ることもできるし</li>" + ...
%     "<li style=""color: red;"">色を指定することもできるし</li>" + ...
%     "<li style=""font-size: 20;"">フォントサイズを指定することもできるし</li>" + ...
%     "<li><a href=""http://www.mathworks.com/"">リンクを貼ることもできます</a></li>" + ...
%     "</ul>";
% fig = uifigure(Position = [300 300 400 200]);
% lbl = uilabel(fig, ...
%     Position = [20 20 360 160], ...
%     Interpreter = 'html', ...
%     WordWrap = 'on', ...
%     Text = txt);
%
%
%
%% "プロットの作成" ライブ エディター タスク
% R2021a ではライブ エディター タスクに新しく「プロットの作成」が追加されました。
% "どんな可視化がベストなのか分からない"
% "どのオプションをいじれば良いのか分からない"
% という場合は試してみてください。
%
%
%
%% tick label の自動回転
% tick labelの角度は xtickangle や ytickangle で指定できることを知っている方はいるかもしれません。これは、ラベルが重ならないように角度をつけるためですが、 R2021a ではラベルの角度を自動的に調整してくれます。しかも、figure のサイズをマウスで変更した時もリアルタイムで調整してくれます。
% bar(rand(15,1))
% xticks(1:15)
% xticklabels(cellstr(datetime(2021,11,1:15),"M月d日"))
%
%
%
%% Class Diagram Viewer
% MATLAB でオブジェクト指向プログラミングをされている方にとっては必見です。クラス実装の詳細、メソッドやプロパティの属性、スーパークラスやサブクラスの関係性などについて可視化したいと思ったことありませんか？複数のメンバーとソフトウェア開発を行っている場合は、この様な情報の共有は必須となります。Class Diagram Viewer では、クラスの詳細を可視化することができます。
%
%
%
%% おわりに
% 以上、R2021aの個人的な一押しMATLAB新機能でした。
% でも実は、R2021aには今回紹介した物の10倍以上の数の新機能があります。私は毎回リリースノートを読むのを楽しみにしています。皆さんも読書リストにMATLAB リリースノートを追加してみては如何でしょう。
%
%
%% 補助関数
% 以下は跳ねるボールのシミュレーションで使われている補助関数です。
% 放物運動の ode 関数

function dYdt = projectile(t,Y)
% Y = [x; x'; y; y']
dYdt = zeros(4,1);
dYdt(1) = Y(2);
dYdt(2) = 0;
dYdt(3) = Y(4);
dYdt(4) = -9.81;
end

% 地面や壁に当たったイベントを検出するためのイベント関数

function [position,isterminal,direction] = hitEvent(t,Y,xlimits)
% Y = [x; x'; y; y']

% [地面; 左壁; 右壁]
position = [Y(3);Y(1)-xlimits(1);Y(1)-xlimits(2)];
isterminal = [1;1;1];
direction = [-1;-1;1];
end

% シミュレーション結果を集約するための関数

function [T,X,Y] = appendData(T,X,Y,t,y)
T = [T;t+T(end)];
X = [X;y(:,1)];
Y = [Y;y(:,3)];
end

% 新しい初期値を計算するための関数

function init_cond = calcNewInit(y,init_cond,ie)
if isempty(ie)                % イベント検出しなかった。地面や壁に当たらなかった
  init_cond = y(end,:);
elseif ie == 1                % 地面に当たった
  init_cond = [y(end,1) init_cond(2) y(end,3) -y(end,4)*0.9];
elseif ie == 2 || ie == 3     % 壁に当たった
  init_cond = [y(end,1) -init_cond(2) y(end,3) y(end,4)];
end
end