function H=mlin(varargin)
% Mouse LINe(s) in current axes. GUI, data selection. Allows to set minimal step
%Switches YDir temporarily to 'normal'.
%
%Call:
% H = mlin([col] [,diagstep])
% H = mlin([diagstep][,col] )
% Press mouse button within plot box and draw next line,
% possibly visiting the area outside of plot box.
%
% Release the button and continue, or delete all at once or one-by-one
% lines by mouse click, or finish MLIN
%
%Input:
% col= color/linewidth specificator for CLINE, e.g. '9r.' or 'b'...
% default col='k-4.'
% diagstep, def. 100, defines minimal distance between neighboring points
% as (box diagonal length)/diagstep
%
%Output:
% H = Handle(s) to drawn lines
%
% DEMOs
%
% 1. Drawing in empty axes
% cla
% mlin %Black dot & line
%
% 2. H=mlin('7hr',150) % red hexa, smaller step
%
% 3. H=mlin('9b') %Thick line
%
% 4. Drawing over a matrix image (screenshot example)
% s=512;
% imagesc(peaks(s)+randn(s))
% colormap(bow('afm'))
% set(gca,'FontSize',15);
% title('Noisy peaks')
% shg,pause(1)
% H=mlin(200,'2k');
% pause(2)
% set(H,'color','r');
% Vassili Pastushenko Nov. 2007+ Jan. 2008 (minimal step)
CE=varargin;
%Check input for col and diagstep
parsque %parse queue
currax=gca;
%Axis limits for flow control
axis(axis);
xx=xlim;
yy=ylim;
dX=diff(xx);
dY=diff(yy);
%define step
step=norm([dX,dY])/diagstep;
Ydir=get(currax,'YDir');
VIS=get(currax,'visible');
set(currax,'YDir','normal','visible','off');
box=[xx(1)+1i*yy,xx(2)+1i*fliplr(yy),xx(1)+1i*yy(1)];
BOX=cline(box,'k'); %Shows where to start drawing
fi=gcf;
%Save Button 'Up' and 'Motion' Fcn's
Button_move_old=get(fi,'WindowButtonMotionFcn');
Button_up_old=get(fi,'WindowButtonUpFcn');
%Button_down_old=get(fi,'WindowButtonDownFcn');
settex %SETs TEXts explaining actions of mouse click outside box
H=[]; %Output
h=[]; %dynamic handle
deciret=0; %DECIsion RETurn
%Drawing loop for consecutive curves
while 1
set(htex,'string',decitex);
decide % different actions after mouse click or button down
if deciret
set(currax,'YDir',Ydir,'visible',VIS); %Recover original settings
TOTAL=[ht,BOX];% Altogether objects to remove
delete(TOTAL); %Remove texts and BOX
return
end
coun=1; %Count of points sampled
xy=[Inf Inf]; %placeholder to define dynamic handle h
h=cline(xy,col);
if auto
set(h,'linewidth',1.5);
end
set(htex,'string',sectex); %We start drawing
set(fi,'WindowButtonMotionFcn',@followpointer,'WindowButtonUpFcn',@stopmouse);
uiwait
end
function followpointer(obj,cas)
currp=get(currax,'currentpoint');
curp=currp(2:3);
if norm(curp-xy(coun,:))>=step;
coun=coun+1;
xy(coun,:)=curp;
set(h,'xdata',xy(:,1),'ydata',xy(:,2));
end
end
function stopmouse(obj,cas)
%recover WindowButtonFcn's Motion and Up
set(fi,'WindowButtonMotionFcn',Button_move_old,'WindowButtonUpFcn',Button_up_old);
xy(1,:)=[];
falstart=numel(xy(:,1))<3;
if ~falstart
falstart=falstart|(prod(xx-xy(1,1))>0 | prod(yy-xy(1,2))>0);
end
if falstart
delete(h);
else
set(h,'XData',xy(:,1),'YData',xy(:,2));
H(end+1)=h;
end
uiresume
end %stopmouse
function decide
waitforbuttonpress
pont=get(currax,'CurrentPoint');
turnon=prod(pont(3)-yy)<0&&prod(pont(1)-xx)<0;
deletret=prod(pont(3)-yy)<0;
deletlast=(pont(2)<xx(1))&deletret;
deciret=(pont(2)>xx(2))&deletret;
if turnon||deciret
if deciret
cheer(numel(H));
end
return
end
deletal=pont(3)<yy(1);
Hhas=~isempty(H);
if deletal&&Hhas
delete(H);
cheer(numel(H));
H=[];
end
if deletlast&&Hhas
delete(H(end));
cheer(1);
H(end)=[];
end
end
function settex
postx=mean(xx);
posty=yy(2)+.06*dY;
posrej=xx(1)-.08*dX;
posquitx=xx(2)+.08*dX;
posquity=yy(1)+.5*dY;
%Start drawing
decitex='\bfStart in box \rm or click your \bfdecision';
sectex='\bfDrawing \rmthe line';
htex=text(postx,posty,decitex,'color','k','backgroundcolor',.8*[1 1 1]);
hrej=text(posrej,yy(1)+.5*dY,{' ';'\bfReject last \rmand draw new'},'color','k',...
'backgroundcolor','y','rotation',90);
hdel=text(postx,posty-1.16*dY,{'\bfDelete all \rmlines';' '},'color','k',...
'backgroundcolor',[.8,.3 .3]);
hquit=text(posquitx,posquity,{'\bfFinish drawing';' '},'color','k',...
'backgroundcolor',[.2 1 .2],'rotation',90);
ht=[htex,hrej,hquit,hdel];
set(ht,'FontSize',20,'HorizontalAlignment','Center');
end
function parsque
NAR=numel(CE);
if NAR>2
cheer(2)
error('Too many inputs: ');
end
%Defaults
col='-k.5';
diagstep=100;
auto=true; %allows to set default line width
%Parse queue
for i=1:NAR
locv=CE{i};
locid=class(locv);
if strmatch(locid,'double','exact')
diagstep=locv;
end
if strmatch(locid,'char','exact')
col=locv;
auto=false;
end
end %end for
end %end parsque
function cheer(N)
if nargin<1
N=3;
end
s=[];
M=round(1000*unifrnd(.6,1,1,N));
for i=1:N
wid=M(i);
x=(0:wid)';
s=[s;sin((pi/wid)*x).^3.*sin(2*(x+x.^2/M(i)))];
end
sound(s/2);
end
end