Code covered by the BSD License  

Highlights from
stereoview - Ver 7.0

image thumbnail
from stereoview - Ver 7.0 by Iari-Gabriel Marino
Stereoview plots two stereoscopical images of any 3D plot.

stereoview
function stereoview
% STEREOVIEW  Stereoscopic plotting function
% 
%   stereoview grabs the current 3D figure and plots it in two
%   stereoscopical images.
% 
%   Once launched, you can:
%   1) Choose the interocular distance coefficient (idc)
%   that is defined as the ratio between the distance from the Camera
%   Target and the interocular distance; a value of 30 works fine.
% 
%   2) Choose the viewing mode: 'parallel' or 'crossed'.
% 
% 	3) Rotate the view. In the Free Rotation mode, use:
%   a, s, d, w to rotate,
%   x to stop.
% 
%   4) Start a continuous rotation of the view; x to stop.
% 
%   5) Print the two stereoscopical views in separate images. You
%   may change the options for the saved images directly in the .m file.
% 
%   6) choose 'perspective' or 'orthographic' view.
% 
%   Version 4.0 NEWS
%   - stop of the continuous rotation with "x"
%   - can print the two images
% 
%   Version 5.0 NEWS
%   - can change the distance between the two
%     views to allow easier visualization
%   - can change zoom
%   - vertical axis bending bug fixed
% 
%   Version 6.0 NEWS
%   - allows chosing perspective or orthographic
%   - unused commands deleted
% 
%   Version 7.0 NEWS
%   - bug about viewing along z fixed
%   - bug about horizontal positioning of plots fixed
%   - bug about projection mode fixed
%   - figure color preserved
%   - renderer: zbuffer
%   - figure(2) bug fixed (thanks to Andrew Murray)
% 
% ----------------------------------------------------------
% 2010      Iari-Gabriel Marino
%           <infoAToptotesys.it>
%           <iari-gabriel.marinoATfis.unipr.it>
%           http://www.fis.unipr.it/home/marino/    
% ----------------------------------------------------------
%   Example 0
% 
%   knot
%   stereoview
% 
%   ------------------------
%   Example 1
% 
%   [X,Y,Z] = peaks(30);
%   surfc(X,Y,Z)
%   stereoview
% 
%   ------------------------
%   Example 2
% 
% 	daspect([1,1,1])
% 	load wind
% 	xmin = min(x(:));
% 	xmax = max(x(:));
% 	ymin = min(y(:));
% 	ymax = max(y(:));
% 	zmin = min(z(:));
% 	daspect([2,2,1])
% 	xrange = linspace(xmin,xmax,8);
% 	yrange = linspace(ymin,ymax,8);
% 	zrange = 3:4:15;
% 	[cx cy cz] = meshgrid(xrange,yrange,zrange);
% 	hcones = coneplot(x,y,z,u,v,w,cx,cy,cz,5);
% 	set(hcones,'FaceColor','red','EdgeColor','none')
% 	hold on
% 	wind_speed = sqrt(u.^2 + v.^2 + w.^2);
% 	hsurfaces = slice(x,y,z,wind_speed,[xmin,xmax],ymax,zmin);
% 	set(hsurfaces,'FaceColor','interp','EdgeColor','none')
% 	hold off
% 	axis tight; view(30,40); axis off
% 	camproj perspective; camzoom(1.5)
% 	camlight right; lighting phong
% 	set(hsurfaces,'AmbientStrength',.6)
% 	set(hcones,'DiffuseStrength',.8)
%   stereoview
% 
%   ------------------------
%   Example 3
% 
% 	[x y z v] = flow;
% 	h = contourslice(x,y,z,v,[1:9],[],[0],linspace(-8,2,10));
% 	axis([0,10,-3,3,-3,3]); daspect([1,1,1])
% 	camva(24); camproj perspective;
% 	campos([-3,-15,5])
% 	set(gcf,'Color',[.5,.5,.5],'Renderer','zbuffer')
% 	set(gca,'Color','black','XColor','white', ...
%         'YColor','white','ZColor','white')
% 	box on
%   stereoview

St.title = 'Stereoview by I.-G. Marino';

