function xpklein(action);
%XPKLEIN Klein bottle demo.
%   A Klein bottle is a nonorientable surface in 
%   four-dimensional space. It is formed by attaching two 
%   Mobius strips along their common boundary.
%
%   Klein bottles cannot be constructed without intersection 
%   in three-space. The figure shown is an example of such a 
%   self-intersecting Klein bottle. 
%
%   Thanks to Davide Cervone, University of Minnesota.

%   Denise L. Chen  7-6-93
%   Copyright 1984-2000 The MathWorks, Inc. 
%   $Revision: 1.25 $  $Date: 2000/08/29 18:56:04 $

oldFigNumber = watchon;

if nargin < 1,
   action='initialize';
end;

if strcmp(action,'initialize'),
   figNumber=figure( ...
      'Name','Klein Bottle', ...
      'NumberTitle','off', ...
      'Visible','off');
   axes( ...
      'Position',[0.05 0.05 0.70 0.90]);
   
   %===================================
   % Information for all buttons
   labelColor=[0.8 0.8 0.8];
   yInitPos=0.90;
   xPos=0.80;
   btnLen=0.15;
   btnWid=0.10;
   % Spacing between the button and the next command's label
   spacing=0.05;
   
   %====================================
   % The CONSOLE frame
   frmBorder=0.02;
   yPos=0.05-frmBorder;
   frmPos=[xPos-frmBorder yPos btnLen+2*frmBorder 0.9+2*frmBorder];
   uicontrol( ...
      'Style','frame', ...
      'Units','normalized', ...
      'Position',frmPos, ...
      'BackgroundColor',[0.50 0.50 0.50]);
   
   %====================================
   % The WHOLE button
   btnNumber=1;
   yPos=0.90-(btnNumber-1)*(btnWid+spacing);
   labelStr='Whole';
   callbackStr='xpklein(''whole'')';
   uicontrol( ...
      'Style','push', ...
      'Units','normalized', ...
      'Position',[xPos yPos-spacing btnLen btnWid], ...
      'String',labelStr, ...
      'Callback',callbackStr);
  
   %====================================
   % The HALF button
   btnNumber=2;
   yPos=0.90-(btnNumber-1)*(btnWid+spacing);
   labelStr='Half';
   callbackStr='xpklein(''half'')';
   uicontrol( ...
      'Style','push', ...
      'Units','normalized', ...
      'Position',[xPos yPos-spacing btnLen btnWid], ...
      'String',labelStr, ...
      'Callback',callbackStr);
     
   %====================================
   % The TRANSPARENCY button
   btnNumber=3;
   yPos=0.90-(btnNumber-1)*(btnWid+spacing);
   labelStr='Transparent';
   callbackStr='xpklein(''transparency'')';
   uicontrol( ...
      'Style','push', ...
      'Units','normalized', ...
      'Position',[xPos yPos-spacing btnLen btnWid], ...
      'String',labelStr, ...
      'Callback',callbackStr);
  
   %====================================
   % The INFO button
   labelStr='Info';
   callbackStr='xpklein(''info'')';
   uicontrol( ...
      'Style','push', ...
      'Units','normalized', ...
      'Position',[xPos 0.20 btnLen 0.10], ...
      'String',labelStr, ...
      'Callback',callbackStr);
   
   %====================================
   % The CLOSE button
   labelStr='Close';
   callbackStr= 'close(gcf)';
   uicontrol( ...
      'Style','push', ...
      'Units','normalized', ...
      'Position',[xPos 0.05 btnLen 0.10], ...
      'String',labelStr, ...
      'Callback',callbackStr);
   
   %====================================
   % Generate the Klein bottle
   
   % Set up the graphics parameters
   %set(gcf,'color',[0.7 .7 .7]);
   set(figNumber,'color',[0.3 .3 .3]);
   colormap(hsv);
   
   % Set Klein bottle parameters
   n = 12;
   a = .2;                         % the diameter of the small tube
   c = .6;                         % the diameter of the bulb
   t1 = pi/4 : pi/n : 5*pi/4;      % parameter along the tube
   t2 = 5*pi/4 : pi/n : 9*pi/4;    % angle around the tube
   u  = pi/2 : pi/n : 5*pi/2;
   [X,Z1] = meshgrid(t1,u);
   [Y,Z2] = meshgrid(t2,u);
   
   % The handle
   len = sqrt(sin(X).^2 + cos(2*X).^2);
   x1 = c*ones(size(X)).*(cos(X).*sin(X) ...
      - 0.5*ones(size(X))+a*sin(Z1).*sin(X)./len);
   y1 = a*c*cos(Z1).*ones(size(X));
   z1 = ones(size(X)).*cos(X) + a*c*sin(Z1).*cos(2*X)./len;
   handleHndl=surf(x1,y1,z1,X);
   set(handleHndl,'EdgeColor',[.5 .5 .5],'Tag','handle');
   set(handleHndl,'UserData',X);    % save CData in UserData
   hold on;
   
   % The bulb
   r = sin(Y) .* cos(Y) - (a + 1/2) * ones(size(Y));
   x2 = c * sin(Z2) .* r;
   y2 = - c * cos(Z2) .* r;
   z2 = ones(size(Y)) .* cos(Y);
   bulbHndl=surf(x2,y2,z2,Y);
   set(bulbHndl,'EdgeColor',[.5 .5 .5],'Tag','bulb');
   set(bulbHndl,'UserData',Y);    % save CData in UserData
   
   view(-37,30);
   axis off
   box on
   
   % Now make the figure reappear
   set(figNumber, ...
      'Visible','on');
   
   watchoff(oldFigNumber);
   
   %====================================
   % Half of the bottle
   
