function ReturnValue=LinComb3(fn,argument)
%
%This function demonstrates linear combinations in 3 dimensions.  Currently
%the user inputs alpha, beta, u and v and it plots the two vectors, their 
%linear combination and the plane foremed by the two vectors u and v
%

%    Copyright (C) 1996  Brad North

%    This program is free software; you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation; either version 2 of the License, or
%    (at your option) any later version.

%    This program is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.

%    You should have received a copy of the GNU General Public License
%    along with this program; if not, write to the Free Software
%    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

%    Problems, Comments, and Suggestions can be sent to 
%            northbh@nextwork.rose-hulman.edu
%Changes to be made:
%	Animate vector to form the plane
%		draw seveveral vectors at 0 0 0 and have a point go around in
%		a circle.  Every few degrees, a vector will start growing radially
%		
%Function Directory:
%
%	arrow:		Makes arrow tips on vectors.  Pass 2 handles through
%			argument.  The plot corresponding to the second handle
%			becomes an arrow tip.
%
%	ChangeView:	Changes the 3-D viewpoint using Matlab's view function.
%
%	CalcVectors:	Plots u and v, their alpha u + beta v and a plane if the
%			string 'PlaneToo' is passed through <argument>.
%
%	init:		Draws the figure, axes, GUI and sets up the callbacks and 
%			handles.
%
%Handle Directory:
%	
%	h_MainFig:	The figure's handle.
%
%	The folowing handles are stored in the main figure's UserData
%
%      Array Value    	 Name		   Description			CallBack
%--------------------------------------------------------------------------------------	
%	h_data(1)	h_axis;		The axis.			None
%	h_data(2)	h_U1;		Edit block for u vector		None
%	h_data(3)	h_U2;		Same (element 2)		None
%	h_data(4)	h_U3;		Same (element 3)		None
%	h_data(5)	h_V1;		Edit block for v vector		None
%	h_data(6)	h_V2;		Same (element 2)		None
%	h_data(7)	h_V3;		Same (element 3)		None
%	h_data(8)	h_a;		Edit block for alpha		None		
%	h_data(9)	h_b;		Edit block for beta		None
%	h_data(10)	h_slide1;	Horizontal Slider		lincomb3('ChangeView');
%	h_data(11)	h_slide2;	Vertical Slider			lincomb3('ChangeView');
%
%
%
if nargin == 0
	fn = 'init';
end;


%Activates the figure and makes sure it has been properly initialized

if ~strcmp(fn,'init')
	h_MainFig = gcf;

%If the current figure is not named 'Figure_Name then find 
%the figure that is and put its handle in h_MainFig. This will 
%be found by checking the children of root.

%This is what the name of the figure will be.

Figure_Name='Linear Combinations 3-D';

	if ~strcmp(get(h_MainFig,'name'),Figure_Name)
		h_figs=get(0,'children');
		h_MainFig = findobj(h_figs,'flat',...
				    'name',Figure_Name);

	%If the figure does not exist, initialize it and then
	%run the function that was originally intended

		if length(h_MainFig)==0
			lincomb('init');
			lincomb(fn);
			return;
		end;
	end;
end;
%____________________________________________________________________________

%Function: arrow

%This function puts arrow tips on a vector.  To work is must have
%two plot handles passed to it.  The first handle is the vector the arrow will
%be placed on and the second is the vector that will turn into the arrow tip.
%
%This works by making a triangle out of the vector the tip and an imaginary line
%from the edge of the tip.  Do some trig, find some points and you have an arrow.
%This version works in three dimensions.  This function only re-arranges the xdata,
%ydata, and zdata properties of h_arrow, so the rest of the graph will remain
%unchanged.
%
%NOTE:	To change the length of the arrow tip, modify the <LinePercentage> variable
%	To change the angle of the tips with relation to the vector, change the
%	<ArrowAngle> variable.
%
%	Argument:

%(1)	h_vector:	plot in left window
%(2)	h_arrow:	tip of arrow