St.idc = 30; %interocularDistanceCoefficient;
St.freeRotating = 0;
St.RotatingFlag = 0;
St.flying = 0;
% take the data of the original figure and set it invisible
origColormap = colormap;
origColor = get(gcf,'Color');
St.origcamup = camup;
St.origFig = gcf; set(St.origFig,'visible','off')
St.origAxis = gca;
origProj = camproj;
% create the stereo figure
St.stereoF = figure; set(St.stereoF,'name',St.title,'numbertitle','off','CloseRequestFcn',{@closeReqFcn,St});
pos = [120 271 780 420]; colormap(origColormap); set(gcf,'color',origColor);
set(St.stereoF,'Position',pos,'doublebuffer','on');
% create two axes (the two stereoscopical views) and paste on them the
% same original data; "axis vis3d" freezes aspect ratio properties to
% enable rotation of 3-D objects and overrides stretch-to-fill.
St.sxEye = copyobj(St.origAxis,St.origFig); set(St.sxEye,'pare',St.stereoF)
set(St.sxEye,'position',[0/10 3/10 5/10 6.5/10]);
axes(St.sxEye); axis vis3d;
St.dxEye = copyobj(St.origAxis,St.origFig); set(St.dxEye,'pare',St.stereoF)
set(St.dxEye,'position',[5/10 3/10 5/10 6.5/10]);
axes(St.dxEye); axis vis3d;
set(gcf,'Renderer','zbuffer');

% create buttons and controls
St.azLeftButton = uicontrol(gcf,'style','push','string','Left','position',[41 30 38 20]);
St.azRightButton = uicontrol(gcf,'style','push','string','Right','position',[81 30 38 20]);
St.azLeftRotButton = uicontrol(gcf,'style','push','string','<<','position',[41 10 38 20]);
St.azRightRotButton = uicontrol(gcf,'style','push','string','>>','position',[81 10 38 20]);
St.elUpButton = uicontrol(gcf,'style','push','string','Up','position',[121 30 38 20]);
St.elDownButton = uicontrol(gcf,'style','push','string','Down','position',[161 30 38 20]);
St.idcText = uicontrol(gcf,'style','text','string','IDC','position',[301 30 38 20]);
St.idcEdit = uicontrol(gcf,'style','edit','string','100','position',[291 10 58 20]);
St.changeModeList = uicontrol(gcf,'style','listbox','string',{'Parallel';'Crossed'},'position',[201 10 78 40]);
St.rotButton = uicontrol(gcf,'style','push','string','Free Rotation','position',[121 10 78 20]);
St.PrintViewsButton = uicontrol(gcf,'style','push','string','Print Views','position',[661 30 68 20]);
St.resetViewButton = uicontrol(gcf,'style','push','string','Reset View','position',[661 10 68 20]);
St.plotsMoreDistanceButton = uicontrol(gcf,'style','push','string','Plots <->','position',[581 30 68 20]);
St.plotsLessDistanceButton = uicontrol(gcf,'style','push','string','Plots >-<','position',[581 10 68 20]);
St.plotsMoreZoomButton = uicontrol(gcf,'style','push','string','Zoom +','position',[501 30 68 20]);
St.plotsLessZoomButton = uicontrol(gcf,'style','push','string','Zoom -','position',[501 10 68 20]);
St.projButton = uicontrol(gcf,'style','push','string','Ortho.','position',[360 10 68 20]);

switch origProj
    case 'perspective'
        set(St.projButton,'string','Ortho.');
    case 'orthographic'
        set(St.projButton,'string','Persp.');
end

set(St.azLeftButton,'callback',{@changeAz,{St,10}});
set(St.azRightButton,'callback',{@changeAz,{St,-10}});
set(St.azLeftRotButton,'callback',{@rotateAz,{St,10}});
set(St.azRightRotButton,'callback',{@rotateAz,{St,-10}});
set(St.elUpButton,'callback',{@changeEl,{St,-5}});
set(St.elDownButton,'callback',{@changeEl,{St,5}});
set(St.idcEdit,'callback',{@changeIdc,St});
set(St.changeModeList,'callback',{@changeMode,St});
set(St.rotButton,'callback',{@freeRot,St});
set(St.PrintViewsButton,'callback',{@printViews,St});
set(St.resetViewButton,'callback',{@resetView,St});
set(St.plotsMoreDistanceButton,'callback',{@plotsDistance,{St,5}});
set(St.plotsLessDistanceButton,'callback',{@plotsDistance,{St,-5}});
set(St.plotsMoreZoomButton,'callback',{@plotsZoom,{St,-.5}});
set(St.plotsLessZoomButton,'callback',{@plotsZoom,{St,.5}});
set(St.projButton,'callback',{@changeProj,St});

