function ReturnVal=TransAB(fn,arg);

%    TransAB: Transformation Picture for Ax=b
%    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

%If there are no input strings, initialize the gui

if nargin == 0
	fn = 'init';
end;


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

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

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

	if ~strcmp(get(h_MainFig,'name'),'Transformation Pictures Ax = b')
		h_figs=get(0,'children');
		h_MainFig = findobj(h_figs,'flat',...
				    'name','Transformaton Pictures Ax = b');

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

		if length(h_MainFig)==0
			transab('init');
			transab(fn);
			return;
		end;
	end;
end;
%____________________________________________________________________________
%Function: arrow



%	h_vector:	vector to be arrowed

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);
%
%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.
%
if strcmp(fn,'GetPoint');

	h_axis=arg;

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

	CurPoint=get(h_axis,'CurrentPoint');

	ReturnVal=CurPoint(1,1:2)';
	return;
end;
%_______________________________________________________________________________


%Function: RightRescale

if strcmp(fn,'RightRescale');

	h_data = get(h_MainFig,'User');
	h_axis = h_data(2);
	h_XMin = h_data(12);
	h_XMax = h_data(13);
	h_YMin = h_data(14);
	h_YMax = h_data(15);
	
	xlim=[eval(get(h_XMin,'string')) eval(get(h_XMax,'string'))];
	ylim=[eval(get(h_YMin,'string')) eval(get(h_YMax,'string'))];

	set(h_axis,'xlim',xlim,...
		   'ylim',ylim);

	return;

end;
	

	
%_______________________________________________________________________________

%Function: PrepareAxes

if strcmp(fn,'PrepareAxes')

	h_data		= get(h_MainFig,'User');
	h_b		= h_data(7:8);
	h_x		= h_data(9:10);
	h_axis		= h_data(1:2);

	h_Range		= get(h_axis(2),'User');
	h_Vector	= h_Range(1);
	h_RangePlot	= h_Range(2);

	h_Null		= get(h_axis(1),'User');
	h_arrows	= h_Null(1);
	h_ParaLine	= h_Null(2);
	h_NullPlot	= h_Null(3);

	Matrix=transAB('EvalMatrix');
	Range=orth(Matrix);
	NullSpace=null(Matrix);

	NullSize=size(NullSpace);

	if NullSize == [2 2];

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

		set(h_Null(1:2),'xdata',0,...
				'ydata',0);

		set(h_axis(1),'color',[1 0 0]);

		set(h_axis(2),'color',[0 0 0]);

		set(h_RangePlot,'xdata',[0 0],...
			     'ydata',[0 0],...
			     'linestyle','o',...
			     'Button',' ');

		set([h_Vector;h_RangePlot],'xdata',0,'ydata',0);

	elseif NullSize == [0 0]

		set(h_Range(3),'xdata',0,...
				  'ydata',0);

		set(h_Range(1),'xdata',[0 1],...
			       'ydata',[0 1],...
			       'Button','Transab(''BeginDrag'',[0 0]);',...
			       'color',[1 1 1]);

		transab('arrow',h_Range(1));

		set(h_Null(1:2),'xdata',0,...
				'ydata',0);

		set(h_axis(1),'color',[0 0 0]);

		axes(h_axis(1));
		set(h_NullPlot,'xdata',[0 0],...
				'ydata',[0 0],...
				'linestyle','o');

		set(h_axis(2),'color',[0 0 1]);

		set([h_NullPlot;h_RangePlot],'xdata',0,'ydata',0);
	
		Transab('EvalVectors2');		

	else

		set(h_axis,'color',[0 0 0]);

		xlim1=get(h_axis(1),'xlim');
		xlim2=get(h_axis(2),'xlim');

		RangeY=Range(2)/Range(1)*xlim1;
		set(h_RangePlot,'xdata',xlim1,...
				'ydata',RangeY,...
				'linestyle',':');

		NullY=NullSpace(2)/NullSpace(1)*xlim2;
		set(h_NullPlot,'xdata',xlim2,...
			       'ydata',NullY,...
			       'linestyle','-');

		NewVect=[.5 -.5;.5 .5]*Range(:);

		set(h_Vector,'xdata',[0 NewVect(1)],...
			     'ydata',[0 NewVect(2)],...
			     'color','m',...
			     'Button','transAB(''BeginDrag'',[2 1]);');

		transAb('arrow',h_Vector);

		transAB('EvalVectors');
	end;
	return;