if strcmp(fn,'arrow')

	LinePercentage=.2;
	ArrowAngle=pi/8;

	h_vector=argument(1);
	h_arrow=argument(2);
	h_axis=get(h_vector,'Parent');
	xlim=get(h_axis,'xlim');
	ylim=get(h_axis,'ylim');
	
	xdat=get(h_vector,'Xdata');
	ydat=get(h_vector,'Ydata');
	zdat=get(h_vector,'Zdata');
	
	x=xdat(length(xdat))/(xlim(2)-xlim(1));
	y=ydat(length(ydat))/(ylim(2)-ylim(1));
	
	a=sqrt(x^2+y^2);
	if a==0 
		a=10^(-100);
	end;
	b=LinePercentage*a;
	c=sqrt(a^2+b^2-2*a*b*cos(ArrowAngle));
	theta=acos((a^2+c^2-b^2)/(2*a*c));

	if x>0
		at=atan(y/x);
	end;

	if x<0
		at=atan(y/x)+pi;
	end;
	
 	if x==0
		if y<=0
			at=-pi/2;
		end;
		if y >0
			at=pi/2;
		end;
	end;
	phi=at-theta;
	xc=c*cos(phi);
	yc=c*sin(phi);
	xc2=c*cos(theta+at);
	yc2=c*sin(theta+at);
	z=zdat(length(zdat));
	set(h_arrow,'xdata',[xc2 x xc].*abs(xlim(2)-xlim(1)),...
		    'ydata',[yc2 y yc].*abs(ylim(2)-ylim(1)),...
		    'zdata',[(1-.2*cos(ArrowAngle))*z z (1-.2*cos(ArrowAngle))*z]);
	return;
end;
%____________________________________________________________________________

%Function: ChangeView

%Pretty easy.  It pulls the value off of the handles for the sliders and 
%sets the view by the value.

%h_data:
%
%	10)	h_Slide1
%	11)	h_Slide2

if strcmp(fn,'ChangeView')

	h_data=get(h_MainFig,'UserData');
	vert=get(h_data(10),'value');
	horiz=get(h_data(11),'value');
	view(horiz,vert);
	return;

end;

%____________________________________________________________________________

%Function: CalcVectors

if strcmp(fn,'CalcVectors')

	h_data=get(h_MainFig,'UserData');
	
	u=[eval(get(h_data(2),'string'));...
	   eval(get(h_data(3),'string'));...
	   eval(get(h_data(4),'string'))];
	
	v=[eval(get(h_data(5),'string'));...
	   eval(get(h_data(6),'string'));...
	   eval(get(h_data(7),'string'))];

	delete(get(h_data(1),'children'));

	alpha=eval(get(h_data(8),'string'));
	beta=eval(get(h_data(9),'string'));

	if u(1) ~= 0
		u1=0:u(1)/100:u(1);
	else
		u1=zeros(1,101);
	end;

	if u(2) ~= 0
		u2=0:u(2)/100:u(2);
	else
		u2=zeros(1,101);
	end;

	if u(3) ~= 0
		u3=0:u(3)/100:u(3);
	else
		u3=zeros(1,101);
	end;
	
	if v(1) ~= 0
		v1=0:v(1)/100:v(1);
	else
		v1=zeros(1,101);
	end;

	if v(2) ~= 0
		v2=0:v(2)/100:v(2);
	else
		v2=zeros(1,101);
	end;
	
	if v(3) ~= 0
		v3=0:v(3)/100:v(3);
	else
		v3=zeros(1,101);
	end;


	
		uv1=alpha*u1+beta*v1;
		uv2=alpha*u2+beta*v2;
		uv3=alpha*u3+beta*v3;

		h_uplot=plot3(u1,u2,u3,'m','linewidth',2);
		h_vplot=plot3(v1,v2,v3,'b','linewidth',2);

		h_arrow=plot3(0,0,0,'m','linewidth',2);
		lincomb3('arrow',[h_uplot h_arrow]);

		h_arrow=plot3(0,0,0,'b','linewidth',2);
		lincomb3('arrow',[h_vplot h_arrow]);

		h_uvplot=plot3(uv1,uv2,uv3,'k','linewidth',2);
		h_arrow=plot3(0,0,0,'k','linewidth',2);
		lincomb3('arrow',[h_uvplot h_arrow]);
	

	if strcmp(argument,'PlaneToo')
		a=[u(1) u(2);v(1) v(2)];
		b=[u(3);v(3)];
		slopes=a\b;
		colormap(bone);
		xl=get(h_data(1),'xlim');
		yl=get(h_data(1),'ylim');
		[x,y]=meshgrid(linspace(xl(1),xl(2),30),linspace(yl(1),yl(2),30));
		z=slopes(1)*x+slopes(2)*y;
		mesh(x,y,z);

	end;
		


	return;

end;

%____________________________________________________________________________

%Function: init