% plot the stereoscopical figures
St = PlotStereo(St);
shg

function St = PlotStereo(St)
% for camera position and target always consider as reference
% the original (invisible) figure
oriAspR = get(St.origAxis,'DataAspectRatio');
St.P0 = campos(St.origAxis)./oriAspR;    % normalization of X and Y by using DataAspectRatio values
St.T0 = camtarget(St.origAxis)./oriAspR; % normalization of X and Y by using DataAspectRatio values
d = sqrt(sum((St.P0-St.T0).^2)); % distance between camera and target: ||St.T0-St.P0||
% L is the real interocular distance; St.idc is a coefficient
L = d/St.idc;
%------------------------------
% Calculations for the position of the two cameras (eyes)
%------------------------------
if not(isequal((St.P0-St.T0)/norm(St.P0-St.T0),[0 0 1])) % The view direction is not the z axis
    P1 = St.P0 + L/2 * unitv(cross(St.P0-St.T0,[0 0 1]));
    P2 = St.P0 - L/2 * unitv(cross(St.P0-St.T0,[0 0 1]));
    %------------------------------
    campos(St.sxEye,P1.*oriAspR); % torno ai valori veri di X e Y moltiplicando per [oriAspR(1) oriAspR(2) 1]
    camtarget(St.sxEye,St.T0.*oriAspR);
    camup(St.sxEye,St.origcamup)
    campos(St.dxEye,P2.*oriAspR);
    camtarget(St.dxEye,St.T0.*oriAspR);
    camup(St.dxEye,St.origcamup)
else % if the view direction is along z
    P1 = St.P0 + L/2 * unitv(cross(St.P0-St.T0,[1 0 0]));
    P2 = St.P0 - L/2 * unitv(cross(St.P0-St.T0,[1 0 0]));
    %------------------------------
    campos(St.sxEye,P1.*oriAspR); % torno ai valori veri di X e Y moltiplicando per [oriAspR(1) oriAspR(2) 1]
    camtarget(St.sxEye,St.T0.*oriAspR);
    camup(St.sxEye,St.origcamup)
    campos(St.dxEye,P2.*oriAspR);
    camtarget(St.dxEye,St.T0.*oriAspR);
    camup(St.dxEye,St.origcamup)
end

function u = unitv(v)
u = v/(sqrt(sum(v.^2)));

function St = closeReqFcn(Handle,action,St)
if strcmp(get(St.stereoF,'Tag'),'flying'),
    disp('Press x before closing.');
    set(St.stereoF,'name','Press x before closing.');
else
    set(St.stereoF,'Tag','2close');
    delete(St.stereoF);
    set(St.origFig,'visible','on');
end

function St = changeProj(Handle,action,St)
axes(St.sxEye)
sxProj = camproj;
switch sxProj
    case 'perspective'
        axes(St.sxEye)
        camproj('orthographic')
        axes(St.dxEye)
        camproj('orthographic')
        set(St.projButton,'string','Persp.');
    case 'orthographic'
        axes(St.sxEye)
        camproj('perspective')
        axes(St.dxEye)
        camproj('perspective')
        set(St.projButton,'string','Ortho.');
end


function St = changeMode(ListH,action,St)
choice = get(ListH,'value');
sxPos = get(St.sxEye,'pos');
dxPos = get(St.dxEye,'pos');
switch choice
    case 1, % 'parallel'
        if sxPos(1)>dxPos(1),
            set(St.sxEye,'pos',[dxPos(1) sxPos(2) sxPos(3) sxPos(4)]);
            set(St.dxEye,'pos',[sxPos(1) dxPos(2) dxPos(3) dxPos(4)]);
        end
    case 2, % 'crossed'
        if sxPos(1)<dxPos(1),
            set(St.sxEye,'pos',[dxPos(1) sxPos(2) sxPos(3) sxPos(4)]);
            set(St.dxEye,'pos',[sxPos(1) dxPos(2) dxPos(3) dxPos(4)]);
        end
end
St = PlotStereo(St);

