function varargout = view(varargin)
%VIEW   3-D graph viewpoint specification.
%   VIEW(AZ,EL) and VIEW([AZ,EL]) set the angle of the view from which an
%   observer sees the current 3-D plot.  AZ is the azimuth or horizontal
%   rotation and EL is the vertical elevation (both in degrees). Azimuth
%   revolves about the z-axis, with positive values indicating counter-
%   clockwise rotation of the viewpoint. Positive values of elevation
%   correspond to moving above the object; negative values move below.
%   VIEW([X Y Z]) sets the view angle in Cartesian coordinates. The
%   magnitude of vector X,Y,Z is ignored.
%
%   Here are some examples:
%
%   AZ = -37.5, EL = 30 is the default 3-D view.
%   AZ = 0, EL = 90 is directly overhead and the default 2-D view.
%   AZ = EL = 0 looks directly up the first column of the matrix.
%   AZ = 180 is behind the matrix.
%
%   VIEW(2) sets the default 2-D view, AZ = 0, EL = 90.
%   VIEW(3) sets the default 3-D view, AZ = -37.5, EL = 30.
%
%   [AZ,EL] = VIEW returns the current azimuth and elevation.
%
%   VIEW(T) accepts a 4-by-4 transformation matrix, such as
%   the perspective transformations generated by VIEWMTX.
%
%   T = VIEW returns the current general 4-by-4 transformation matrix.
%
%   VIEW(AX,...) uses axes AX instead of the current axes.
%
%   See also VIEWMTX, the AXES properties View, Xform.

%   Copyright 1984-2002 The MathWorks, Inc.
%   $Revision: 5.12.4.1 $

error(nargchk(0, 3, nargin));
error(nargoutchk(0, 2, nargout));
for i=1:length(varargin),
  if ~isnumeric(varargin{i}) & (i==1 & ~isAxesHandle(varargin{i}))
    error('Invalid input arguments');
  end
end

%
% determine which axes the view is to be applied to, as well as what the
% input arguments to ViewCore are going to be
%
viewArgs = {};
switch nargin,
 case 0;
  hAxes = gca;
  
 case { 1, 2 }
  if isAxesHandle(varargin{1}),
    hAxes = varargin{1};
    viewArgs = varargin(2:end);
  else
    hAxes = gca;
    viewArgs = varargin(1:end);
  end
  
 case 3
  if ~isAxesHandle(varargin{1}),
    error('First argument must be a scalar axes handle');
  else
    hAxes = varargin{1};
    viewArgs = varargin(2:end);
  end
end

%
% set the view
%
if ~isempty(viewArgs)
  ViewCore(hAxes, viewArgs{:});
end

%
% construct the return args, return the azimuth and elevation for 2 lhs args,
% otherwise, return the transformation matrix
%
switch nargout,
 case 0,
  if nargin == 0,
    varargout{1} = get(hAxes, 'XForm');
  end
  
 case 1,
  varargout{1} = get(hAxes, 'XForm');
  
 case 2,
  axView = get(hAxes, 'View');
  varargout{1} = axView(1);
  varargout{2} = axView(2);
  
end

%
%==============================================================================
% isAxesHandle - determine if an input argument is an axes handle
%
function isAxes = isAxesHandle(hAxes)

isAxes = logical(0);
if (length(hAxes) == 1) & ishandle(hAxes) & strcmp(get(hAxes,'Type'),'axes'),
  isAxes = logical(1);
end

%
%==============================================================================
% ViewCore - actual code that sets the axes view
%
function ViewCore(hAxes, arg1, arg2)

azIn     = [];
elIn     = [];
xformMat = [];

switch (nargin)

  %
  %--------------------------------------------------------
  % 2 arg - cases are:
  %   view(hAxes, 2)
  %   view(hAxes, 3)
  %   view(hAxes, [az, el])
  %   view(hAxes, T)
  %   view(hAxes, [x y z])
  %
 case 2
  [r, c] = size(arg1);
  if (r == 1) & (c == 1)
    %
    % view(2) or view(3)
    %
    switch arg1
     case 2
      azIn = 0;
      elIn = 90;

     case 3
      azIn = -37.5;
      elIn = 30;

     otherwise
      error('Single scalar argument must be 2 or 3');
    end
  elseif (r == 1) & (c == 2)
    %
    % view([az, el]
    %
    azIn = arg1(1);
    elIn = arg1(2);
  elseif (r == 4) & (c == 4)
    %
    % view(T)
    %
    xformMat = arg1;
  elseif r*c == 3
    %
    % view([x, y, z])
    %
    unit = arg1/norm(arg1);
    azIn = atan2(unit(1),-unit(2))*180/pi;
    elIn = atan2(unit(3),sqrt(unit(1)^2+unit(2)^2))*180/pi;
  else
    error('Argument must be scalar, two-vector, or 4-by-4 matrix');
  end

  %
  %--------------------------------------------------------
  % 3 args - cases are
  %   view(hAxes, az, el)
  %
 case 3
  if (length(arg1) == 1) & (length(arg2) == 1),
    azIn = arg1;
    elIn = arg2;
  else
    error('Arguments must be scalars')
  end

end

%
% there is one of two cases at this point:
%   1) the azimuth and elevation are defined
%   2) the transformation matrix is defined
%      set the transformation matrix
%
if ~isempty(xformMat),
  set(hAxes, 'XForm', xformMat);
elseif ~isempty(azIn) & ~isempty(elIn),
  set(hAxes, 'View', [azIn, elIn]);
end