if strcmp(fn,'init')



	h_MainFig=figure('NumberTitle','off',...
			'Name','Linear Combinations 3-D',...
			'color',[1 1 1]);
	
	h_axis=	axes;
	
	h_axis2=axes('pos',[.6 .8 .4 .2],...
		     'visible','off',...
		     'xlim',[0 1],...
		     'ylim',[0 1]);

	axes(h_axis);
	plot3(0,0,0,'ko');
	hold on;
	set(h_axis,...
		'pos',[.1 .1 .48 .8],...
		'color',[1 1 1],...
		'ycolor',[0 0 0],...
		'xcolor',[0 0 0],...
		'zcolor',[0 0 0]);
		
	view(30,30);

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.6 .3 .4 .45],...
		'style','frame',...
		'back',[1 1 1],...
		'fore',[0 0 0]);

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.6 0 .4 .3],...
		'style','frame',...
		'back',[1 1 1],...
		'fore',[0 0 0]);

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.61 .58 .05 .05],...
		'back',[1 1 1],...
		'style','text',...
		'string','u =',...
		'fore',[1 0 1]);
	
	h_U3=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.67 .50 .08 .05],...
		'back',[1 1 1],...
		'style','edit',...
		'string','0');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.66 .49 .1 .07],...
		'back',[1 1 1],...
		'style','frame');

	h_U2	=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.67 .58 .08 .05],...
		'back',[1 1 1],...
		'style','edit',...
		'string','0');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.66 .57 .1 .07],...
		'back',[1 1 1],...
		'style','frame');

	h_U1=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.67 .66 .08 .05],...
		'back',[1 1 1],...
		'style','edit',...
		'string','1');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.66 .65 .1 .07],...
		'back',[1 1 1],...
		'style','frame');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.79 .58 .05 .05],...
		'back',[1 1 1],...
		'style','text',...
		'string','v =',...
		'fore',[0 0 1]);
	
	h_V3=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.86 .50 .08 .05],...
		'back',[1 1 1],...
		'style','edit',...
		'string','0');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.85 .49 .1 .07],...
		'back',[1 1 1],...
		'style','frame');

	h_V2=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.86 .58 .08 .05],...
		'back',[1 1 1],...
		'style','edit',...
		'string','1');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.85 .57 .1 .07],...
		'back',[1 1 1],...
		'style','frame');
	 
	h_V1=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.86 .66 .08 .05],...
		'back',[1 1 1],...
		'style','edit',...
		'string','0');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.85 .65 .1 .07],...
		'back',[1 1 1],...
		'style','frame');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.63 .35 .16 .07],...
		'string','Plot Vectors',...
		'Callback','lincomb3(''CalcVectors'',''no plane'');');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.81 .35 .16 .07],...
		'string','Plot Plane',...
		'Callback','lincomb3(''CalcVectors'',''PlaneToo'');');

%Vertical Slider
	
	h_slide1=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.62 .05 .035 .2],...
		'Max',360,...
		'Min',0,...
		'CallBack','lincomb3(''ChangeView'');',...
		'style','slider',...
		'value',30);

	h_slide2=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.7 .05 .25 .045],...
		'Max',360,...
		'Min',0,...
		'CallBack','lincomb3(''ChangeView'');',...
		'style','slider',...
		'value',30);

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.7 .16 .25 .05],...
		'back',[1 1 1],...
		'string','Change Viewpoint',...
		'style','text');		

		axes(h_axis2);
		
		text(.15,.73,'a =',...
			'fontname','symbol',...
			'color',[0 0 0]);

		text(.15,.3,'b =',...
			'fontname','symbol',...
			'color',[0 0 0]);

		axes(h_axis);

		xlabel('x','color',[0 0 0]);
		ylabel('y','color',[0 0 0]);
		zlabel('z','color',[0 0 0]);

	h_a=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.72 .91 .1 .05],...
		'style','edit',...
		'back',[1 1 1],...
		'string','1');

	h_b=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.72 .83 .1 .05],...
		'style','edit',...
		'back',[1 1 1],...
		'string','1');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.71 .82 .12 .07],...
		'style','frame',...
		'back',[1 1 1],...
		'fore',[0 0 0]);

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.71 .9 .12 .07],...
		'style','frame',...
		'back',[1 1 1],...
		'fore',[0 0 0]);
	
	h_data(1)=h_axis;
	h_data(2)=h_U1;
	h_data(3)=h_U2;
	h_data(4)=h_U3;
	h_data(5)=h_V1;
	h_data(6)=h_V2;
	h_data(7)=h_V3;
	h_data(8)=h_a;
	h_data(9)=h_b;
	h_data(10)=h_slide1;
	h_data(11)=h_slide2;
	set(h_MainFig,'User',h_data,...
		'tag','vla');

end
