No BSD License  

Highlights from
mrotate

from mrotate by T. Mervin
manually rotate a 3D object

mrotate(h,c,v,constraint)
function mrotate(h,c,v,constraint)
% MROTATE manually rotate an object with the mouse
%   h : handle of the object to rotate
%   c : rotation point
%   v : rotation vector
%   constraint : vertical or horizontal constraint (not implemented yet)

% adapted from Francois Bouffard's draggable.m function
% TO DO : add keyboard input in order to avoid conflicts with other objects on screen
% 06/07 T. Mervin

% ==============================================================================
% Input arguments management
% ==============================================================================

% Initialization of some default arguments
%constraint = 'none';

% At least the handle to the object must be given
Narg = nargin;
if Narg == 0
    error('Not engough input arguments');
elseif prod(size(h))>1
    error('Only one object at a time can be rotated');
end;

% Fetching informations about the parent axes
axh = get(h,'Parent');
if iscell(axh)
    axh = axh{1};
end;
fgh = get(axh,'Parent');
ax_xlim = get(axh,'XLim');
ax_ylim = get(axh,'YLim');
ax_zlim = get(axh,'ZLim');

% Assigning defaults for constraint
switch lower(constraint)
    case {'h','horizontal'}
        disp('Horizontal constraint type, up & down rotation');
        %if isempty(p); p = ax_xlim; end;
    case {'v','vertical'}
        disp('Vertical constraint type, left & right rotation');
        %if isempty(p); p = ax_ylim; end;
    otherwise
        %error('Unknown constraint type');
        disp('Unknown constraint type');
end;

% ==============================================================================
% Saving initial state and parameters, setting up the object callback
% ==============================================================================

% Saving object's and parent figure's initial state
setappdata(h,'initial_userdata',get(h,'UserData'));
setappdata(h,'initial_objbdfcn',get(h,'ButtonDownFcn'));
setappdata(h,'initial_wbdfcn',get(fgh,'WindowButtonDownFcn'));
setappdata(h,'initial_wbufcn',get(fgh,'WindowButtonUpFcn'));
setappdata(h,'initial_wbmfcn',get(fgh,'WindowButtonMotionFcn'));

% Saving parameters
setappdata(h,'constraint_type',constraint);
setappdata(h,'coordinates',c);
setappdata(h,'rotation_vector',v);

% Setting the object's ButtonDownFcn
set(h,'ButtonDownFcn',@click_object);

% ==============================================================================
% FUNCTION click_object
%   Executed when the object is clicked
% ==============================================================================
% REMARQUE : l'objet ne devrait normalement pas tre cliqu
% pour pouvoir initier la rotation

function click_object(obj,eventdata);
    disp('click_object');
    % obj here is the object to be rotated and gcf is the object's parent
    % figure since the user clicked on the object
    h = obj;
    position_type = getappdata(h,'position_type');
    if strcmp(position_type,'xydata')
        setappdata(h,'initial_xdata',get(h,'XData'));
        setappdata(h,'initial_ydata',get(h,'YData'));
    else
%        setappdata(h,'initial_position',get(h,'Position'));
    end;
    setappdata(h,'initial_point',get(gca,'CurrentPoint'));
    set(gcf,'WindowButtonDownFcn',{@activate_rotatefcn,h});
    set(gcf,'WindowButtonUpFcn',{@deactivate_rotatefcn,h});
    activate_rotatefcn(gcf,eventdata,h);

% ==============================================================================
% FUNCTION activate_rotatefcn
%   Activates the WindowButtonMotionFcn for the figure
% ==============================================================================

function activate_rotatefcn(obj,eventdata,h);
    set(obj,'WindowButtonMotionFcn',{@rotatefcn,h});

% ==============================================================================
% FUNCTION deactivate_rotatefcn
%   Deactivates the WindowButtonMotionFcn for the figure
% ==============================================================================

function deactivate_rotatefcn(obj,eventdata,h);
    % obj here is the figure containing the object
    set(obj,'WindowButtonMotionFcn',getappdata(h,'initial_wbmfcn'));
    set(obj,'WindowButtonDownFcn',getappdata(h,'initial_wbdfcn'));
    set(obj,'WindowButtonUpFcn',getappdata(h,'initial_wbufcn'));
    disp('deactivate_rotatefcn');
    % deactivate mrotate completely
    %set_initial_state(h);
    
% ==============================================================================
% FUNCTION set_initial_state
%   Returns the object to its initial state
% ==============================================================================

function set_initial_state(h);
    initial_objbdfcn = getappdata(h,'initial_objbdfcn');
    initial_userdata = getappdata(h,'initial_userdata');
    set(h,'ButtonDownFcn',initial_objbdfcn);
    set(h,'UserData',initial_userdata);
    
% ==============================================================================
% FUNCTION rotatefcn
%   Actual code for dragging the object
% ==============================================================================

function rotatefcn(obj,eventdata,h);
    % obj here is the figure containing the object

    % Getting current point
    current_point = get(gca,'CurrentPoint');
    initial_point = getappdata(h,'initial_point');

    % Retrieving (x,y) couple for current and initial points
    cpt = current_point(1,1:2);
    ipt = initial_point(1,1:2);

    % Computing movement
    dpt = cpt - ipt;
    
    % Computing movement range and imposing movement constraints
    % (p is always [xmin xmax ymin ymax])
    constraint = getappdata(h,'constraint_type');
    switch lower(constraint)
        case {'n','none'};
            %range = p;
        case {'h','horizontal'}
            dpt(2) = 0;
            %range = [p -inf inf];
        case {'v','vertical'}
            dpt(1) = 0;
            %range = [-inf inf p];
    end;
    
    old_dpt = getappdata(h,'old_dpt');
    setappdata(h,'old_dpt',dpt);
    
    c = getappdata(h,'coordinates');
    v = getappdata(h,'rotation_vector');
    disp('rotatefcn');
   
    switch lower(constraint)  % TO DO : really add constraints
        case {'n','none'};
            %range = p;
        case {'h','horizontal'}
            if dpt(1) > old_dpt(1),
                rotate(h,c-v,1,c);
            else 
                rotate(h,c-v,-1,c);
            end;
        case {'v','vertical'}
            if dpt(2) > old_dpt(2),
                rotate(h,c-v,1,c);
            else 
                rotate(h,c-v,-1,c);
            end;
    end;

Contact us at files@mathworks.com