%2-dimensional vector plotter with projection and dot product
clear all;
%The following code gets user input for length and angle of two vectors

options.WindowStyle='normal'; %Allows user to manipulate windows while ...
                                %waiting for user input
prompt={'Length of First Vector','Angle (deg) of First Vector (V1)',...
    'Length of Second Vector','Angle (deg) of Second Vector (V2)'};
title1='Vector Lengths and Angles';
dims=[1,70];
definput={'4','45','2','90'};
params=inputdlg(prompt,title1,dims,definput,options);
    vec1_length=str2num(char(params(1)));
    vec1_angle=(pi/180)*str2num(char(params(2)));
    if vec1_angle<0;
        vec1_angle=vec1_angle+2*pi;
    end;
    vec2_length=str2num(char(params(3)));
    vec2_angle=(pi/180)*str2num(char(params(4)));
    if vec2_angle<0;
        vec2_angle=vec2_angle+2*pi;
    end;
% Sets the start and end points of the two vectors
vec1_start = [0 0];
vec1x=vec1_length*cos(vec1_angle);
vec1y=vec1_length*sin(vec1_angle);
vec1_end = [vec1x vec1y];
vec1 = vec1_end-vec1_start;
vec2_start = [0 0];
vec2x=vec2_length*cos(vec2_angle);
vec2y=vec2_length*sin(vec2_angle);
vec2_end = [vec2x vec2y];
vec2 = vec2_end-vec2_start;
biggervec=max([vec1_length,vec2_length]); %Determines which vector is...
                                            %longer (used later to set
                                            %limits for zoomed-in view

% The following code draws the two vectors using the "quiver" command.
% The quiver command draws vectors as arrows, so quiver(x0,y0,xcomp,ycomp)
% draws an arrow starting at x0,y0 with horizontal component xcomp and
% vertical component ycomp
figure(1); % Opens figure window
quiver(vec1_start(1),vec1_start(2),vec1(1),vec1(2),'AutoScale','off',...
    'MaxHeadSize',0.5*biggervec/vec1_length,'Color','k');
hold on; % Allows multiple vectors on same plot
quiver(vec2_start(1),vec2_start(2),vec2(1),vec2(2),'AutoScale','off',...
    'MaxHeadSize',0.5*biggervec/vec2_length,'Color','k');
grid on; % Makes horizontal and vertical grid lines

%Using the longer vector to set the plot limits
plotlim=ceil(2*biggervec);
axis([-plotlim  plotlim -plotlim  plotlim]);
daspect([1 1 1]); % Makes sure plot remains square (so perpendicular lines
                    % appear with 90-deg angle to user)

% Labels vector 1 and vector 2, prints lengths on plot, and prints
% initial title for graph (the title will change as lines are drawn)
text(vec1_end(1),vec1_end(2), '   V1');
text(vec2_end(1),vec2_end(2), '   V2');
H1=text(0.5*plotlim,0.6*plotlim,['V1 length=',num2str(vec1_length)]);
H2=text(0.5*plotlim,0.5*plotlim,['V2 length=',num2str(vec2_length)]);
title(['Two Vectors Separated by ',num2str((180/pi)*abs(vec1_angle...
    -vec2_angle)),' deg' ]);
pause(3); % Gives the user a few seconds to look at the two vectors

% The following code gets user input for which of the two vectors will be
% projected onto the direction of the other
prompt={'Project Vector 1 or 2?'};
title2='Vector to Project';
dims=[1,60];
definput={'1'}; % Default to project vector 1 onto vector 2
params=inputdlg(prompt,title2,dims,definput,options);
    numvecproj=str2num(char(params(1)));

% The following code assigns the appropriate angle, length, and start/end
% points for the projected vector and the non-projected vectors
if numvecproj==1;
    numvecnoproj=2;
    projvec=vec1;
    projvec_angle=vec1_angle;
    projvec_length=vec1_length;
    projvec_start=vec1_start;
    projvec_end=vec1_end;
    noprojvec=vec2;
    noprojvec_angle=vec2_angle;
    noprojvec_length=vec2_length;
    noprojvec_start=vec2_start;
    noprojvec_end=vec2_end;
else
    numvecproj=2;
    numvecnoproj=1;
    projvec=vec2;
    projvec_angle=vec2_angle;
    projvec_length=vec2_length;
    projvec_start=vec2_start;
    projvec_end=vec2_end;
    noprojvec=vec1;
    noprojvec_angle=vec1_angle;
    noprojvec_length=vec1_length;
    noprojvec_start=vec1_start;
    noprojvec_end=vec1_end;
end;

 theta=projvec_angle-noprojvec_angle; % Finds the ngle between the vectors
 
 % The following code determines the angle of the perpendicular line from
 % the tip of the vector being projected to the non-projected vector 
 if theta>=0 & theta<=pi;
        perpangle=noprojvec_angle-pi/2;
 end;
 if theta>pi & theta<=2*pi;
        perpangle=noprojvec_angle+pi/2;
 end;
 if theta<=0 & theta>=-pi;
        perpangle=noprojvec_angle+pi/2;
 end;
 if theta<-pi & theta>=-2*pi;
        perpangle=noprojvec_angle-pi/2;
 end;

 % The following code draws a dashed line along the direction of the non-
 % projected vector in 20 steps (so user can see line being drawn)
 title(['Extend line along V',num2str(numvecnoproj),' onto which V',...
     num2str(numvecproj),' will be projected']);
 for count=1:19;
      projlength=projvec_length*cos(theta);
      linend=2*(count/20)*noprojvec_end;
      linstart=-linend;
      H3=plot([linstart(1),linend(1)],[linstart(2),linend(2)],...
          'LineStyle','--','Color','k');
      pause(0.3);
      delete(H3)
 end;
 
 % The following code draws the completed dashed line along the
 % direction of the non-projected vector 
 linend=2*noprojvec_end;
 linstart=-linend;
 plot([linstart(1),linend(1)],[linstart(2),linend(2)],...
          'LineStyle','--','Color','k');
 pause(2); % Gives the user a few seconds to see the extended line along
            % the direction of the non-projected vector
            
 % The following code zooms in on the end of the projected vector and draws
 % a dotted line perpendicular to the non-projected vector in 20 steps (so
 % the user can see the perpendicular line being drawn)
 title(['Drop perpendicular from end of V',num2str(numvecproj),...
     ' onto direction of V',num2str(numvecnoproj)]);
 lineprojstart=projvec_end;
 lineprojlength=abs(norm(projvec)*sin(theta));
 centerpoint=[lineprojstart(1),lineprojstart(2)];
 delete(H1);
 delete(H2);
 for count=1:20;
    lineprojend=projvec_end+(count/20)*lineprojlength*[cos(perpangle),...
        sin(perpangle)];
     plot([lineprojstart(1),lineprojend(1)],[lineprojstart(2),lineprojend(2)],...
         'LineStyle',':','Linewidth',1,'Color','k');
     zoomlimit=2*abs(projlength);
     axis([centerpoint(1)-zoomlimit centerpoint(1)+zoomlimit...
         centerpoint(2)-zoomlimit centerpoint(2)+zoomlimit]);
     daspect([1 1 1]);
     pause(0.35);
end;

plot([noprojvec_start(1),lineprojend(1)],[noprojvec_start(2),lineprojend(2)],...
        'Linewidth',1,'Color','k');

% The following code zooms out to the original view and prints the values
% of the projection and other data onto the plot

axis([-plotlim  plotlim    -plotlim  plotlim],'equal'); 
H1=text(0.7*plotlim,0.4*plotlim,['V1 length=',num2str(vec1_length)]);
H2=text(0.7*plotlim,0.3*plotlim,['V2 length=',num2str(vec2_length)]);

title('Length of Projection and Inner Product');
text(-plotlim,0.9*plotlim,['Projection of V',num2str(numvecproj),...
    ' onto direction of V',num2str(numvecnoproj),' has length ',...
    num2str(projlength,3)]);
text(-plotlim,0.8*plotlim,['So taking ',num2str(projvec_length),' steps in' ...
    ' direction of V',num2str(numvecproj)]);
text(-plotlim,0.7*plotlim,[' gets you ',num2str(projlength,3),...
     ' steps in direction of V',num2str(numvecnoproj)]);
if projlength<0;
    text(-plotlim,0.6*plotlim,['Negative value means projection is '...
        'in opposite direction of V',num2str(numvecnoproj)]);
end;

text(-plotlim,-0.8*plotlim,['Multiplying the projection length by the length of V',...
    num2str(numvecnoproj),' gives ',num2str(projlength*norm(noprojvec),3)]);
text(-plotlim,-0.9*plotlim,[' and the inner product V',num2str(numvecproj),...
    '*V',num2str(numvecnoproj),' has value ',num2str(vec1*vec2',3)]);
