Skip to content

Instantly share code, notes, and snippets.

@tejashah88
Created May 12, 2019 13:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tejashah88/81984b8a66a8696c1d14c70fa50ac1e6 to your computer and use it in GitHub Desktop.
Save tejashah88/81984b8a66a8696c1d14c70fa50ac1e6 to your computer and use it in GitHub Desktop.
A rainbow analog clock animation in MATLAB for my ENGIN-136 class.
% Final Project: Rainbow Analog Clock
% Author: Tejas Shah
% Class: ENGIN-136 - Intro to MATLAB
% Clear any vars and current figure and show it on top of screen
clear, clf, shg
% Setup drawing board for clock
axis([-1.1 1.1 -1.1 1.1]);
axis square
axis off
% Used for 1-second markings
sec_x = sin(2*pi*(1:60)/60);
sec_y = cos(2*pi*(1:60)/60);
% Used for 5-second markings
sec_marks = 5:5:60;
% Draw border of clock with 1 second markings
line(sec_x, sec_y,...
'LineStyle', 'none',...
'Marker', 'o',...
'Color', 'black',...
'MarkerSize', 2);
line(sec_x(sec_marks), sec_y(sec_marks),...
'LineStyle', 'none',...
'Marker', '*',...
'Color', 'red',...
'MarkerSize', 8);
% Draw 5-second markings
for i = 1:length(sec_marks)
x_pos = 1.1 * (sec_x(sec_marks(i)) - 0.05);
y_pos = 1.1 * (sec_y(sec_marks(i)));
text(x_pos, y_pos, num2str(i), 'fontsize', 16);
end
% Initialize the various time hands
hour = RainbowLine(20, 4);
min = RainbowLine(20, 4);
sec = RainbowLine(20, 2);
msec = RainbowLine(20, 1);
% Add a close button
close_btn = uicontrol('string', 'close', 'style', 'toggle');
% Increases drawing speed by using any available hardware for openGL
% acceleration. If not present, it'll default to using the software version
opengl hardware
while ishandle(close_btn) && ~get(close_btn, 'value')
c = clock;
% Draw the datetime text below the clock
datetime_text = text(0, -1.2,...
datestr(datetime('now')),...
'FontSize', 16,...
'HorizontalAlignment', 'center');
% Draw hours hand
t = c(4)/12 + c(5)/(60 * 12) + c(6)/(60 * 60 * 12);
hour.Draw([0 0.8*sin(2*pi*t)], [0 0.8*cos(2*pi*t)], [0 .3]);
% Draw minutes hand
t = c(5)/60 + c(6)/(60 * 60);
min.Draw([0 sin(2*pi*t)], [0 cos(2*pi*t)], [.5 .8]);
% Draw seconds hand, changing its color based on second
t = floor(c(6)) / 60;
sec.Draw([0 sin(2*pi*t)], [0 cos(2*pi*t)], t);
% Draw milliseconds hand
t = floor((c(6) - floor(c(6))) * 1000) / 1000;
msec.Draw([0 0.5*sin(2*pi*t)], [0 0.5*cos(2*pi*t)], t);
% Force draw the figure to update hand positions
% NOTE: average draw time is 10 ms +/- 5 ms
drawnow;
% Delete the datetime text for redrawing it after current loop iteration
delete(datetime_text);
end
% Close the figure once we're done
close(gcf);
classdef RainbowLine < handle
properties
X
Y
NumPoints
LineWidth
LineHandle
end
methods
function obj = RainbowLine(NumPoints, LineWidth)
% set colormap to HSV to properly draw the rainbow effect
colormap(hsv);
% by default, the color axis will scale based on the colors
% that are drawn, based on the HSV scale from 0 to 1
% ex. if the colors present are from 0 to 0.8, and all of a
% sudden, a 0.9 appears, the color axis is automatically scaled
% to 0 to 0.9, affecting all the other drawn colors
caxis('manual')
% Number of points for linear spacing generation
obj.NumPoints = NumPoints;
obj.LineWidth = LineWidth;
% Initialize the line handle
obj.Draw([0 0], [0 0]);
end
function obj = Draw(obj, X, Y, CRange)
% Compute the linspace for X and Y
obj.X = linspace(X(1), X(2), obj.NumPoints);
obj.Y = linspace(Y(1), Y(2), obj.NumPoints);
XData = [obj.X; obj.X];
YData = [obj.Y; obj.Y];
% Create an array of zeros for the Z axis (no 3D drawing)
z = zeros(size(obj.X));
ZData = [z; z];
if ~exist('CRange', 'var'); CRange = [0 1]; end
if length(CRange) == 1; CRange = [CRange CRange]; end
% The color range is from 0 to 1, via HSV, so make a series of
% colored points from red to orange to yellow to green to cyan
% to blue to purple back to red with the same amount of points
col = linspace(CRange(1), CRange(2), obj.NumPoints);
ColorData = [col; col];
if ~ishandle(obj.LineHandle)
% Create line handle if it doesn't exist
obj.LineHandle = surface(...
XData, YData, ZData, ColorData,...
'FaceColor', 'none',...
'EdgeColor', 'interp',...
'LineWidth', obj.LineWidth);
else
% Update existing line handle with new data
obj.LineHandle.XData = XData;
obj.LineHandle.YData = YData;
obj.LineHandle.CData = ColorData;
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment