function [x,y,z,xi,yi] = improfile(xa,ya,a,xi,yi,n,method)
%IMPROFILE Extract data along a path in an image.
%	C = IMPROFILE prompts you to define the desired path using the
%	mouse in the current figure.  The image values C along the path
%	are returned. Click at multiple points to define a multi-segment
%	path.  Left mouse button adds points to a multiple line path. 
%	Use right mouse button (shift-click on the Macintosh) or RETURN to
%	add the final point. IMPROFILE without image data only works
%	when the current axis contains an image. C = IMPROFILE(N)
%	returns N points along the selected path.
%
%	C = IMPROFILE(I,Xi,Yi,N) returns N image values along the 
%	path (Xi,Yi).  If N is omitted, a value for each pixel along
%	path is returned.
%
%	C = IMPROFILE(x,y,I,Xi,Yi) or C = IMPROFILE(x,y,I,Xi,Yi,N) 
%	accounts for non-default axis limits.  
%	[X,Y,C,Xi,Yi] = IMPROFILE(...) returns the (X,Y) position along
%	the path and the selected points (Xi,Yi). PLOT3(X,Y,C) can be 
%	used to plot the results.
%
%	Without lefthand side arguments, IMPROFILE(...) plots the image
%	improfile in a separate figure.  NOTE: X and Y are returned in
%	pixel coordinates where the pixel values are defined in the
%	center of each pixel.
%
%	Use a trailing method argument to specify the interpolation
%	method used, IMPROFILE(...,'method').  Possiblities are
%	'bilinear','bicubic', and 'nearest'.  'bilinear' is the
%	the default for intensity images, 'nearest' is the
%	default for indexed images.
%
%	See also IMPIXEL.

%	Copyright (c) 1993 by The MathWorks, Inc.
%	$Revision: 1.18 $  $Date: 1993/09/24 22:01:14 $

% Set defaults for flags.
getn = 1;    % Determine number of points from profile if true.
getprof = 0; % Get profile from user via mouse if true also get data from image.
getmethod = 1; % Determine method from data if true.
getcoords = 1; % Determine axis coordinates if true.

% Determine which IMAGE coordinate system is being used.
s = [version '    ']; k = find(s<46 & s>58);
if ~isempty(k), s = s(1:min(k)); end
[ver,count,msg,next] = sscanf(s,'%f',1);
if ver > 4.1,
  useNew = 1;
elseif ver < 4.1,
  useNew = 0;
else
  if s(next)>='a', useNew = 1; else useNew = 0; end
end

if nargin==0, % improfile
  getprof = 1; getcoords = 0;

elseif nargin==1, % improfile(n) or improfile('method')
  if isstr(xa), method = xa; getmethod = 0; else n = xa; getn = 0; end
  getprof = 1; getcoords = 0;

elseif nargin==2, % improfile(n,'method')
  if isstr(ya),
    method = ya; n = xa; getn = 0; getmethod = 0;
  else 
    error('Wrong number of arguments or unknown interpolation method.');
  end
  getprof = 1; getcoords = 0;

elseif nargin==3, % improfile(a,xi,yi)
  xi = ya; yi = a; a = xa;
  
elseif nargin==4, % improfile(a,xi,yi,n) or improfile(a,xi,yi,'method')
  if isstr(xi), method = xi; getmethod = 0; else n = xi; getn = 0; end
  xi = ya; yi = a; a = xa;

elseif nargin==5, % improfile(x,y,a,xi,yi) or improfile(a,xi,yi,n,'method')
  if isstr(yi), 
    method = yi; n = xi; getn = 0; getmethod = 0;
    xi = ya; yi = a; a = xa;
  else
    getcoords = 0;
  end

elseif nargin==6, % improfile(x,y,a,xi,yi,n) or improfile(x,y,a,xi,yi,'method')
  if isstr(n), method = n; getmethod - 0; else getn = 0; end
  getcoords = 0;

elseif nargin==7, % improfile(x,y,a,xi,yi,n,'method')
  getdata = 0; getprof = 0; getn = 0;
  if ~isstr(method), 
    error('Method must be ''bilinear'',''bicubic'', or ''nearest''.');
  end
  getcoords = 0; getmethod = 0;
end

if ~getn,
  if n<2, error('N must be > 1.'); end
end

if getcoords,
  if useNew,
    xa = [1 size(a,2)];
    ya = [1 size(a,1)];
  else
    xa = [1 size(a,2)+1];
    ya = [1 size(a,1)+1];
  end
end

if getprof, % Get profile from user if necessary using data from image
  [xa,ya,a,state] = getimage;
  if max(size(a))==1, error('Can''t get profile of 1-by-1 image.'); end
  if ~state, error('Requires an image in the current axis.'); end
  prof = getline(gcf); % Get profile from user
else
  if max(size(a))==1, error('Can''t get profile of 1-by-1 image.'); end
  if prod(size(xi))~=prod(size(yi)),
    error('Xi and Yi must have the same number of points');
  end
  prof = [xi(:) yi(:)]; % [xi yi]
end

if getmethod,
  if isind(a), method = 'nearest'; else method = 'bilinear'; end
end

% Parametric distance along segments
s = [0;cumsum(sqrt(sum((diff(prof).^2)')'))];

[ma,na] = size(a);
xmin = min(min(xa)); ymin = min(min(ya));
xmax = max(max(xa)); ymax = max(max(ya));
if useNew
  dx = max( (xmax-xmin)/(na-1), eps );
  dy = max( (ymax-ymin)/(ma-1), eps );
else
  dx = max( (xmax-xmin)/na, eps );
  dy = max( (ymax-ymin)/ma, eps );
end

if getn,
  d = abs(diff(prof./(ones(size(prof,1),1)*[dx dy])));
  n = max(sum(max(ceil(d)')),2); % In pixel coordinates
end

% Interpolation points along segments
profi = interp1(s,prof,(0:n-1)*max(s)/(n-1));

if useNew,
  xxa = xmin:dx:xmax;
  yya = ymin:dy:ymax;

  % Image values along interpolation points
  x1 = max(xxa(1),min(profi(:,1),xxa(length(xxa))));
  y1 = max(yya(1),min(profi(:,2),yya(length(yya))));
  z1 = interp2(xxa,yya,a,x1,y1,method);
else
  % Fix-up coordinates to deal with coordinates extending from pixel
  % boundaries rather than pixel centers.
  xxa = (xmin+dx/2):dx:(xmax-dx/2);
  yya = (ymin+dy/2):dy:(ymax-dy/2);

  % Image values along interpolation points
  x1 = max(xxa(1),min(profi(:,1),xxa(length(xxa))));
  y1 = max(yya(1),min(profi(:,2),yya(length(yya))));
  z1 = interp2(xxa,yya,a,x1,y1,method);
end

if nargout == 0 % plot it
   oldgcf = gcf;
   if getprof,
      h = get(0,'children');
      fig = 0;
      for i=1:length(h),
        if strcmp(get(h(i),'name'),'Profile'),
           fig = h(i);
        end
      end
      if ~fig, % Create new window
        fig = figure('Name','Profile');
      end
      figure(fig)
   else
      fig = gcf;
   end
   if length(prof)>2,
     plot3(x1,y1,z1), set(gca,'ydir','reverse');
     xlabel X, ylabel Y
   else
     plot(sqrt((x1-min(x1)).^2+(y1-min(y1)).^2),z1)
     xlabel('Distance along profile')
   end
elseif nargout == 1
   x = z1;
else
   x = x1;
   y = y1;
   z = z1;
   xi = prof(:,1);
   yi = prof(:,2);
end
