function h = slice3i(vol, I2X, slicedim, sliceidx, handle, keepxyz)
% Display a slice from a volume in 3-D
% h = slice3(vol, I2X, slicedim, sliceidx, handle) 
%
% Vol is either a scalar or RGB volume, e.g. N x M x K or N x M x K x 3.
% I2X is a transformation matrix from volume coordinates to xyz 3-D world
% coordinates, similar to the transform used by image3i.
%
%     [x y z 1]' = I2X * [i j k 1]'
%
% slicedim  is 1, 2 or 3 and corresponds to i, j and k.
% sliceidx  the index of the slice along slicedim
% handle    an optional handle to a previous slice to reuse
% h         the handle to the created slice.
%
% Example:
%
% load mri;
% T = [1 0 0 0;0 1 0 0;0 0 2.5 0];
% h1 = slice3i(squeeze(D),T,1,64);
% h2 = slice3i(squeeze(D),T,2,64);
% h3 = slice3i(squeeze(D),T,3,14);
% colormap gray(88);
% view(30,45); axis equal;
%
% SEE ALSO: image3i, imagesc3
%
% Author: Anders Brun, anders@cb.uu.se (2009)
%
% Modified by Qianqian Fang, q.fang at neu.edu
%
% Features added: 
%    1) compatible with octave 4.0 or newer
%    2) start 3D rotation by clicking/holding the middle mouse key
%    3) adjust colormap levels by dragging with the right mouse key
%    4) support 4-D data (up/down key to change frames)
% 

if(nargin<6)
    keepxyz=0;
end

try
    h = update_slice(vol, I2X, slicedim, sliceidx, handle, keepxyz);
catch
    h = update_slice(vol, I2X, slicedim, sliceidx);
end
    
% set up gui
gui.handle = h;
gui.vol = vol;
gui.I2X = I2X;
gui.slicedim = slicedim;
gui.sliceidx = sliceidx;
set(gui.handle,'ButtonDownFcn',@startmovit);

set(h,'UserData',gui);

function stoprotate(src,hrot)
if strcmp(get(gcf,'SelectionType'), 'extend')
    rotate3d off;
end

function startmovit(src,evnt)

if strcmp(get(gcf,'SelectionType'), 'extend')
    rotate3d on;
    return;
end

% Unpack gui object
gui = get(src,'UserData');
%turn off mouse pointer
%set(gcf,'PointerShapeCData',nan(16,16));
%set(gcf,'Pointer','custom');

thisfig = gcbf();
gui.startray = get(gca,'CurrentPoint');
gui.startidx = gui.sliceidx;
gui.p0=get(gcf,'currentpoint');
gui.level0=size(colormap,1);


% Store gui object
set(src,'UserData',gui);
set(thisfig,'WindowButtonMotionFcn',@movit);
set(thisfig,'WindowButtonUpFcn',@stopmovit);
set(thisfig,'UserData',src);


function movit(src,evnt)
% Unpack gui object
gui = get(get(gcf,'UserData'),'UserData');
% Some safetymeasures
try
if isequal(gui.startray,[])
    return
end
catch
end

if strcmp(get(gcf,'SelectionType'), 'alt')
    if(isempty(gui) || ~isfield(gui,'p0'))
        return;
    end
    delta=get(gcf,'currentpoint')-gui.p0;
    windim=get(gcf,'position');
    delta=delta./windim(3:4);
    currentlevel=round(gui.level0+delta(2)/4*256);
    if(currentlevel>256)
        currentlevel=256;
    elseif(currentlevel<8)
        currentlevel=8;
    end
    colormap(jet(currentlevel));
    return;
end

% Do "smart" positioning of the markers...
nowray = get(gca,'CurrentPoint');

% Project rays on slice-axis
s = gui.I2X(1:3,gui.slicedim);
a = gui.startray(1,:)';
b = gui.startray(2,:)';

alphabeta = pinv([s'*s, -s'*(b-a);(b-a)'*s, -(b-a)'*(b-a)])*[s'*a, (b-a)'*a]';
pstart = alphabeta(1)*s;
alphastart = alphabeta(1);
a = nowray(1,:)';
b = nowray(2,:)';
alphabeta = pinv([s'*s, -s'*(b-a);(b-a)'*s, -(b-a)'*(b-a)])*[s'*a, (b-a)'*a]';
pnow = alphabeta(1)*s;
alphanow = alphabeta(1);
slicediff = alphanow-alphastart;

gui.sliceidx = gui.startidx+slicediff;
gui.sliceidx = min(max(1,gui.sliceidx),size(gui.vol,gui.slicedim));
update_slice(gui.vol, gui.I2X, gui.slicedim, gui.sliceidx, gui.handle);
drawnow;

% Store gui object
set(get(gcf,'UserData'),'UserData',gui);


function stopmovit(src,evnt)

thisfig = gcbf();
%set(gcf,'Pointer','arrow');
set(thisfig,'WindowButtonUpFcn','');
set(thisfig,'WindowButtonMotionFcn','');
gui = get(get(gcf,'UserData'),'UserData');
gui.startray = [];
%gui.sliceidx = gui.nextsliceidx
set(get(gcf,'UserData'),'UserData',gui);
set(gcf,'UserData',[]);
drawnow;

function h = update_slice(vol, I2X, slicedim, sliceidx, handle, keepxyz)

if(nargin<6)
    keepxyz=0;
end

if ndims(vol) == 3         %Scalar mode
elseif ndims(vol) == 4     %RGB mode
    if(size(vol,4)>3)
        gui = get(get(gcf,'UserData'),'UserData');
        if(~isempty(gui) && isfield(gui,'frame'))
            vol=gui.vol(:,:,:,gui.frame);
        else
            vol=gui.vol(:,:,:,1);
        end
    end
else
  error('Only scalar and RGB images supported')
end

% Create the slice
if slicedim == 3 % k
  ij2xyz = I2X(:,[1 2]);
  ij2xyz(:,3) = I2X*[0 0 sliceidx 1]';
  sliceim = squeeze(vol(:,:,round(sliceidx),:));

elseif slicedim == 2 % j
  ij2xyz = I2X(:,[1 3]);
  ij2xyz(:,3) = I2X*[0 sliceidx 0 1]';
  sliceim = squeeze(vol(:,round(sliceidx),:,:));

elseif slicedim == 1 % i
  ij2xyz = I2X(:,[2 3]);
  ij2xyz(:,3) = I2X*[sliceidx 0 0 1]';
  sliceim = squeeze(vol(round(sliceidx),:,:,:));
else
    error('Slicedim should be 1, 2 or 3')
end


if nargin<5 || handle == 0
  h = image3i(sliceim,ij2xyz);
else
  h = image3i(sliceim,ij2xyz,handle, keepxyz);
end

