function ReturnValue=LinComb(fn,arg)

%Lincomb shows linear combinations in 2 dimensions.  It has two options.
%This first option allows the user to click on the screen for u and v and
%then enter alpha and beta.  The second option allows the user to click for
%u and v and then click to place a vector.  Alpha and beta then appear in the
%bottom window.

%    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

%	h_data(1)=h_MainFig;	:the Figure
%	h_data(2)=h_axis;	:the axes
%	h_data(3)=h_vecU;	:the plot of u
%	h_data(4)=h_vecV;	:the plot of v
%	h_data(5)=h_UScalar;	:edit alpha for top controls
%	h_data(6)=h_VScalar;	:edit beta for top controls
%	h_data(7)=h_Vec1;	:output vector display (x comp.)
%	h_data(8)=h_Vec2;	:output vector display (y comp.)
%	h_data(9)=h_VectorPlot;	:plot of output vector
%	h_data(10)=h_Uvec1;	:edit x comp for u for bottom controls
%	h_data(11)=h_Uvec2;	:edit y comp for u
%	h_data(12)=h_Vvec1;	:edit x comp for v
%	h_data(13)=h_Vvec2;	:edit y comp for u
%	h_data(14)=h_TopButton;	:button activating top controls
%	h_data(15)=h_BotButton;	:button activating bottom controls
%	h_data(16)=h_axis2;	:axis containg symbol a and b
%	h_data(17)=h_alpha;	:text box displaying alpha
%	h_data(18)=h_beta;	:text box displaying beta
%	h_data(19)=h_AlphaText;	:symbol font a (text object in h_axis2)
%	h_data(20)=h_BetaText;	:symbol font b (text object in h_axis2)


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';
	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

%Have these two vectors and pass them to the arg string as:
%[h_vector;h_arrow]

%(1)	h_vector:	plot in left window


if strcmp(fn,'arrow')

	h_vector=arg;
	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');
	
	x=xdat(length(xdat))/(xlim(2)-xlim(1));
	y=ydat(length(ydat))/(ylim(2)-ylim(1));
	
	sine=sin(9*pi/8);
	cosine=cos(9*pi/8);

	a1=([cosine (-sine);sine cosine]*[x;y]).*.1+[x;y];
	a2=([cosine sine;-sine cosine]*[x;y]).*.1+[x;y];
	

	set(h_vector,'xdata',[0 x NaN a1(1) x a2(1)].*(xlim(2)-xlim(1)),...
		    'ydata',[0 y NaN a1(2) y a2(2)].*(ylim(2)-ylim(1)));
	drawnow;	

	return;
end;
%____________________________________________________________________________

%Function: [xcoord;ycoord]=GetPoint(h_axis);

if strcmp(fn,'GetPoint')
%

%GetPoint	Gets th pointer location from the current figure and relates it
%		to the tick marks on the axis.
%
%USEAGE		[x;y]=GetPoint(h_axis);
%		x and y are the coordinates of the pointer expressed in terms of the
%		axis corresponding to the handle h_axis.  The figure handle is extracted
%		directly from the object properties of the axis.
%		column vector is passed back containing relative vector.
%
	h_axis=arg;
	h_fig=get(h_axis,'Parent');

	CurPoint=get(h_axis,'CurrentPoint');
	xlim=get(h_axis,'xlim');
	ylim=get(h_axis,'ylim');

	if CurPoint(1,1) > xlim(2)

		CurPoint(1,1) = xlim(2);

	elseif CurPoint(1,1) < xlim(1)

		CurPoint(1,1) = xlim(1);

	end;

	if CurPoint(1,2) > ylim(2)

		CurPoint(1,2) = ylim(2);

	elseif CurPoint(1,2) < ylim(1)

		CurPoint(1,2) = ylim(1);

	end;

	ReturnValue=[CurPoint(1,1);CurPoint(1,2)];
	return;
end;

%____________________________________________________________________________

%Function: CheckBox

if strcmp (fn,'CheckBox')

	h_data=get(h_MainFig,'UserData');
	h_TopBox=h_data(14);
	h_BotBox=h_data(15);

	get(h_TopBox,'value');
	get(h_BotBox,'value');

	if strcmp(arg,'top')
		
		if strcmp(get(h_data(10),'style'),'edit')
		
			lincomb('Reset','Top');
			set(h_data(20),'visible','off');
			set(h_data(19),'visible','off');

		end;
	
		set(h_TopBox,'Value',1);
		set(h_BotBox,'Value',0);
		return;
	

	else

		if strcmp(get(h_data(10),'style'),'text')

			lincomb('Reset','Bot');
			set(h_data(19),'visible','on');
			set(h_data(20),'visible','on');

		end;

		set(h_TopBox,'Value',0);
		set(h_BotBox,'Value',1);
		return;

	end;
