function zi = griddata1 (x, y, z, xi, yi, sr, ppq, expon)
					
% griddata1 -- 2-d data gridder.
%  griddata1(N, sr, ppq, expon) demonstrates itself.
%   Defaults: 100, inf, 1, and 1, respectively.
%  griddata1(x, y, z, xi, yi, sr, ppq, expon) is an inverse-
%   distance 2-d data gridder, which is guided by the search-
%   radius sr (default = inf), the points-per-quadrant ppq
%   (default = 1), and the exponent expon (default = 1).
%   The search-radius is the maximum distance permitted
%   between an interpolated position and the qualifying
%   data-points.  The points-per-quadrant is the maximum
%   number of (x, y) points to be used in each of the four
%   quadrants surrounding the corresponding (xi, yi) position.
%   The exponent for inverse-distance weighting defaults to 1,
%   denoting the simple reciprocal.  Invalid interpolates are
%   marked by NaN.
%  griddata1(x, y, z, xi, yi, [sr, ppq, expon]) is an
%   alternative syntax, in closer keeping with the "method"
%   syntax of the Matlab "griddata" function.

%  This began as John Evans' "gridgen_griddata" version
%   of a Rich Signell routine.  Cleaned-up by Denham to be
%   stand-alone, more versatile, and self-demonstrating.
 
% Modifications (Denham):
%
% Copyright (C) 2000 Dr. Charles R. Denham, ZYDECO.
%  All Rights Reserved.
%   Disclosure without explicit written consent from the
%    copyright owner does not constitute publication.
 
% Version of 20-Jul-2000 13:44:52.
% Updated    24-Jul-2000 11:12:17.

DEFAULT_SR = inf;    % Infinite search-radius.
DEFAULT_PPQ = 1;     % Nearest point in each quadrant.
DEFAULT_EXPON = 1;   % Very shallow unit-response.

if nargin < 1, x = 'demo'; help(mfilename), end

if isequal(x, 'demo'), x = 100; end

if isstr(x), x = eval(x); end

if length(x) == 1
	sr = DEFAULT_SR;
	ppq = DEFAULT_PPQ;
	expon = DEFAULT_EXPON;
	if nargin > 1, sr = y; end, if ischar(sr), sr = eval(sr); end
	if nargin > 2, ppq = z; end, if ischar(ppq), ppq = eval(ppq); end
	if nargin > 3, expon = xi; end
	if ischar(expon), expon = eval(expon); end
	n = x;
	x = rand(n, 1);
	y = rand(size(x));
	z = x+y;
	NGRID = 10;
	g = (0:NGRID)/NGRID;
	[xi, yi] = meshgrid(g, g);
	tic
	result = feval(mfilename, x, y, z, xi, yi, sr, ppq, expon);
	disp([' ## Elapsed time: ' int2str(round(toc)) ' s'])
	hold off
	try, set(gcf, 'Renderer', 'zbuffer'), catch, end
	surf(xi, yi, result)
	hold on
	plot3(x, y, z, '*k')
	hold off
	mfile = strrep(mfilename, '_', '\_');
	title([mfile ' ' int2str(n) ' ' num2str(sr) ' ' int2str(ppq) ...
			' ' num2str(expon)])
	xlabel x, ylabel y, zlabel z
	try, rotate3d on, catch, end
	return
end

if nargin  == 6 & length(sr) > 1
	for i = 1:length(sr), v{i} = sr(i); end
	zi = feval(mfilename, x, y, z, xi, yi, v{:});
	return
end

if nargin < 5, help(mfilename), return, end
if nargin < 6, sr = DEFAULT_SR; end
if nargin < 7, ppq = DEFAULT_PPQ; end
if nargin < 8, ppq = DEFAULT_EXPON; end

x = x(:); y = y(:); z = z(:);

search_radius = sr;
points_per_quadrant = max(ppq, 1);

n = length(xi(:));

