No BSD License  

Highlights from
Click-n'-drag plot

image thumbnail
from Click-n'-drag plot by Jean-Pascal Rueff
Move curves with mouse in a MATLAB figure.

interactive_move(varargin)
function interactive_move(varargin)
%
%function interactive_move(tag)
%
%Click and drag curves interactively
%Automatically select the pointed curve
%
%- Focus on figure first
%- Enable with interactive_move
%- Click outside of axes (gray area) to disable
%- Press x or y while draging to constraint x or y movements
%
%Copyright J.P. Rueff, Aout 2004, modified Juin 2005

% set(gca,'XLimMode','manual','YLimMode','manual');

%---handle initialization
handles = guidata(gca);
handles.macro_active=0;
%handles.lineObj = findobj(gca, 'Type', 'line');
handles.lineObj=[findobj(gca, 'Type', 'line');findobj(gca, 'Type', 'patch')];
handles.currentlineObj=0;
handles.key='';
guidata(gca,handles);

if nargin==0,tag=1;,else tag=varargin{1};end

%---define callback routine on setup
if tag==1
%     disp('interactive_move enable')
    handles.init_state = uisuspend(gcf);guidata(gca,handles); %--save initial state

    
    set(gcf, 'windowbuttondownfcn', {@myclick,1});
    set(gcf, 'windowbuttonmotionfcn', {@myclick,2});
    set(gcf, 'windowbuttonupfcn', {@myclick,3});
    set(gcf, 'keypressfcn', {@myclick,4});
    %---define callback routine on delete
else
%      disp('interactive_move disable')
      uirestore(handles.init_state);
end

%--------function to handle event
function myclick(h,event,type)

handles=guidata(gca);

switch type
    case 1 %---Button down
        out=get(gca,'CurrentPoint');
        handles.lineObj=[findobj(gca, 'Type', 'line');findobj(gca, 'Type', 'patch')];
        set(gca,'NextPlot','replace')
        set(gcf,'Pointer','fullcrosshair');
        handles.macro_active=1;
        handles.xpos0=out(1,1);%--store initial position x
        handles.ypos0=out(1,2);%--store initial position y
        xl=get(gca,'XLim');yl=get(gca,'YLim');
        if ((handles.xpos0 > xl(1) & handles.xpos0 < xl(2)) & (handles.ypos0 > yl(1) & handles.ypos0 < yl(2))) %--disable if outside axes
            [handles.currentlineObj,handles.currentlinestyle]=line_pickup(handles.lineObj,[out(1,1) out(1,2)]);%--choose the right curve via line_pickup
            if handles.currentlineObj~=0 %--if curve foundd
                handles.xData = get(handles.lineObj(handles.currentlineObj), 'XData');%--assign x data
                handles.yData = get(handles.lineObj(handles.currentlineObj), 'YData');%--assign y data 
            end
            handles.currentTitle=get(get(gca, 'Title'), 'String');
            guidata(gca,handles)
            
            title(['[' num2str(out(1,1)) ',' num2str(out(1,2)) ']']);
        else
            interactive_move(0);
        end    
    case 2%---Button Move
        if handles.macro_active
            out=get(gca,'CurrentPoint');
            set(gcf,'Pointer','fullcrosshair');
            title(['[' num2str(out(1,1)) ',' num2str(out(1,2)) ']']);
            if handles.currentlineObj~=0
                switch handles.key
                    case ''%--if no key pressed
                        set(handles.lineObj(handles.currentlineObj),'XData',handles.xData-(handles.xpos0-out(1,1)));%-move x data
                        set(handles.lineObj(handles.currentlineObj),'YData',handles.yData-(handles.ypos0-out(1,2)));%-move y data    
                        handles.xData-(handles.xpos0-out(1,1));%-update x data
                        handles.yData-(handles.ypos0-out(1,2));%-update y data
                        title(['[' num2str(out(1,1)) ',' num2str(out(1,2)) '], offset=[' num2str(handles.xpos0-out(1,1)) ',' num2str(handles.ypos0-out(1,2)) ']']);
                    case 'x'%--if x pressed
                        set(handles.lineObj(handles.currentlineObj),'XData',handles.xData-(handles.xpos0-out(1,1)));%--move x data
                        handles.xData-(handles.xpos0-out(1,1));%-update x data
                        title(['[' num2str(out(1,1)) ',' num2str(out(1,2)) '], offset=[' num2str(handles.xpos0-out(1,1)) ',0]']);
                    case 'y'%--if y pressed
                        set(handles.lineObj(handles.currentlineObj),'YData',handles.yData-(handles.ypos0-out(1,2)));%--move y data
                        handles.yData-(handles.ypos0-out(1,2));%-updata y data
                        title(['[' num2str(out(1,1)) ',' num2str(out(1,2)) '], offset=[0,' num2str(handles.ypos0-out(1,2)) ']']);
                    case 'a'%--if a pressed, move all curves
                        for i=1:length(handles.lineObj)
                        handles.yData=get(handles.lineObj(i), 'YData');
                        set(handles.lineObj(i),'YData',handles.yData-(handles.ypos0-out(1,2)));%--move y data
                        handles.yData-(handles.ypos0-out(1,2));%-updata y data
                        title(['[' num2str(out(1,1)) ',' num2str(out(1,2)) '], offset=[0,' num2str(handles.ypos0-out(1,2)) ']']);
                        end
                end              
            end
            
            guidata(gca,handles)
        end
        
    case 3 %----Button up (cleanup some variable)
        set(gcf,'Pointer','arrow');
        set(gca,'NextPlot','add')
        if handles.currentlineObj~=0,set(handles.lineObj(handles.currentlineObj),'LineStyle',handles.currentlinestyle),end
        handles.macro_active=0;
        handles.key='';
        title(handles.currentTitle);
        guidata(gca,handles)
        
    case 4 %----Button press
        handles.key=get(gcf,'CurrentCharacter');
        guidata(gca,handles)
    end
    
    %---------function to pickup to pointed curve
    function [col,lstyle]=line_pickup(list_line_obj,pos)
    
    col=0;
    lstyle='-';
    
    %-define searching windows
    xl=get(gca,'XLim');
    xwin=abs(xl(1)-xl(2))/100;
    yl=get(gca,'YLim');
    ywin=abs(yl(1)-yl(2))/100;
    
    %-load all datasets
    for i=1:length(list_line_obj)
        xData{i}=get(list_line_obj(i), 'XData');
        yData{i}=get(list_line_obj(i), 'YData');
    end
    
%     %--look for matches in x and y direction
    for i=1:length(list_line_obj)
        candidate{i}=find((abs(pos(1,2)-yData{i})<ywin) & (abs(pos(1,1)-xData{i})<xwin));
    end
           
    %---find the right guy
 for i=1:length(list_line_obj)
     if ~isempty(candidate{i})
         col=i;
         lstyle=get(list_line_obj(col),'LineStyle');
         if lstyle==':'
         set(list_line_obj(col),'LineStyle','-');
         else
         set(list_line_obj(col),'LineStyle',':');
         end
     end
 end
    

Contact us at files@mathworks.com