function St = plotsDistance(ButtonH,action,data)
St = data{1};
d = data{2};
set(St.sxEye,'units','pixel')
set(St.dxEye,'units','pixel')
sxPos = get(St.sxEye,'pos');
dxPos = get(St.dxEye,'pos');
set(St.sxEye,'pos',[sxPos(1)-d sxPos(2) sxPos(3) sxPos(4)]);
set(St.dxEye,'pos',[dxPos(1)+d dxPos(2) dxPos(3) dxPos(4)]);
set(St.sxEye,'units','normal')
set(St.dxEye,'units','normal')

function St = plotsZoom(ButtonH,action,data)
St = data{1};
z = data{2};
sxZoom = get(St.sxEye,'CameraViewAngle');
dxZoom = get(St.dxEye,'CameraViewAngle');
set(St.sxEye,'CameraViewAngle',sxZoom+z);
set(St.dxEye,'CameraViewAngle',dxZoom+z);

function St = changeIdc(EditH,action,St)
St.idc = str2num(get(EditH,'string'));
St = PlotStereo(St);

function St = resetView(ButtonH,action,St)
close(St.stereoF)
stereoview

function St = printViews(ButtonH,action,St)
fh_L = figure;
set(St.sxEye,'parent',fh_L,'units','normal')
set(gca,'pos',[0.13 0.11 0.775 0.8150])
print(gcf,'-dpng','stereoview_L')
set(St.sxEye,'parent',St.stereoF,'position',[0/10 3/10 5/10 6.5/10]);
close(fh_L)
fh_R = figure;
set(St.dxEye,'parent',fh_R,'units','normal')
set(gca,'pos',[0.13 0.11 0.775 0.8150])
print(gcf,'-dpng','stereoview_R')
set(St.dxEye,'parent',St.stereoF,'position',[5/10 3/10 5/10 6.5/10]);
close(fh_R)

function St = changeAz(ButtonH,action,data)
St = data{1};
moveAz = data{2};
axes(St.sxEye)
camorbit(moveAz,0);
axes(St.dxEye)
camorbit(moveAz,0);
drawnow

function St = rotateAz(ButtonH,action,data)
St = data{1};
moveAz = data{2};
set(St.stereoF,'WindowStyle','modal');
set(St.stereoF,'name','Rotating - Press x to exit.');
disp('Rotation Mode: Press x to exit')
St.RotatingFlag = 1;
while St.RotatingFlag == 1,
    figure(St.stereoF);
    if strcmp(get(St.stereoF,'CurrentCharacter'),'x')
            St.RotatingFlag = 0;
            set(St.stereoF,'CurrentCharacter','p')
    end
    axes(St.sxEye)
    camorbit(moveAz,0);
    axes(St.dxEye)
    camorbit(moveAz,0);
    drawnow
end
set(St.stereoF,'name',St.title);
set(St.stereoF,'WindowStyle','normal');

function St = changeEl(ButtonH,action,data)
St = data{1};
moveEl = data{2};
axes(St.sxEye)
camorbit(0,moveEl);
axes(St.dxEye)
camorbit(0,moveEl);
drawnow

function St = freeRot(ButtonH,action,St)
set(St.stereoF,'WindowStyle','modal');
set(ButtonH,'String','x to stop');
set(St.stereoF,'name','Flying - Use: a d w s - x to Exit.');
set(St.stereoF,'Tag','flying');
St.freeRotating = 1;
while St.freeRotating,
    if not(strcmp(get(St.stereoF,'Tag'),'2close')),
        figure(St.stereoF);
        switch get(St.stereoF,'CurrentCharacter')
        case 'a',
            changeAz([],[],{St ; 5});
            set(St.stereoF,'CurrentCharacter','p')
        case 'd',
            changeAz([],[],{St ; -5});
            set(St.stereoF,'CurrentCharacter','p')
        case 'w',
            changeEl([],[],{St ; 5});
            set(St.stereoF,'CurrentCharacter','p')
        case 's',
            changeEl([],[],{St ; -5});
            set(St.stereoF,'CurrentCharacter','p')
        case 'x',
            St.freeRotating = 0;
            set(St.stereoF,'CurrentCharacter','p')
        otherwise,
        end
        drawnow
    else
        St.freeRotating = 0;
        delete(St.stereoF);
    end
end
set(St.stereoF,'Tag','stopped');
set(ButtonH,'String','Free Rotation');
set(St.stereoF,'name',St.title);
set(St.stereoF,'WindowStyle','normal');

Contact us at files@mathworks.com