end;

%____________________________________________________________________________

%Function: Reset

if strcmp(fn,'Reset');

	
	h_data=get(h_MainFig,'Userdata');
		
	if ~strcmp(arg,'Top') & ~strcmp(arg,'Bot')
		
		set(h_data(5:6),'string','1');

		set(h_data(7:8),'string','1');

		set(h_data(9),'xdata',[0 1],...
		'ydata',[0 1]);

		lincomb('arrow',h_data(9));

		set(h_data(3),'xdata',[0 1],...
			      'ydata',[0 0]);

		lincomb('arrow',h_data(3));

		set(h_data(4),'xdata',[0 0],...
			      'ydata',[0 1]);

		lincomb('arrow',h_data(4));

		set(h_data([10 13]),'string','1');
		set(h_data(11:12),'string','0');

		refresh;
		
		MainPos=get(h_MainFig,'pos');
		set(h_MainFig,'pos',MainPos+.001);
		set(h_MainFig,'pos',MainPos);


	elseif strcmp(arg,'Top')


		set(h_data(3),'button','lincomb(''BeginDrag'',''U'');');
		set(h_data(4),'button','lincomb(''BeginDrag'',''V'');');
		set(h_data(9),'button','');

		set(h_data(10:13),'style','text');

		alpha=get(h_data(17),'string');
		beta=get(h_data(18),'string');
		set(h_data(17:18),'visible','off');

		set(h_data(5),'style','edit',...
		'string',alpha);

		set(h_data(6),'style','edit',...
		'string',beta);

		refresh;
		
		MainPos=get(h_MainFig,'pos');
		set(h_MainFig,'pos',MainPos+.001);
		set(h_MainFig,'pos',MainPos);


	elseif strcmp(arg,'Bot')

		set(h_data(3:4),'button','');
		set(h_data(9),'button','lincomb(''BeginDrag2'');');

		set(h_data(10:13),'style','edit');

		alpha=get(h_data(5),'string');
		beta=get(h_data(6),'string');
		
		set(h_data(5:6),'style','text');

		set(h_data(17),'visible','on',...
		'string',alpha);

		set(h_data(18),'visible','on',...
		'string',beta);

		refresh;
		
		MainPos=get(h_MainFig,'pos');
		set(h_MainFig,'pos',MainPos+.001);
		set(h_MainFig,'pos',MainPos);

	end;

end;
%____________________________________________________________________________

%Function: BeginDrag

if strcmp(fn,'BeginDrag')

	set(h_MainFig,'WindowButtonUpFcn','lincomb(''EndDrag'');');

	if strcmp(arg,'U')

		set(h_MainFig,'WindowButtonMotionFcn','lincomb(''Drag'',[3;4]);');

	elseif strcmp(arg,'V')
	
		set(h_MainFig,'WindowButtonMotionFcn','lincomb(''Drag'',[4;3]);');

	end;
	return;

end;
%____________________________________________________________________________

%Function: Drag

if strcmp(fn,'Drag')

	h_data=get(h_MainFig,'User');
	h_axis=h_data(2);
	h_Vec1=h_data(7);
	h_Vec2=h_data(8);
	h_LinCombVect=h_data(9);


	CurPoint=lincomb('GetPoint',h_axis);
	set(h_data(arg(1)),'xdata',[0 CurPoint(1)],...
			'ydata',[0 CurPoint(2)]);
	lincomb('arrow',h_data(arg(1)));

	OtherVect=[get(h_data(arg(2)),'xdata');get(h_data(arg(2)),'ydata')];

	Comb=str2num(get(h_data(arg(1)+2),'string'))*CurPoint(:)+...
	     str2num(get(h_data(arg(2)+2),'string'))*OtherVect(1:2,2);

	set(h_LinCombVect,'xdata',[0 Comb(1)],...
			  'ydata',[0 Comb(2)]);

	lincomb('arrow',h_LinCombVect);

	set(h_Vec1,'string',num2str(Comb(1)));
	set(h_Vec2,'string',num2str(Comb(2)));

	set(h_data(2*arg(1)+4),'string',num2str(CurPoint(1)));
	set(h_data(2*arg(1)+5),'string',num2str(CurPoint(2)));
	return;
	
end;	
	
%____________________________________________________________________________

%Function: EndDrag

if strcmp(fn,'EndDrag')

	set(h_MainFig,'WindowButtonUpFcn','',...
	'WindowButtonMotionFcn','');

	return;

end;
%____________________________________________________________________________

%Function: BeginDrag2