elseif strcmp(action,'half')
   
   watchon;
   shading interp;
   handleHndl = findobj(gcf,'Type','surface','Tag','handle');
   bulbHndl = findobj(gcf,'Type','surface','Tag','bulb');
   
   c = get(handleHndl,'UserData');
   [row col] = size(c);
   c(1:floor(row/2),:) = NaN*ones(floor(row/2),col);
   set(handleHndl,'CData',c);
   
   c = get(bulbHndl,'UserData');
   [row col] = size(c);
   c(1:floor(row/2),:) = NaN*ones(floor(row/2),col);
   set(bulbHndl,'CData',c);
   set([handleHndl bulbHndl],'FaceAlpha',1);
   drawnow;
   watchoff;
   
   %====================================
   % Whole bottle
   
elseif strcmp(action,'whole')
   
   watchon;
   shading faceted;
   handleHndl = findobj(gcf,'Type','surface','Tag','handle');
   bulbHndl = findobj(gcf,'Type','surface','Tag','bulb');
   set(handleHndl,'CData',get(handleHndl,'UserData'));
   set(bulbHndl,'CData',get(bulbHndl,'UserData'));
   set([handleHndl bulbHndl],'EdgeColor',[.5 .5 .5],'FaceAlpha',1);
   drawnow;
   watchoff;
      
   %====================================
   % Transparent bottle
   
elseif strcmp(action,'transparency')
   
   watchon;
   shading faceted;
   handleHndl = findobj(gcf,'Type','surface','Tag','handle');
   bulbHndl = findobj(gcf,'Type','surface','Tag','bulb');
   set(handleHndl,'CData',get(handleHndl,'UserData'));
   set(bulbHndl,'CData',get(bulbHndl,'UserData'));
   set([handleHndl bulbHndl],'EdgeColor',[.5 .5 .5],'FaceAlpha',.5);
   drawnow;
   watchoff;
   
   %====================================
   % Info text 
   
elseif strcmp(action,'info')
   watchoff;
   helpwin(mfilename)
   
end;        % if strcmp(action, ...


	