% Loop through one grid-point at a time.

for k = 1:n
	
	% Locate the data lying within the search-radius,
	%  applied independently to x and y, rather than
	%  to actual radial distance.

	near_inds = find ( (abs(x-xi(k)) <= search_radius) & ...
		(abs(y-yi(k)) <= search_radius) );
	nearx = x(near_inds)-xi(k); 
	neary = y(near_inds)-yi(k);
	nearz = z(near_inds);
	
	quad1_inds = find ( (nearx>=0) & (neary>=0) );
	quad1x = nearx(quad1_inds); 
	quad1y = neary(quad1_inds);
	quad1z = nearz(quad1_inds);
	
	quad2_inds = find ( (nearx<0) & (neary>=0) );
	quad2x = nearx(quad2_inds); 
	quad2y = neary(quad2_inds);
	quad2z = nearz(quad2_inds);
	
	quad3_inds = find ( (nearx<0) & (neary<0) );
	quad3x = nearx(quad3_inds); 
	quad3y = neary(quad3_inds);
	quad3z = nearz(quad3_inds);
	
	quad4_inds = find ( (nearx>=0) & (neary<0) );
	quad4x = nearx(quad4_inds); 
	quad4y = neary(quad4_inds);
	quad4z = nearz(quad4_inds);
	
	% Select up to the maximum number per quadrant.

	if ( ~isempty(quad1_inds) )
		ranges_quad1 =  sqrt(quad1x.^2 + quad1y.^2);
		[sorted_range_quad1, range_inds] = sort(ranges_quad1);
		closest_quad1_inds = ...
			range_inds([1:1:min(length(range_inds),points_per_quadrant)]);
	else
		ranges_quad1 = [];
		closest_quad1_inds = [];
	end
	 
	if ( ~isempty(quad2_inds) )
		ranges_quad2 =  sqrt(quad2x.^2 + quad2y.^2);
		[sorted_range_quad2, range_inds] = sort(ranges_quad2);
		closest_quad2_inds = ...
			range_inds([1:1:min(length(range_inds),points_per_quadrant)]);
	else
		ranges_quad2 = [];
		closest_quad2_inds = [];
	end
	 
	if ( ~isempty(quad3_inds) )
		ranges_quad3 =  sqrt(quad3x.^2 + quad3y.^2);
		[sorted_range_quad3, range_inds] = sort(ranges_quad3);
		closest_quad3_inds = ...
			range_inds([1:1:min(length(range_inds),points_per_quadrant)]);
	else
		ranges_quad3 = [];
		closest_quad3_inds = [];
	end
	 
	if ( ~isempty(quad4_inds) )
		ranges_quad4 =  sqrt(quad4x.^2 + quad4y.^2);
		[sorted_range_quad4, range_inds] = sort(ranges_quad4);
		closest_quad4_inds = ...
			range_inds([1:1:min(length(range_inds),points_per_quadrant)]);
	else
		ranges_quad4 = [];
		closest_quad4_inds = [];
	end

	% Bundle all the qualifying data together.

	closest_ranges = [ranges_quad1(closest_quad1_inds); ...
					ranges_quad2(closest_quad2_inds); ...
					ranges_quad3(closest_quad3_inds); ...
					ranges_quad4(closest_quad4_inds); ];
				  
	closest_z = [quad1z(closest_quad1_inds); ...
					quad2z(closest_quad2_inds); ...
					quad3z(closest_quad3_inds); ...
					quad4z(closest_quad4_inds); ];

	% Use inverse-distance weighting with the nearest points
	%  in each quadrant. If none, the result is NaN.
	
	if ( isempty(closest_ranges) )
		zi(k) = NaN;
	else
		inv_ranges = closest_ranges .^ (-expon);
		zi(k) = sum ( ( inv_ranges ./ sum(inv_ranges) ) .* closest_z );
	end
		 
end

zi = reshape(zi, size(xi));