if strcmp(fn,'BeginDrag2')

	set(h_MainFig,'WindowButtonUpFcn','lincomb(''EndDrag'');',...
		      'WindowButtonMotionFcn','lincomb(''Drag2'');');

	return;

end;
%____________________________________________________________________________

if strcmp(fn,'Drag2')

	h_data=get(h_MainFig,'User');
	h_axis=h_data(2);
	h_u=h_data(3);
	h_v=h_data(4);
	h_uv=h_data(9);
	h_alpha=h_data([5 17]);
	h_beta=h_data([6 18]);

	u=[get(h_u,'xdata');get(h_u,'ydata')];
	v=[get(h_v,'xdata');get(h_v,'ydata')];
	CurPoint=get(h_axis,'CurrentPoint');

	set(h_uv,'xdata',[0 CurPoint(1,1)],...
		 'ydata',[0 CurPoint(1,2)]);

	lincomb('arrow',h_uv);

	A=[u(1:2,2) v(1:2,2)];
	b=CurPoint(1,1:2)';
	AlphaBeta=A\b;

	set(h_alpha,'string',num2str(AlphaBeta(1)));
	set(h_beta,'string',num2str(AlphaBeta(2)));

	set(h_data(7),'string',num2str(CurPoint(1,1)));
	set(h_data(8),'string',num2str(CurPoint(1,2)));

	return;

end;

%____________________________________________________________________________

%Function: UpdateVects

if strcmp(fn,'UpdateVects')

	h_data=get(h_MainFig,'User');
	
	h_alpha=h_data(5);
	h_beta=h_data(6);
	h_Uvec1=h_data(10);
	h_Uvec2=h_data(11);
	h_Vvec1=h_data(12);
	h_Vvec2=h_data(13);
	h_Vect1=h_data(7);
	h_Vect2=h_data(8);

	h_UPlot=h_data(3);
	h_VPlot=h_data(4);
	h_UVPlot=h_data(9);

	alpha=str2num(get(h_alpha,'string'));
	beta=str2num(get(h_beta,'string'));

	u=[str2num(get(h_Uvec1,'string'));str2num(get(h_Uvec2,'string'))];

	v=[str2num(get(h_Vvec1,'string'));str2num(get(h_Vvec2,'string'))];

	uv=alpha*u+beta*v;

	set(h_Vect1,'string',num2str(uv(1)));
	set(h_Vect2,'string',num2str(uv(2)));

	set(h_UPlot,'xdata',[0 u(1)],...
		    'ydata',[0 u(2)]);

	set(h_VPlot,'xdata',[0 v(1)],...
		    'ydata',[0 v(2)]);

	set(h_UVPlot,'xdata',[0 uv(1)],...
		     'ydata',[0 uv(2)]);

	lincomb('arrow',h_UPlot);
	lincomb('arrow',h_VPlot);
	lincomb('arrow',h_UVPlot);

	return;

end;

%____________________________________________________________________________

%Function: init