end;
		
%_______________________________________________________________________________

%Function: BeginDrag

if strcmp(fn,'BeginDrag')

	NullSize=arg;

	if NullSize==[0 0];
		set(h_MainFig,'WindowButtonMotionFcn','transAB(''Drag'',[0 0]);',...
			      'WindowButtonUpFcn','transAB(''EndDrag'');');
	else

		set(h_MainFig,'WindowButtonMotionFcn','transAB(''Drag'',[2 1]);',...
			      'WindowButtonUpFcn','transAB(''EndDrag'');');
	end;
	return;
end;

%_______________________________________________________________________________

%Function: Drag

if strcmp(fn,'Drag')

	h_data=get(h_MainFig,'User');
	h_RangeAxis=get(h_data(2),'User');
	NullSize=arg;
	CurPoint=get(h_data(2),'CurrentPoint');
	

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

	transAB('arrow',h_RangeAxis(1));

	if NullSize==[0 0]

		transAB('EvalVectors2');
	else
		transAB('EvalVectors');
	end;

	return;

end;
%_______________________________________________________________________________

%Function: EndDrag

if strcmp(fn,'EndDrag')

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

end;

%_______________________________________________________________________________

%Function: EvalVectors2

if strcmp(fn,'EvalVectors2')

	h_data=get(h_MainFig,'User');
	h_axis=h_data(1);
	h_axis2=h_data(2);
	h_bx=h_data(7);
	h_by=h_data(8);
	h_Xx=h_data(9);
	h_Xy=h_data(10);

	h_Null=get(h_axis,'User');
	h_arrows=h_Null(1);

	h_Range=get(h_axis2,'User');
	h_vector=h_Range(1);

	a=Transab('EvalMatrix');
	xdata=get(h_vector,'xdata');
	ydata=get(h_vector,'ydata');
	
	x=a\[xdata(2);ydata(2)];
	set(h_arrows,'xdata',[0 x(1)],...
		     'ydata',[0 x(2)]);

	set(h_bx,'string',num2str(xdata(2)));
	set(h_by,'string',num2str(ydata(2)));
	set(h_Xx,'string',num2str(x(1)));
	set(h_Xy,'string',num2str(x(2)));

	transab('arrow',h_arrows);
	return;

end;
%_______________________________________________________________________________

%Function: EvalVectors

