function zi = triterp(tri, x, y, z, xi, yi)

% triterp -- Linear interpolation on triangles.
%  triterp(tri, x, y, z, xi, yi) interpolates z(x, y)
%   at points (xi, yi), using the triangulation
%   tri.  If tri is empty, the Matlab "delaunay"
%   routine is called to compute it.
%  triterp(x, y, z, xi, yi) calls triterp([], x, y, z, xi, yi).

%  This routine is cloned directly from the "linear"
%  sub-function found in "griddata.m".

% Modified blocks below are marked by "ZYDECO":
% Copyright (C) 1999 Dr. Charles R. Denham, ZYDECO.
%  All Rights Reserved.
%   Disclosure without explicit written consent from the
%    copyright owner does not constitute publication.
% Version of 25-Jun-1999 09:29:57.
% Updated    23-Jul-1999 14:19:43.

%function zi = linear(x,y,z,xi,yi)
%LINEAR Triangle-based linear interpolation

%   Reference: David F. Watson, "Contouring: A guide
%   to the analysis and display of spacial data", Pergamon, 1994.

if nargin < 5 | nargin > 6   % ZYDECO.
	help(mfilename)
	zi = [];
	return
end

if nargin < 5 | nargin > 6   % ZYDECO.
	error(' ## Requires exactly five or six input arguments.')
end

% Prepare for unavailable tri.

if nargin == 5   % ZYDECO.
	yi = xi;
	xi = z;
	z = y;
	y = x;
	x = tri;
	tri = [];
	zi = triterp(tri, x, y, z, xi, yi);
	return
end

% Pad z with NaNs if shorter than the (x, y) data.

if length(z) < length(x)   % ZYDECO.
	z(length(x)) = 0;
	z(length(x)+1:end) = NaN;
end

siz = size(xi);
xi = xi(:); yi = yi(:); % Treat these as columns
x = x(:); y = y(:); % Treat these as columns

% Triangularize the data

if isempty(tri)   % ZYDECO.
	tri = delaunay(x,y,'sorted');
end

if isempty(tri),
  warning('Data cannot be triangulated.');
  zi = repmat(NaN,size(xi));
  return
end

% Find the nearest triangle (t)
t = tsearch(x,y,tri,xi,yi);
%t = tsearchsafe(x,y,tri,xi,yi);

% Only keep the relevant triangles.
out = find(isnan(t));
if ~isempty(out), t(out) = ones(size(out)); end
tri = tri(t,:);

% Compute Barycentric coordinates (w).  P. 78 in Watson.
del = (x(tri(:,2))-x(tri(:,1))) .* (y(tri(:,3))-y(tri(:,1))) - ...
      (x(tri(:,3))-x(tri(:,1))) .* (y(tri(:,2))-y(tri(:,1)));
w(:,3) = ((x(tri(:,1))-xi).*(y(tri(:,2))-yi) - ...
          (x(tri(:,2))-xi).*(y(tri(:,1))-yi)) ./ del;
w(:,2) = ((x(tri(:,3))-xi).*(y(tri(:,1))-yi) - ...
          (x(tri(:,1))-xi).*(y(tri(:,3))-yi)) ./ del;
w(:,1) = ((x(tri(:,2))-xi).*(y(tri(:,3))-yi) - ...
          (x(tri(:,3))-xi).*(y(tri(:,2))-yi)) ./ del;
w(out,:) = zeros(length(out),3);

z = z(:).'; % Treat z as a row so that code below involving
            % z(tri) works even when tri is 1-by-3.
zi = sum(z(tri) .* w,2);

zi = reshape(zi,siz);

if ~isempty(out), zi(out) = NaN; end
