function wvfour1(action)
%WVFOUR1  Plot Fourier sine or cosine approximations of a function.
%
%         <DESCRIPTION>
%         wvfour1 is a graphical interface for plotting truncated Fourier
%         sine or cosine series approximations of a function f(x) defined
%         on the unit interval 0<x<1.
%
%         <TO RUN>
%         Type wvfour1 at the MATLAB prompt with no options.
%
%         <TO USE>
%         Once started, the following options may be set:
%
%            X Range -  View the function and its Fourier series on x0 < x < x1.
%                       With f(x) defined on [0,1], extending the X Range beyond
%                       this interval shows the periodic extension of the Fourier
%                       series.
%            Series Type - A radio button to select Fourier sine or cosine series.
%            Terms Slider - Used to select the number of terms in the Fourier
%                           series approximation.
%            f(x)         - Editable field to enter the function f(x) to be
%                           approximated.
%
%            RESTART      - Button to refresh the plot area.

% Created: 6/95 by R. Knobel
% Requires: MATLAB 4.2(c) - MATLAB 5.3. 

if nargin < 1
   action = 'start';
end

% If this is not the initial startup, get graphic handles 
if ~strcmp(action,'start'),
   handles = get(gcf,'UserData');
   hPlot1  = handles(1);
   hPlot2  = handles(2);
   hFunction = handles(3);
   hAxes   = handles(4);
   hXmin   = handles(5);
   hXmax   = handles(6);
   hTerms_slider = handles(7);
   hTerms_field  = handles(8);
   hSin    = handles(9);
   hCos    = handles(10);
end

% If this is the initial startup, create figure, controls, and 
% initial plot.

if strcmp(action,'start'),
   
   bgcolor = 'black';
   fgcolor = 'white';
   
   figure; 
   set(gcf, ...
      'NumberTitle','off', ...
      'Name','Fourier Series', ...
      'BackingStore','off',...
      'Units','normalized',...
      'Color',bgcolor);
   
   % Console Frame
     
   top      =0.95;
   bottom   =0.05;
   left     =0.82;
   btnWid   =0.13;
   btnHt    =0.08;
   frmBorder=0.02;
   
   frmPos=[left-frmBorder bottom-frmBorder btnWid+2*frmBorder ...
         top-bottom+2*frmBorder];
   uicontrol('Style','frame', ...
      'Units','normalized', ...
      'Position',frmPos, ...
      'ForegroundColor','white',...
      'BackgroundColor','black');
   
   % X interval
   
   uicontrol( ...
      'Style','text',...
      'Units','normalized',...
      'Position', [left top-.08 .14 .07],...
      'BackgroundColor','black',...
      'ForegroundColor','red',...
      'String','X Range View');
   min_x = 0;
   hXmin=uicontrol( ...
      'Style','edit',...
      'Units','normalized',...
      'Position', [left top-.15 .05 .05],...
      'BackgroundColor',[1 1 1],...
      'String',num2str(min_x));
   max_x = 1;
   hXmax=uicontrol( ...
      'Style','edit',...
      'Units','normalized',...
      'Position', [left+.07 top-.15 .05 .05],...
      'BackgroundColor',[1 1 1],...
      'String',num2str(max_x));
   
   % Cosine or Sine Series Radio Control
   
   uicontrol(...
      'Style','frame',...
      'Units','normalized',...
      'Position',[.81 top-.35 .15 .12],...
      'Background','white');
   uicontrol(...
      'Style','text',...
      'Units','normalized',...
      'Position',[.81 top-.25 .15 .04],...
      'Background','black',...
      'Foreground','red',...
      'String','Series Type');
   hSin = uicontrol(...
      'Style','radio',...
      'String','Sine',...
      'Background','white',...
      'Units','normalized',...
      'Position',[left top-.29 btnWid .04],...
      'Value',1,...
      'CallBack','wvfour1(''typesin'')');
   
   hCos = uicontrol(...
      'Style','radio',...
      'String','Cosine',...
      'Background','white',...
      'Units','normalized',...
      'Position',[left top-.33 btnWid .04],...
      'CallBack','wvfour1(''typecos'')');
   
   % "Number of terms" field and slider
   
   uicontrol(...
      'Style','text',...
      'Units','normalized',...
      'Position',[left-.01 top-.48 .11 .05],...
      'BackgroundColor','black',...
      'ForegroundColor','red',...
      'String','# Terms: ');
   terms = 1;
   hTerms_field=uicontrol( ...
      'Style','text',...
      'Units','normalized',...
      'Position', [left+.10 top-.48 .04 .05], ...
      'BackgroundColor','black',...
      'ForegroundColor','red',...
      'String', 'terms'); 
   
   min_terms = 1;
   max_terms = 100;
   hTerms_slider=uicontrol( ...
      'Style','slider',...
      'Units','normalized',...
      'Position',[left top-.52 btnWid .04],...
      'Value',terms,...
      'Max',max_terms,...
      'Min',min_terms,...
      'CallBack','wvfour1(''draw'')');
   uicontrol(...
      'Style','text',...
      'Units','normalized',...
      'Position',[left top-.56 .03 .04],...
      'BackgroundColor','black',...
      'ForegroundColor','red',...
      'String',num2str(min_terms));
   uicontrol(...
      'Style','text',...
      'Units','normalized',...
      'Position',[left+btnWid-.04 top-.56 .04 .04],...
      'BackgroundColor','black',...
      'ForegroundColor','red',...
      'String',num2str(max_terms));
   
   % The Restart Button
   
   uicontrol( ...
      'Style','push', ...
      'Units','normalized', ...
      'Position',[left bottom+btnHt+.02  btnWid btnHt], ...
      'String','Restart', ...
      'Callback','wvfour1(''restart'')');
   
   % The Close Button
   
   uicontrol( ...
      'Style','Pushbutton', ...
      'Units','normalized',... 
      'Position',[left bottom btnWid btnHt], ...
      'Callback','wvfour1(''close'')',...
      'String','Close');
   
   % Field at bottom of screen to input f(x)
      
   oldFunction = 'x^2*(1-x)'; 
   
   uicontrol('Style','text',...
      'Units','normalized',...
      'Position',[.03 .02 .10 .045],...
      'BackgroundColor',bgcolor,...
      'ForegroundColor',fgcolor,...
      'String','f(x) = ');
   hFunction=uicontrol(...
      'Style','edit',...
      'Units','normalized',...
      'Position',[.13 .02 .5 .045],...
      'BackgroundColor','white',...
      'ForegroundColor','black',...
      'UserData',' ',...
      'String',oldFunction );
   
   % Setup plot area
   
   hAxes = axes(...
      'Position',[.12 .26 .6 .6],...
      'color',bgcolor,...
      'XColor',fgcolor,...
      'YColor',fgcolor,...
      'XLim',[min_x max_x],...
      'YLim',[0 1]);
   hold on;
   xlabel('x');
   ylabel('f(x)');
   title('Green - f(x)      Yellow - Fourier Series Approximation','Color',fgcolor);
   
   hPlot1 = plot(min_x,0,'g','EraseMode','xor');
   hPlot2 = plot(max_x,0,'y','EraseMode','xor');
   
   handles = [hPlot1 hPlot2 hFunction hAxes hXmin hXmax hTerms_slider hTerms_field ...
         hSin hCos]; 
      set(gcf,'UserData',handles);
      
   wvfour1('restart')
   
