function CS=contoursurf(arg1,arg2,arg3,arg4);

%  CONTOURSURF contouring over non-rectangular surface.
%        
%  This is an extension of contourc.
%  CONTOURSURF calculates the contour matrix C for use by EXTCONTOUR
%  to draw the actual contour plot.
%  C = CONTOURSURF(Z) computes the contour matrix for a contour plot
%  of matrix Z treating the values in Z as heights above a plane.
%  C = CONTOURSURF(X,Y,Z), where X and Y are vectors, specifies the X- 
%  and Y-axes for the contour computation. X and Y can also be matrices of 
%  the same size as Z, in which case they specify a surface in an 
%  identical manner as SURFACE.
%  CONTOURSURF(Z,N) and CONTOURSURF(X,Y,Z,N) compute N contour lines, 
%  overriding the default automatic value.
%  CONTOURSURF(Z,V) and CONTOURSURF(X,Y,Z,V) compute LENGTH(V) contour 
%  lines at the values specified in vector V.
%  CONTOURSURF([X Y],N,Z) contours the triangular mesh specified by
%  node location vectors X,Y with height vector Z, where N is a 3xn matrix 
%  containing the node indices for n triangles.
%  
%  The contour matrix C is a two row matrix of contour lines. Each
%  contiguous drawing segment contains the value of the contour, 
%  the number of (x,y) drawing pairs, and the pairs themselves.  
%  The segments are appended end-to-end as
%  
%      C = [level1 x1 x2 x3 ... level2 x2 x2 x3 ...;
%     pairs1 y1 y2 y3 ... pairs2 y2 y2 y3 ...]
%  
%  See also EXTCONTOUR.

% Author: R. Pawlowicz (IOS) rich@ios.bc.ca
%   12/12/94


 
if (nargin <=2 ),
 numarg_for_call='arg1';
 for ii=2:nargin,
  numarg_for_call=[numarg_for_call ',arg' int2str(ii)];
 end;
 zz=arg1;
else
 if min(size(arg3))==1 & any(size(arg2)==3), % fall-through for triangular mesh
   if (nargin==3), CS=contourtri(arg1,arg3,arg2);
   else      CS=contourtri(arg1,arg3,arg2,arg4);
   end;
   return;
 end;
 numarg_for_call='arg3';
 for ii=4:nargin,
  numarg_for_call=[numarg_for_call ',arg' int2str(ii)];
 end;
 zz=arg3;
end; 

eval(['CS=contourc(' numarg_for_call ');']);
[Ny,Nx]=size(zz);
 
% Find data values and check curve orientation.
 
ii=ones(1,size(CS,2));

if size(CS,2)==0, return; end;

k=1;
while (k < size(CS,2)),
  nl=CS(2,k);
  
  % Now this is a little bit of magic needed to make the filled contours
  % work. Essentially I draw the *closed* contours so that the "high" side is
  % always on the right. To test this, I take the cross product of the
  % first vector with a vector to a corner point and test the sign
  % against the elevation change. There are several special cases:
  % (1) If the contour line goes through a point (which happen when -Infs
  % are around), and (2) when the contour level equals the level on the high
  % side (this always seems to happen in 'simple test' cases!). We take
  % care of (1) by choosing other points, and we take care of (2) by adding
  % eps to the data before comparing with the contour data.
  
  if ( CS(:,k+1)==CS(:,k+nl) & nl>1 ),
    lev=CS(1,k);
    x1=CS(1,k+1); y1=CS(2,k+1);
    x2=CS(1,k+2); y2=CS(2,k+2);
    vx1=x2-x1; vy1=y2-y1;
    cpx=round(x1); cpy=round(y1);
    if ( [cpx cpy]==[x1 y1] ),
      cpx=round(x2); cpy=round(y2);
      if ( [cpx cpy]==[x2 y2]),
   if ( ~([cpx cpy]==round([x1 y1])) ),
     cpx=round(x1);
   else
     cpx=round(x1)+y2-y1;
     cpy=round(y1)-x2+x1;
   end;
       end;
    end;
    vx2=cpx-x1; vy2=cpy-y1;
%    if (sign(zz(cpy,cpx)-lev+epslev)==0) disp('lev=0'); end;
%    if (sign(vx1*vy2-vx2*vy1)==0) disp('cross=0'); end;
    if ( sign(zz(cpy,cpx)-lev+eps) == sign(vx1*vy2-vx2*vy1)  ),
      CS(:,k+[1:nl])=fliplr(CS(:,k+[1:nl]));
    end; 
  end;
  ii(k)=0;
  k=k+1+nl;
end;

% Data from integer coords to data coords. There are 3 cases
% (1) Matrix X/Y
% (2) Vector X/Y
% (3) no X/Y. (do nothing);

if (nargin>2 & min(size(arg1))>1 ),

 X=CS(1,ii)';   Y=CS(2,ii)';
 cX=ceil(X);    fX=floor(X);
 cY=ceil(Y);    fY=floor(Y);
 
 Ibl=cY+(fX-1)*Ny;    Itl=fY+(fX-1)*Ny;
 Itr=fY+(cX-1)*Ny;    Ibr=cY+(cX-1)*Ny;
 
 dy=cY-Y; dx=X-fX;
 
 % Correct for possible conflicts in matlabs [1 1 1 ] indexing. This
 % probably will *never* happen in real life, but turns up annoyingly
 % often in "simple" test cases.
 if (Nx*Ny == length(Ibl) ),
   Ibl=[1;Ibl];   Itl=[1;Itl];
   Itr=[1;Itr];   Ibr=[1;Ibr];
   dx=[0;dx];     dy=[0;dy];
   Csave=CS(:,1); 
   ii(1)=1;  
 end;
 
 CS(1,(ii)) = [ arg1(Ibl).*(1-dx).*(1-dy) + arg1(Itl).*(1-dx).*dy ...
       + arg1(Itr).*dx.*dy   + arg1(Ibr).*dx.*(1-dy)]';
 CS(2,(ii)) = [ arg2(Ibl).*(1-dx).*(1-dy) + arg2(Itl).*(1-dx).*dy ...
       + arg2(Itr).*dx.*dy   + arg2(Ibr).*dx.*(1-dy) ]';

 if (exist('Csave')),
  CS(:,1)=Csave;
 end;
 
elseif (nargin>2 & min(size(arg1))==1 ),
 X=CS(1,ii);  Y=CS(2,ii);
 cX=ceil(X); fX=floor(X);
 cY=ceil(Y); fY=floor(Y);

 dy=cY-Y;    dx=X-fX;

 if (size(arg1,2)==1), 
   CS(1,ii)=[arg1(fX)'.*(1-dx)+arg1(cX)'.*dx];
 else
   CS(1,ii)=[arg1(fX).*(1-dx)+arg1(cX).*dx];
 end;
 
 if (size(arg2,2)==1), 
   CS(2,ii)=[arg2(fY)'.*dy+arg2(cY)'.*(1-dy)]; 
 else
   CS(2,ii)=[arg2(fY).*dy+arg2(cY).*(1-dy)]; 
 end;
 
end;
       
        

