MATLABで時計アプリ (2) (アナログ時計) 

## はじめに
[前回](https://qiita.com/sanmojih/items/0bd8a326a6a022c4b615)、MATLABでのデジタル時計アプリの作成方法を紹介しました。
デジタル時計は、数字を表示するだけなので、次は、針を持つアナログ時計を作成しています。

## figureの作成

まず、figureを作成します。こちらはアナログ時計とほぼ変わりません

```matlab
%% Figureの表示
figH                 = figure();              % figH: Figureオブジェクト
figH.MenuBar         = 'none';                % メニューをオフ
figH.CloseRequestFcn = @CloseRequestFcn_figH; % クローズ時のコールバック関数
figH.NumberTitle     = 'off';                 % 番号表示なし
figH.Name            = 'Analog Clock';        % タイトル
```

## axes の作成
アナログ時計では、針を描画したいので、figure全体に表示するaxes(軸)を準備します。

```matlab
%% Axesの表示
axH          = axes(figH);    % axH: 軸オブジェクト
axH.Units    = 'normalized';  % Positionの単位指定
axH.Position = [0,0,1,1];     % Figure全体にAxesを表示
```

## 時計の枠の表示

時計の枠を作成します。最も一般的な時計ということで、次のように円を表示します。

```matlab
%% 時計枠(丸) を表示
x = linspace(0,2*pi,100);              % 1周を100分割(単位:ラジアン)
plot(axH,sin(x),cos(x),'LineWidth',5); % 円を描画

axis(axH,'equal'); % 縦横比を合わせる
hold(axH,'on');    % plot追加のためhold
```

こんな表示になります。
![simple_analogclock_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482917/ae4bf8b3-1d80-0c5e-d720-9b8d02c82a85.png)


## 数字を表示

時計の時刻を表す数字を text で表示します。
各時刻に対応する角度を計算して、sin/cos で座標を決定します。

```matlab
%% 数字を表示
for h1=1:12
    radh = -h1/12*2*pi+pi/2; % 角度の計算
    
    textH = text(axH,0.8*cos(radh),0.8*sin(radh),num2str(h1)); % テキスト作成
    textH.HorizontalAlignment = 'center';  % 中央寄せ
    textH.FontSize            = 30;        % フォントサイズ
    textH.FontWeight          = 'bold';    % 太字指定
end
```

数字が入って少し時計らしくなってきました。

![simple_analogclock_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482917/6d0faa75-659e-df51-a0f4-edf2f0cdaf27.png)


## 時計の針の表示
plot で針を表示します。'k' は色を黒に指定することを意味します。太さは、LineWidth で指定します。

```matlab
%% 長針/短針 のデフォルト表示 (6:00)

hourLineH   = plot(axH,[0,0],[0,-0.6],'k','LineWidth',10);
minuteLineH = plot(axH,[0,0],[0,1],   'k','LineWidth',5);
secondLineH = plot(axH,[0,0],[0,1],   'k','LineWidth',1);
```

一応、時計と認識できる絵になりました。

![simple_analogclock_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482917/78c9a267-0dd5-d498-fe40-8e7b9c8c57df.png)


## 針の位置の設定（timerのコールバック関数）

timer のコールバック関数では、その時間での針の位置を計算して表示を更新します。
now は、現在のシリアル時刻(datenum: 0年1月0日0:00を0とした日数の表現)を得ることができます。
単位は、'日'なので、例えば、60*60*24 を乗算すると、単位が秒になります。
これを使って計算すると、現在の時刻に相当する針の角度を求めることができます。
グラフィックスとして、針の位置を変更するためには、それぞれの lineオブジェクトの XData, YData を更新します。

```matlab
    function updateClock(~,~)
        %% Timerコールバック: 表示の更新                
        % 各針の角度の計算
        sec = now*60*60*24; % 現在時刻の経過秒
        
        rad1 = -fix(sec)/60*2*pi+pi/2;  % 秒針の角度
        rad2 = -sec/60/60*2*pi+pi/2;    % 長針(分)の角度
        rad3 = -sec/60/60/12*2*pi+pi/2; % 短針(時間)の角度
        
        % 各針の描画の更新
        secondLineH.XData = [0,cos(rad1)];        
        secondLineH.YData = [0,sin(rad1)];
        
        minuteLineH.XData = [0,cos(rad2)];
        minuteLineH.YData = [0,sin(rad2)];
        
        hourLineH.XData = [0,0.6*cos(rad3)];
        hourLineH.YData = [0,0.6*sin(rad3)];        
        
    end
```

## 完成したプログラム

[前回](https://qiita.com/sanmojih/items/0bd8a326a6a022c4b615)と同じところは省略して、プログラム全体を示します。

```matlab
function simple_analogclock()

%% Figureの表示
figH                 = figure();              % figH: Figureオブジェクト
figH.MenuBar         = 'none';                % メニューをオフ
figH.CloseRequestFcn = @CloseRequestFcn_figH; % クローズ時のコールバック関数
figH.NumberTitle     = 'off';                 % 番号表示なし
figH.Name            = 'Analog Clock';        % タイトル

%% Axesの表示
axH          = axes(figH);    % axH: 軸オブジェクト
axH.Units    = 'normalized';  % Positionの単位指定
axH.Position = [0,0,1,1];     % Figure全体にAxesを表示

%% 時計枠(丸) を表示
x = linspace(0,2*pi,100);              % 1周を100分割(単位:ラジアン)
plot(axH,sin(x),cos(x),'LineWidth',5); % 円を描画

axis(axH,'equal'); % 縦横比を合わせる
hold(axH,'on');    % plot追加のためhold

%% 数字を表示
for h1=1:12
    radh = -h1/12*2*pi+pi/2; % 角度の計算
    
    textH = text(axH,0.8*cos(radh),0.8*sin(radh),num2str(h1)); % テキスト作成
    textH.HorizontalAlignment = 'center';  % 中央寄せ
    textH.FontSize            = 30;        % フォントサイズ
    textH.FontWeight          = 'bold';    % 太字指定
end

%% 長針/短針 のデフォルト表示 (6:00)

hourLineH   = plot(axH,[0,0],[0,-0.6],'k','LineWidth',10);
minuteLineH = plot(axH,[0,0],[0,1],   'k','LineWidth',5);
secondLineH = plot(axH,[0,0],[0,1],   'k','LineWidth',1);

% 現在時刻に合わせる
updateClock();

%% 軸表示の調整
axH.XTick = []; % X軸目盛をオフ
axH.YTick = []; % Y軸目盛をオフ

%% Timerの設定
timerH               = timer();      % timeH: タイマーオブジェクト
timerH.ExecutionMode = 'FixedRate';  % 定期的に実行するよう指定
timerH.Period        = 1;            % 1秒間隔
timerH.TimerFcn      = @updateClock; % コールバック関数指定

% 開始時刻の調整(秒が変わる瞬間にできるだけ合わせる。※処理時間の若干の遅延は許容する)
curTime   = datetime(now,'ConvertFrom','datenum');  % 現在時刻
delayTime = ceil(curTime.Second)-curTime.Second;    % 次に秒が変わる時間との差分(ミリ秒)を計算

timerH.StartDelay = delayTime; % Timerの開始時刻までの遅延を指定

%% timerの開始
start(timerH);

    %% コールバック関数
    function CloseRequestFcn_figH(~,~)
        %% Figureを閉じたときのコールバック：timerをStopしてからクローズ
        stop(timerH);
        delete(timerH);
        delete(figH);
    end

    function updateClock(~,~)
        %% Timerコールバック: 表示の更新                
        % 各針の角度の計算
        sec = now*60*60*24; % 現在時刻の経過秒
        
        rad1 = -fix(sec)/60*2*pi+pi/2;  % 秒針の角度
        rad2 = -sec/60/60*2*pi+pi/2;    % 長針(分)の角度
        rad3 = -sec/60/60/12*2*pi+pi/2; % 短針(時間)の角度
        
        % 各針の描画の更新
        secondLineH.XData = [0,cos(rad1)];        
        secondLineH.YData = [0,sin(rad1)];
        
        minuteLineH.XData = [0,cos(rad2)];
        minuteLineH.YData = [0,sin(rad2)];
        
        hourLineH.XData = [0,0.6*cos(rad3)];
        hourLineH.YData = [0,0.6*sin(rad3)];        
        
    end

end
```

## 実行例
実行してみます。

![simple_analogclock.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482917/6bb37509-2b89-c8a7-32be-3f82a7d67f51.png)

## 終わりに
シンプルな時計アプリの例を紹介しました。
GUIやアニメーションのプログラムの勉強にはいい題材で、好みでいろんな時計アプリを作成できると思いますので、チャレンジしてみてください。
ちなみに、[MATLAB Central](https://jp.mathworks.com/matlabcentral/fileexchange?q=clock) にもいろいろな例がありますよ。