elseif strcmp(action,'restart'),
   
   min_x = str2num(get(hXmin,'String'));
   max_x = str2num(get(hXmax,'String'));
   x = linspace(0,1,200);
   
   f = get(hFunction,'String');
   l = length(f);
   for k = fliplr(find((f=='^') | (f=='*') | (f=='/')))
      if ~strcmp(f(k-1),'.')
         f = [f(1:k-1) '.' f(k:l)];
         l = l+1;
      end
   end
   vectorized_f = f;
   
   oldFunction = get(hFunction,'UserData');
   if ~strcmp(oldFunction,vectorized_f)
      oldFunction = vectorized_f;
      max_terms = get(hTerms_slider,'Max');
      for k=1:max_terms,
         integrand = ['(' oldFunction ').* sin(pi*' num2str(k) '*x)'];
         sin_coeff(k) = sum( eval(integrand) ) / 200;
         integrand = ['(' oldFunction ').* cos(pi*(' num2str(k-1) ')*x)'];
         cos_coeff(k) = sum( eval(integrand) ) / 200;
      end;
      cos_coeff(1) = .5*cos_coeff(1);
      
      set(hSin,'UserData',sin_coeff);
      set(hCos,'UserData',cos_coeff);
      set(hFunction,'UserData',oldFunction);
   end;
   
   oldFunction = get(hFunction,'UserData');
   y = eval(oldFunction);
   if length(y)==1,
      y = y*ones(size(x));
   end;
   
   a = min(y);
   b = max(y);
   if min_x==0 & max_x==1,
      scale = b-a;
      min_y = min([0 a-.1*scale]);
      max_y = max([0 b+.1*scale]);
   else
      scale = max(abs([a b])); 
      max_y =  1.1*scale;
      min_y = -1.1*scale;
   end;
   if min_y == max_y,
      min_y = min_y - .5;
      max_y = max_y + .5;
   end;
   
   set(hAxes, 'XLim',[min_x max_x], 'YLim',[min_y max_y]);
   set(hPlot1, 'XData',x,'YData',y);
   
   set(hTerms_slider,'Value',1);
   set(hTerms_field,'String',1);
    
   wvfour1('draw')
   
elseif strcmp(action,'draw'),
   
   max_x = str2num(get(hXmax,'String'));
   min_x = str2num(get(hXmin,'String'));
   terms = ceil(get(hTerms_slider,'Value'));
   set(hTerms_field,'String',num2str(terms));
   
   sin_coeff = get(hSin,'UserData');
   cos_coeff = get(hCos,'UserData');
   
   numpts = ceil(max_x-min_x)*100;
   x = linspace(min_x,max_x,numpts);
   y = zeros( size(x) );
   
   if get(hSin,'Value')==1,
      for k=1:terms,
         y = y + 2 * sin_coeff(k) * sin(k*pi*x);
      end;
   else
      for k=1:terms,
         y = y + 2 * cos_coeff(k) * cos((k-1)*pi*x);
      end;
   end;
   set(hPlot2,'XData',x,'YData',y)
   
elseif strcmp(action(1:4),'type'),
   
   if strcmp(action,'typesin'),
      set(hSin,'Value',1);
      set(hCos,'Value',0);
   else
      set(hSin,'Value',0);
      set(hCos,'Value',1);
   end;
   
   wvfour1('draw');
   
elseif strcmp(action,'close'),
   
   close
   
end