Initial commit
This commit is contained in:
commit
3af0ed0421
53
examples.m
Normal file
53
examples.m
Normal file
@ -0,0 +1,53 @@
|
||||
%% Sine
|
||||
|
||||
frequency = 1;
|
||||
amplitude = 1;
|
||||
phase = 0; %pi/2;
|
||||
|
||||
fourierViz(frequency, amplitude, phase, 'baseMultiply', 0.25, 'export', false);
|
||||
|
||||
|
||||
%% Square simple
|
||||
|
||||
frequency = 1:2:3;
|
||||
amplitude = 2./(pi*comps);
|
||||
phase = [0 0.25]*2*pi; % Phases expressed in cycles
|
||||
|
||||
fourierViz(frequency, amplitude, phase, 'baseMultiply', 1, 'export', false);
|
||||
|
||||
|
||||
%% Square
|
||||
|
||||
frequency = 1:2:41;
|
||||
amplitude = 2./(pi*frequency);
|
||||
phase = zeros(numel(frequency), 1);
|
||||
|
||||
fourierViz(frequency, amplitude, phase, 'baseMultiply', 4, 'export', false);
|
||||
|
||||
|
||||
%% Square complex
|
||||
|
||||
frequency = 1:2:101;
|
||||
amplitude = 2./(pi*frequency);
|
||||
phase = zeros(numel(frequency), 1);
|
||||
|
||||
fourierViz(frequency, amplitude, phase, 'baseMultiply', 20, 'export', false);
|
||||
|
||||
|
||||
%% Sawtooth
|
||||
|
||||
frequency = 1:15;
|
||||
amplitude = 2./(pi*frequency);
|
||||
phase = zeros(numel(frequency),1);
|
||||
|
||||
fourierViz(frequency, amplitude, phase, 'baseMultiply', 3, 'export', false);
|
||||
|
||||
|
||||
%% Beat
|
||||
|
||||
frequency = [1 1.2];
|
||||
amplitude = [1 1];
|
||||
phase = [0 0];
|
||||
|
||||
fourierViz(frequency, amplitude, phase, 'baseMultiply', 1.5, 'export', false);
|
||||
|
||||
144
fourierViz.m
Normal file
144
fourierViz.m
Normal file
@ -0,0 +1,144 @@
|
||||
function fourierViz(varargin)
|
||||
%FOURIERVIZ Fourier visualization in Matlab
|
||||
%
|
||||
% By default, the fastest component has a frequency of 1 Hz
|
||||
|
||||
% Handle input
|
||||
p = inputParser;
|
||||
p.addOptional('frequency', 1);
|
||||
p.addOptional('amplitude', 1);
|
||||
p.addOptional('phase', 0);
|
||||
p.addParamValue('baseMultiply', 2);
|
||||
p.addParamValue('export', false);
|
||||
p.addParamValue('filename', 'fourierVizLastRun.gif', @ischar);
|
||||
p.parse(varargin{:});
|
||||
p = p.Results;
|
||||
|
||||
% Component frequency scale factor
|
||||
freqScaleFactor = max(p.frequency) / p.baseMultiply;
|
||||
|
||||
% Normalize magnitudes
|
||||
p.amplitude = p.amplitude / sum(p.amplitude);
|
||||
|
||||
% Figure
|
||||
doPlot = true;
|
||||
fh = figure('Position', [200 100 1600 800]);
|
||||
opts = struct;
|
||||
opts.margin = [0 0 0 0];
|
||||
opts.spaceBetweenPlots = 0;
|
||||
opts.nX = 1;
|
||||
opts.nY = 1;
|
||||
opts.iX = 1;
|
||||
opts.iY = 1;
|
||||
mk.subplot(opts);
|
||||
hold on;
|
||||
set(gca,'xtick',[]);
|
||||
set(gca,'xticklabel',[]);
|
||||
set(gca,'ytick',[]);
|
||||
set(gca,'yticklabel',[]);
|
||||
xlim([-1.2 3.2]);
|
||||
ylim([-1.2 1.2]);
|
||||
|
||||
% Time
|
||||
dt = 0.016;
|
||||
tick = 0;
|
||||
|
||||
% Base frequency & period
|
||||
baseFrequency = sym(p.frequency(1)/freqScaleFactor);
|
||||
for ii = 2:numel(p.frequency)
|
||||
baseFrequency = gcd(baseFrequency, sym(p.frequency(ii)/freqScaleFactor));
|
||||
end
|
||||
baseFrequency = double(baseFrequency);
|
||||
basePeriod = 1/baseFrequency;
|
||||
|
||||
% Circle
|
||||
xCircle = 0:2*pi/100:2*pi;
|
||||
|
||||
% Oscilloscope
|
||||
osc = nan(6e2,1);
|
||||
oscilloscopePrefilled = false;
|
||||
|
||||
% Colors
|
||||
clrGrey = struct('color', [0.8784 0.8784 0.8784]);
|
||||
clrGreen = struct('color', [0.1804 0.4902 0.1961]);
|
||||
clrBlue = struct('color', [0.0824 0.3961 0.7529]);
|
||||
clrRed = struct('color', [0.7765 0.1569 0.1569]);
|
||||
|
||||
while doPlot
|
||||
tick = tick + 1;
|
||||
|
||||
% Has the figure been closed
|
||||
if ~ishandle(fh)
|
||||
doPlot = false;
|
||||
continue;
|
||||
end
|
||||
|
||||
% Update time
|
||||
t = dt * tick;
|
||||
|
||||
% Update oscilloscopePrefilled
|
||||
if ~oscilloscopePrefilled && t>=basePeriod
|
||||
if ~any(isnan(osc))
|
||||
oscilloscopePrefilled = true;
|
||||
end
|
||||
tick = 1;
|
||||
t = dt * tick;
|
||||
end
|
||||
|
||||
% Init plot coordinates
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
% Plot
|
||||
if oscilloscopePrefilled
|
||||
cla;
|
||||
plot(cos(xCircle), sin(xCircle), '-k', clrGrey);
|
||||
end
|
||||
|
||||
% Compute components
|
||||
for ii = 1:numel(p.frequency)
|
||||
if mod(ii,2) == 0
|
||||
clr = clrGreen;
|
||||
else
|
||||
clr = clrBlue;
|
||||
end
|
||||
alpha = ((t * 2*pi * p.frequency(ii)) / freqScaleFactor) + p.phase(ii);
|
||||
x2 = x + (p.amplitude(ii)*cos(alpha));
|
||||
y2 = y + (p.amplitude(ii)*sin(alpha));
|
||||
if oscilloscopePrefilled
|
||||
plot([x x2], [y y2], '-k', clr, 'LineWidth', 2);
|
||||
plot(x+cos(xCircle)*p.amplitude(ii), y+sin(xCircle)*p.amplitude(ii), '-k', clr, 'LineWidth', 2);
|
||||
end
|
||||
x = x2;
|
||||
y = y2;
|
||||
end
|
||||
osc = [y; osc(1:end-1)];
|
||||
if oscilloscopePrefilled
|
||||
plot(x, y, 'or', clrRed);
|
||||
plot([x, 1.5], [y y], '-r', clrRed, 'LineWidth', 1);
|
||||
plot(linspace(1.5, 3.2, numel(osc)), osc, '-r', clrRed, 'LineWidth', 2);
|
||||
end
|
||||
|
||||
% Export to gif
|
||||
if oscilloscopePrefilled && p.export && t < basePeriod
|
||||
if ishandle(fh)
|
||||
frame = getframe(fh);
|
||||
im = frame2im(frame);
|
||||
end
|
||||
[imind, cm] = rgb2ind(im, 256);
|
||||
|
||||
if tick == 1
|
||||
imwrite(imind, cm, p.filename, 'gif', 'Loopcount', inf, 'DelayTime', 0.016);
|
||||
else
|
||||
imwrite(imind, cm, p.filename, 'gif', 'WriteMode', 'append', 'DelayTime', 0.016);
|
||||
end
|
||||
end
|
||||
|
||||
% Pause time
|
||||
if oscilloscopePrefilled
|
||||
pause(dt);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user