if strcmp(fn,'init')


	delete(findobj('name','Linear Combinations'));

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

	axes(h_axis);
	hold on;

	h_vecU=plot([0 1],[0 0],'g',...
	'erasemode','xor',...
	'Button','lincomb(''BeginDrag'',''U'');');
	lincomb('arrow',h_vecU);

	h_vecV=plot([0 0],[0 1],...
	'erasemode','xor',...
	'Button','lincomb(''BeginDrag'',''V'');');
	lincomb('arrow',h_vecV);

	plot(0,0,'ko');

	theta=0:1/100:2*pi;
	x=cos(theta);
	y=sin(theta);
	plot(x,y,'k:');

	h_VectorPlot=plot([0 1],[0 1],'w',...
			'erasemode','xor');

	lincomb('arrow',h_VectorPlot);

	set(h_axis,...
		'xlim',[-1 1],...
		'ylim',[-1 1],...
		'pos',[.1 .1 .48 .8],...
		'color',[1 1 1],...
		'ycolor',[0 0 0],...
		'xcolor',[0 0 0],...
		'drawmode','fast');

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

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

	h_UScalar=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.62 .61 .08 .05],...
		'style','edit',...
		'back',[1 1 1],...
		'fore',[0 0 0],...
		'string','1',...
		'callback','LinComb(''UpdateVects'')');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.72 .61 .05 .05],...
		'style','text',...
		'back',[1 1 1],...
		'fore',[0 0 0],...
		'string','u +');

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


	h_VScalar=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.78 .61 .08 .05],...
		'style','edit',...
		'back',[1 1 1],...
		'fore',[0 0 0],...
		'string','1',...
		'callback','LinComb(''UpdateVects'')');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.88 .61 .05 .05],...
		'style','text',...
		'back',[1 1 1],...
		'fore',[0 0 0],...
		'string','v =');

	h_Vec1=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.92 .63 .07 .05],...
		'style','text',...
		'back',[1 1 1],...
		'fore',[0 0 0],...
		'string','1');

	h_Vec2=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.92 .58 .07 .05],...
		'style','text',...
		'back',[1 1 1],...
		'fore',[0 0 0],...
		'string','1');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.61 .45 .38 .1],...
		'string','Reset',...
		'callback','lincomb(''Reset'','' '');');
	
	
		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.61 .39 .38 .05],...
		'string','Enter components of u and v.',...
		'style','text',...
		'back',[1 1 1]);

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.61 .36 .38 .04],...
		'string','Drag to redefine vector',...
		'style','text',...
		'back',[1 1 1]);

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.6 .8 .4 .2],...
		'style','frame',...
		'back',[.7 .7 .7]);
			
		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.61 .73 .38 .05],...
		'back',[1 1 1],...
		'fore',[0 0 0],...
		'string','Drag to redefine u and v.',...
		'style','text'); 

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.61 .69 .38 .05],...
		'back',[1 1 1],...
		'string','Enter alpha and beta.',...
		'style','text');
	
		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.6 .19 .4 .25],...
		'back',[1 1 1],...
		'fore',[0 0 0],...
		'style','frame');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.61 .25 .05 .05],...
		'back',[1 1 1],...
		'style','text',...
		'string','u =',...
		'fore',[1 0 1]);
	
	h_Uvec1=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.67 .29 .08 .05],...
		'back',[1 1 1],...
		'style','text',...
		'string','1',...
		'callback','lincomb(''UpdateVects'');');

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

	h_Uvec2=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.67 .21 .08 .05],...
		'back',[1 1 1],...
		'style','text',...
		'string','0',...
		'callback','lincomb(''UpdateVects'');');

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

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.79 .25 .05 .05],...
		'back',[1 1 1],...
		'style','text',...
		'string','v =',...
		'fore',[0 0 1]);
	
	h_Vvec1=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.86 .29 .08 .05],...
		'back',[1 1 1],...
		'style','text',...
		'string','0',...
		'callback','lincomb(''UpdateVects'');');

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

	h_Vvec2=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.86 .21 .08 .05],...
		'back',[1 1 1],...
		'style','text',...
		'string','1',...
		'callback','lincomb(''UpdateVects'');');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.85 .2 .1 .07],...
		'back',[1 1 1],...
		'style','frame');
	 
		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.6 0 .003 .2],...
		'back',[1 1 1],...
		'style','frame');

		uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.997 0 .003 .2],...
		'back',[1 1 1],...
		'style','frame');


	h_TopButton=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.7 .9 .25 .07],...
		'string','Fix alpha and beta',...
		'style','checkbox',...
		'value',1,...
		'back',[.7 .7 .7],...
		'callback','lincomb(''CheckBox'',''top'')');

	h_BottomButton=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.7 .83 .25 .07],...
		'string','Fix u and v',...
		'style','checkbox',...
		'value',0,...
		'back',[.7 .7 .7],...
		'CallBack','lincomb(''CheckBox'',''bottom'')');
		
		axes(h_axis2);
		
	h_AlphaText=text(.15,.73,'a =',...
			'fontname','symbol',...
			'color',[0 0 0],...
			'visible','off');

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

		axes(h_axis);
	h_alpha=uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.7 .11 .1 .05],...
		'style','text',...
		'back',[1 1 1]);

	h_beta=	uicontrol(h_MainFig,...
		'units','normalize',...
		'pos',[.7 .03 .1 .05],...
		'style','text',...
		'back',[1 1 1]);
	
	h_data(1)=h_MainFig;
	h_data(2)=h_axis;
	h_data(3)=h_vecU;
	h_data(4)=h_vecV;
	h_data(5)=h_UScalar;
	h_data(6)=h_VScalar;
	h_data(7)=h_Vec1;
	h_data(8)=h_Vec2;
	h_data(9)=h_VectorPlot;
	h_data(10)=h_Uvec1;
	h_data(11)=h_Uvec2;
	h_data(12)=h_Vvec1;
	h_data(13)=h_Vvec2;
	h_data(14)=h_TopButton;
	h_data(15)=h_BottomButton;
	h_data(16)=h_axis2;
	h_data(17)=h_alpha;
	h_data(18)=h_beta;
	h_data(19)=h_AlphaText;
	h_data(20)=h_BetaText;

	set(h_MainFig,'User',h_data,...
		'tag','vla');


end