if strcmp(fn,'EvalVectors')

	h_data=get(h_MainFig,'User');
	h_axis=h_data(1);
	h_axis2=h_data(2);
	h_bx	=	h_data(7);
	h_by	=	h_data(8);
	h_Xx	=	h_data(9);
	h_Xy	=	h_data(10);
	
	
	h_Null		= get(h_axis,'User');
	h_arrows	= h_Null(1);
	h_ParaLine	= h_Null(2);
	h_NullPlot	= h_Null(3);
	
	h_Range		= get(h_axis2,'User');
	h_vector	= h_Range(1);
	h_RangePlot	= h_Range(2);
	h_ProjVect	= h_Range(3);

	xlim=get(h_axis,'xlim');
	
	sine=sin(9*pi/8);
	cosine=cos(9*pi/8);

	b1=[get(h_vector,'xdata');get(h_vector,'ydata')];
	v=[get(h_RangePlot,'xdata');get(h_RangePlot,'ydata')];
	
	ProjMat=v(1:2,2)*inv(v(1:2,2)'*v(1:2,2))*v(1:2,2)';
		
	b=ProjMat*b1(1:2,2);

	a1=[cosine -sine;sine cosine]*b*.1+b;
	a2=[cosine sine;-sine cosine]*b*.1+b;
	

	set(h_ProjVect,'xdata',[0 b(1) NaN a1(1) b(1) a2(1)],...
		       'ydata',[0 b(2) NaN a1(2) b(2) a2(2)]);

	set(h_bx,'string',num2str(b1(1,2)));
	set(h_by,'string',num2str(b1(2,2)));

	a=transAB('EvalMatrix');
	NullSpace=null(a);

	x=[a(1,1:2);NullSpace']\[b(1);0];

	set(h_Xx,'string',x(1));
	set(h_Xy,'string',x(2));

	x(1:2,2)=x+NullSpace(:);
	x(1:2,3)=x(1:2,1)-NullSpace(:);
	x(1:2,4)=x(1:2,1)+.5*NullSpace(:);
	x(1:2,5)=x(1:2,1)-.5*NullSpace(:);

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

	xdata=[0 x(1,1) NaN a1(1,1) x(1,1) a2(1,1) NaN 0 x(1,2) NaN a1(1,2) x(1,2) a2(1,2) NaN 0 x(1,3) NaN a1(1,3) x(1,3) a2(1,3) NaN 0 x(1,4) NaN a1(1,4) x(1,4) a2(1,4) NaN 0 x(1,5) NaN a1(1,5) x(1,5) a2(1,5)];
	ydata=[0 x(2,1) NaN a1(2,1) x(2,1) a2(2,1) NaN 0 x(2,2) NaN a1(2,2) x(2,2) a2(2,2) NaN 0 x(2,3) NaN a1(2,3) x(2,3) a2(2,3) NaN 0 x(2,4) NaN a1(2,4) x(2,4) a2(2,4) NaN 0 x(2,5) NaN a1(2,5) x(2,5) a2(2,5)];
	set(h_arrows,'xdata',xdata,...
		     'ydata',ydata);

	y=NullSpace(2)/NullSpace(1)*xlim+(x(2)-NullSpace(2)/NullSpace(1)*x(1));

	set(h_ParaLine,'xdata',xlim,...
		       'ydata',y);

	return;

end;

%_______________________________________________________________________________

%Function: EvalMatrix
%
%(3)	h_data11:	element (1,1)
%(4)	h_data12:	element (1,2)
%(5)	h_data21:	element (2,1)
%(6)	h_data22:	element (2,2)
% 

if strcmp(fn,'EvalMatrix')

	h_data=get(h_MainFig,'UserData');
	h_data11=h_data(3);
	h_data12=h_data(4);
	h_data21=h_data(5);
	h_data22=h_data(6);

	a(1,1)=eval(get(h_data11,'string'));
	a(1,2)=eval(get(h_data12,'string'));
	a(2,1)=eval(get(h_data21,'string'));
	a(2,2)=eval(get(h_data22,'string'));
	
	ReturnVal=a;
	return;
end;
%_______________________________________________________________________________

%Function: init

if strcmp('init',fn)



	delete(findobj('name','Transformation Pictures Ax = b'));

	h_fig=	figure('Name','Transformation Pictures Ax = b',...
		'NumberTitle','off');

	h_axis=	axes('position',[.07 .4 .4 .5]);

	h_axis2=axes('position',[.57 .4 .4 .5]);

	set(h_axis,...
		'XLim',[-1.5 1.5],'YLim',[-1.5 1.5],...
		'User',0,...
		'drawmode','fast');

		
	set(h_axis2,...
		'XLim',[-1.5 1.5],'YLim',[-1.5 1.5],...
		'User',0,...
		'drawmode','fast');

	
	axes(h_axis);
	hold on;
	h_arrows=plot(0,0,'y','erasemode','xor');
	h_ParaLine=plot(0,0,'w','erasemode','xor');
	h_NullSpace=plot(0,0,'r');
	
	axes(h_axis2);	
	hold on;
	h_Vector=plot(0,0,'m','erasemode','xor');
	h_Range=plot(0,0,'c');
	h_ProjVector=plot(0,0,'color',[1 1 0],'linewidth',2,'erasemode','xor');

%Now the gui

		uicontrol(h_fig,...
		'position',[0 0 1 .3],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');

		uicontrol(h_fig,...
		'position',[.5 .3 .003 .7],...
		'BackgroundColor',[1 1 1],...
		'ForeGroundColor',[1 1 1],...
		'units','normalize',...
		'style','frame');
	
		uicontrol(h_fig,...
		'position',[.5 0 .003 .3],...
		'BackgroundColor',[0 0 0],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');

		uicontrol(h_fig,...
		'position',[.01 .23 .25 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text',...
		'string','Enter matrix A');
	
		
		uicontrol(h_fig,...
		'pos',[.52 .05 .1 .2],...
		'units','normal',...
		'string','Plot',...
		'CallBack','transab(''PrepareAxes'');');
	
	h_data11=uicontrol(h_fig,...
		'position',[.03 .15 .08 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundcolor',[0 0 0],...
		'units','normalize',...
		'style','edit',...
		'string','0');

		uicontrol(h_fig,...
		'position',[.02 .14 .1 .07],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');
	
	h_data12=uicontrol(h_fig,...
		'position',[.14 .15 .08 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundcolor',[0 0 0],...
		'units','normalize',...
		'style','edit',...
		'string','0');

		uicontrol(h_fig,...
		'position',[.13 .14 .1 .07],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');

	h_data21=uicontrol(h_fig,...
		'position',[.03 .07 .08 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundcolor',[0 0 0],...
		'units','normalize',...
		'style','edit',...
		'string','0');

		uicontrol(h_fig,...
		'position',[.02 .06 .1 .07],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');
	
	h_data22=uicontrol(h_fig,...
		'position',[.14 .07 .08 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundcolor',[0 0 0],...
		'units','normalize',...
		'style','edit',...
		'string','0');

		uicontrol(h_fig,...
		'position',[.13 .06 .1 .07],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');

	uicontrol(h_fig,...
		'position',[.28 .23 .20 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text',...
		'string','Enter Min/Max');

		uicontrol(h_fig,...
		'position',[.28 .14 .08 .07],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');

	h_XMin=	uicontrol(h_fig,...
		'position',[.29 .15 .06 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','edit',...
		'string','-1.5',...
		'Callback','transAB(''RightRescale'')');

		uicontrol(h_fig,...
		'position',[.4 .14 .08 .07],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');

	h_XMax=	uicontrol(h_fig,...
		'position',[.41 .15 .06 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','edit',...
		'string','1.5',...
		'Callback','transab(''RightRescale'')');

		uicontrol(h_fig,...
		'position',[.28 .06 .08 .07],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');

	h_YMin=	uicontrol(h_fig,...
		'position',[.29 .07 .06 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','edit',...
		'string','-1.5',...
		'Callback','transab(''RightRescale'')');

		uicontrol(h_fig,...
		'position',[.4 .06 .08 .07],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','frame');

	h_YMax=	uicontrol(h_fig,...
		'position',[.41 .07 .06 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','edit',...
		'string','1.5',...
		'Callback','transab(''RightRescale'')');

		uicontrol(h_fig,...
		'position',[.37 .15 .029 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text',...
		'string','X');
		
		uicontrol(h_fig,...
		'position',[.37 .06 .029 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text',...
		'string','Y');


%*************************************************

		uicontrol(h_fig,...
		'position',[.87 .23 .12 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text',...
		'string','b');

	h_bx=	uicontrol(h_fig,...
		'position',[.87 .15 .12 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text');

	h_by=	uicontrol(h_fig,...
		'position',[.87 .1 .12 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text');


		uicontrol(h_fig,...
		'position',[.63 .23 .22 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text',...
		'string','x');

	h_Xx=	uicontrol(h_fig,...
		'position',[.63 .15 .22 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text');

	h_Xy=	uicontrol(h_fig,...
		'position',[.63 .10 .22 .05],...
		'BackGroundColor',[1 1 1],...
		'ForeGroundColor',[0 0 0],...
		'units','normalize',...
		'style','text');





%(1)	h_axis:		Left hand axis
%(2)	h_axis2:	Right hand axis
%(3)	h_data11:	element (1,1)
%(4)	h_data12:	element (1,2)
%(5)	h_data21:	element (2,1)
%(6)	h_data22:	element (2,2)
%(7)	h_Nx:		X component of nullspace
%(8)	h_Ny:		Y component of nullspace
%(9)	h_Rx:		X component of range
%(10)	h_Ry:		Y component of range
%	h_MainFig:	Main figure

	h_data(1)   	=	h_axis;
	h_data(2)   	=	h_axis2;
	h_data(3)   	=	h_data11;
	h_data(4)   	=	h_data12;
	h_data(5)   	=	h_data21;
	h_data(6)   	=	h_data22;
	h_data(7)   	=	h_bx;
	h_data(8)   	=	h_by;
	h_data(9)   	=	h_Xx;
	h_data(10)  	=	h_Xy;
	h_data(12)  	=	h_XMin;
	h_data(13)  	=	h_XMax;
	h_data(14)  	=	h_YMin;
	h_data(15)  	=	h_YMax;

	
	h_NullAxis(1)	=	h_arrows;
	h_NullAxis(2)	=	h_ParaLine;
	h_NullAxis(3)	=	h_NullSpace;

	h_RangeAxis(1)  =	h_Vector;
	h_RangeAxis(2)	=	h_Range;
	h_RangeAxis(3)	=	h_ProjVector;

	set(h_axis,'User',h_NullAxis);
	set(h_axis2,'User',h_RangeAxis);
	set(h_fig,'UserData',h_data,...
		    'tag','vla');
end;

