Is it possible to create an interactive / editable 2D rectangle or polygon without additional toolboxes?

15 visualizaciones (últimos 30 días)
Hi all, I am trying to create a simple GUI which allows the user to draw shapes (rectanges / polygons) over an image. Drawing the shape is easy enough however I am battling to make them editable. From searching the net it appears that this is very easy to do if you have the image processing toolbox. I can't justify purchasing the whole toolbox just for this so I'm curious as to whether or not there is a simple alternative. I am not an advanced programmer but I am comfortable with callback function basics and keen to improve.
Perhaps there are some examples of this out there already?
Thank you, Tyron

Respuesta aceptada

Image Analyst
Image Analyst el 31 de Mayo de 2013
You can use rbbox(). It's not in any toolbox - it's in base MATLAB. Since it doesn't have little handles to drag around and doesn't require clicks to finish and ask for confirmation, after the user draws the box you just ask them if it's okay or if they want to redraw it. This will do a rectangle. Or you can use dragrect().
There is nothing like impoly() that's in base MATLAB that I know of.
  1 comentario
Sonomatic Australia
Sonomatic Australia el 31 de Mayo de 2013
Thank you for that Image Analyst. Practically your suggestion is fine and normally this would do the trick. However I would like to make the rectangle slightly more user friendly (drag and resize instead of redraw). It sounds fussy but we need to make our tools attractive to our technicians to get their buy in. I am happy to stick with rectangles now instead of polygons.
Here is my code again, I didn't post it correctly last time:
function InteractiveRectangle(x)
if nargin <1
x = 'start';
end
switch x
case 'start'
figure(1);
clf
axes('nextplot','replacechildren')
axis([0 5 0 5])
set(gca,'Units','Normalized') %or Pixels
set(gcf,'Units','Normalized') %or Pixels
%%Draw initial rectanlge
title('click and drag to draw rectangle')
set(gcf,'Pointer','crosshair')
k = waitforbuttonpress;
point1 = get(gca,'CurrentPoint'); % button down detected
finalRect = rbbox; % return figure units
point2 = get(gca,'CurrentPoint'); % button up detected
point1 = point1(1,1:2); % extract x and y
point2 = point2(1,1:2);
p1 = min(point1,point2); % calculate locations
offset = abs(point1-point2); % and dimensions
set(gcf,'Pointer','arrow')
x = round([p1(1) p1(1) p1(1)+offset(1) p1(1)+offset(1) p1(1)]);
y = round([p1(2) p1(2)+offset(2) p1(2)+offset(2) p1(2) p1(2)]);
%force line to be within axis limits (this should be moved to a separate
%function)
x_lims = get(gca, 'xlim');
y_lims = get(gca, 'ylim');
x(x<min(x_lims))=min(x_lims);
x(x>max(x_lims))=max(x_lims);
y(y<min(y_lims))=min(y_lims);
y(y>max(y_lims))=max(y_lims);
%Plot rectangle as rectangle object
% r1=rectangle('Position',rect,...
% 'LineWidth',1,...
% 'EdgeColor','red',...
% 'HandleVisibility','callback');
% Plot rectangle as line object
l1 = line(x,y);
set(l1,'Tag','Line1')
title('')
%%set(l1,'Buttondownfcn','drag2(''start'')') %Syntax for setting function in separate m file
%set(l1,'Buttondownfcn',{@drag2 ; 'start'}) %Syntax for setting function in the same m file
set(gcf,'WindowButtonMotionFcn',@wbmf)
% set(gca,'ButtonDownFcn','InteractiveRectangle(''gcf_bdf'')')
case 'gcf_bdf'
% disp('button pressed')
end
end
function in_bounds = getBounds(ax1, position)
% % Description : Return the bounds of the supplied axes and identify whether
% % supplied position is contained within axes bounds
x_lims = get(ax1, 'xlim');
y_lims = get(ax1, 'ylim');
in_bounds = (position(1,1) >= x_lims(1)) && ...
(position(1,1) <= x_lims(2)) && ...
(position(1,2) >= y_lims(1)) && ...
(position(1,2) <= y_lims(2));
end
function wbmf(src,evnt)
FP=get(src,'CurrentPoint');
pos1=get(gca,'Position');
% if FP(1) > pos1(1) & FP(1) < pos1(1)+pos1(3) & FP(2) > pos1(2) & FP(2) < pos1(2)+pos1(4) % cursor within axes
axlims=get(gca,'XLim');
aylims=get(gca,'YLim');
xscale=abs(diff(axlims))/pos1(3);
yscale=abs(diff(aylims))/pos1(4);
fp=[(FP(1)-pos1(1))*xscale , (FP(2)-pos1(2))*yscale];
l1 = findobj('tag','Line1');
XData = get(l1,'Xdata');
YData = get(l1,'Ydata');
[IN ON]=inpolygon(fp(1),fp(2),XData,YData);
if IN
set(gcf,'Pointer','fleur')
title('click and drag to move rectangle')
set(gca,'Buttondownfcn',{@drag1 ; 'start'}) %set windowbuttonmotionfnc to drag rectangle
else
set(gcf,'Pointer','arrow')
set(gca,'Buttondownfcn','')
end
%Cursor over vertices
if any(round(fp(1)*10)==round(XData*10)) & any(round(fp(2)*10)==round(YData*10))
set(l1,'Marker','o')
title('click and drag to resize rectangle')
set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner
%%Write code to distinguish rectangle corners
if round(fp(1)*10)==round(min(XData)*10) & round(fp(2)*10)==round(min(YData)*10)
set(gcf,'Pointer','botl')
set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner
elseif round(fp(1)*10)==round(max(XData)*10) & round(fp(2)*10)==round(max(YData)*10)
set(gcf,'Pointer','topr')
set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner
elseif round(fp(1)*10)==round(min(XData)*10) & round(fp(2)*10)==round(max(YData)*10)
set(gcf,'Pointer','topl')
set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner
elseif round(fp(1)*10)==round(max(XData)*10) & round(fp(2)*10)==round(min(YData)*10)
set(gcf,'Pointer','botr')
set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner
end
else
set(l1,'Marker','none')
end
%Cursor over edges (For rectangles not any polygon)
if round(fp(1)*10)==round(min(XData)*10) & fp(2) < max(YData) & fp(2) > min(YData)
set(gcf,'Pointer','left')
setappdata(gcf,'iedge',[1,2]);
set(l1,'Buttondownfcn',{@drag4 ; 'start'}) %set windowbuttonmotionfnc to drag side
elseif round(fp(1)*10)==round(max(XData)*10) & fp(2) < max(YData) & fp(2) > min(YData)
set(gcf,'Pointer','right')
setappdata(gcf,'iedge',[3,4]);
set(l1,'Buttondownfcn',{@drag4 ; 'start'}) %set windowbuttonmotionfnc to drag side
elseif round(fp(2)*10)==round(min(YData)*10) & fp(1) < max(XData) & fp(1) > min(XData)
set(gcf,'Pointer','bottom')
setappdata(gcf,'iedge',[1,4]);
set(l1,'Buttondownfcn',{@drag4 ; 'start'}) %set windowbuttonmotionfnc to drag side
elseif round(fp(2)*10)==round(max(YData)*10) & fp(1) < max(XData) & fp(1) > min(XData)
set(gcf,'Pointer','top')
setappdata(gcf,'iedge',[2,3]);
set(l1,'Buttondownfcn',{@drag4 ; 'start'}) %set windowbuttonmotionfnc to drag side
end
end
function drag1(src,evnt,action) % drag entire shape
switch(action)
case 'start',
set(gcf,'Pointer','hand')
l1 = findobj('tag','Line1');
set(l1,'Selected','on')
XData = get(l1,'Xdata');
YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1);
Y = currPt(1,2);
%find closest vertex
[minxy ixy]=min(sqrt((X-XData).^2+(Y-YData).^2));
setappdata(gcbf,'ixy',ixy);
fixedoffset=[currPt(1,1)-XData(ixy),currPt(1,2)-YData(ixy)];
setappdata(gcbf,'fixedoffset',fixedoffset);
WBMF_0=get(gcbf,'WindowButtonMotionFcn');
setappdata(gcbf,'WBMF_0',WBMF_0)
set(gcbf,'WindowButtonMotionFcn',{@drag1 ; 'move'})
set(gcbf,'WindowButtonUpFcn',{@drag1 ; 'stop'})
case 'move'
l1 = findobj('tag','Line1');
set(l1,'Selected','on')
XData = get(l1,'Xdata');
YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
ixy=getappdata(gcf,'ixy');
fixedoffset=getappdata(gcf,'fixedoffset');
XData=XData+(currPt(1,1)-XData(ixy)-fixedoffset(1));
YData=YData+(currPt(1,2)-YData(ixy)-fixedoffset(2));
set(l1,'Xdata',XData);
set(l1,'Ydata',YData);
case 'stop'
WBMF_0=getappdata(gcbf,'WBMF_0');
set(gcbf,'WindowButtonMotionFcn',WBMF_0)
set(gcbf,'WindowButtonUpFcn','')
set(gcf,'Pointer','fleur')
l1 = findobj('tag','Line1');
%Force line to be within axis limits
x = get(l1,'Xdata');
y = get(l1,'Ydata');
x_lims = get(gca, 'xlim');
y_lims = get(gca, 'ylim');
x(x<min(x_lims))=min(x_lims);
x(x>max(x_lims))=max(x_lims);
y(y<min(y_lims))=min(y_lims);
y(y>max(y_lims))=max(y_lims);
set(l1,'Xdata',x)
set(l1,'Ydata',y)
set(l1,'selected','off')
end
end
function drag2(src,evnt,action) % drag individual vertex
switch(action)
case 'start',
pntr=get(gcf,'Pointer');
setappdata(gcf,'pntr',pntr);
set(gcf,'Pointer','hand')
l1 = findobj('tag','Line1');
set(l1,'Selected','on')
XData = get(l1,'Xdata');
YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1);
Y = currPt(1,2);
%find closest vertex
[minxy ixy]=min(sqrt((X-XData).^2+(Y-YData).^2));
setappdata(gcf,'ixy',ixy);
WBMF_0=get(gcbf,'WindowButtonMotionFcn');
setappdata(gcbf,'WBMF_0',WBMF_0)
set(gcbf,'WindowButtonMotionFcn',{@drag2 ; 'move'})
set(gcbf,'WindowButtonUpFcn',{@drag2 ; 'stop'})
case 'move' %moves closest vertex from original click
l1 = findobj('tag','Line1');
set(l1,'Selected','on')
XData = get(l1,'Xdata');
YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1);
Y = currPt(1,2);
ixy=getappdata(gcf,'ixy');
XData(ixy)=X;
YData(ixy)=Y;
set(l1,'Xdata',XData)
set(l1,'Ydata',YData)
case 'stop'
WBMF_0=getappdata(gcbf,'WBMF_0');
set(gcbf,'WindowButtonMotionFcn',WBMF_0)
set(gcbf,'WindowButtonUpFcn','')
% pntr=getappdata(gcf,'pntr');
% set(gcf,'Pointer',pntr)
set(gcf,'Pointer','arrow')
l1 = findobj('tag','Line1');
%Force line to be within axis limits
x = get(l1,'Xdata');
y = get(l1,'Ydata');
x_lims = get(gca, 'xlim');
y_lims = get(gca, 'ylim');
x(x<min(x_lims))=min(x_lims);
x(x>max(x_lims))=max(x_lims);
y(y<min(y_lims))=min(y_lims);
y(y>max(y_lims))=max(y_lims);
set(l1,'Xdata',x)
set(l1,'Ydata',y)
set(l1,'selected','off')
end
end
function drag3(src,evnt,action) % drag rectangle corner
switch(action)
case 'start',
pntr=get(gcf,'Pointer');
setappdata(gcf,'pntr',pntr);
set(gcf,'Pointer','hand')
l1 = findobj('tag','Line1');
set(l1,'Selected','on')
XData = get(l1,'Xdata');
YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1);
Y = currPt(1,2);
%find closest vertex
[minxy ixy]=min(sqrt((X-XData).^2+(Y-YData).^2));
setappdata(gcf,'ixy',ixy);
WBMF_0=get(gcbf,'WindowButtonMotionFcn');
setappdata(gcbf,'WBMF_0',WBMF_0)
set(gcbf,'WindowButtonMotionFcn',{@drag3 ; 'move'})
set(gcbf,'WindowButtonUpFcn',{@drag3 ; 'stop'})
case 'move' %moves closest vertex from original click
l1 = findobj('tag','Line1');
set(l1,'Selected','on')
XData = get(l1,'Xdata');
YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1);
Y = currPt(1,2);
ixy=getappdata(gcf,'ixy');
if ixy==1 | ixy==5
XData([1,2,5])=X;
YData([1,4,5])=Y;
elseif ixy == 2
XData([1,2,5])=X;
YData([2,3])=Y;
elseif ixy == 3
XData([3,4])=X;
YData([2,3])=Y;
elseif ixy == 4
XData([3,4])=X;
YData([1,4,5])=Y;
end
set(l1,'Xdata',XData)
set(l1,'Ydata',YData)
case 'stop'
WBMF_0=getappdata(gcbf,'WBMF_0');
set(gcbf,'WindowButtonMotionFcn',WBMF_0)
set(gcbf,'WindowButtonUpFcn','')
% pntr=getappdata(gcf,'pntr');
% set(gcf,'Pointer',pntr)
set(gcf,'Pointer','arrow')
l1 = findobj('tag','Line1');
%Force line to be within axis limits
x = get(l1,'Xdata');
y = get(l1,'Ydata');
x_lims = get(gca, 'xlim');
y_lims = get(gca, 'ylim');
x(x<min(x_lims))=min(x_lims);
x(x>max(x_lims))=max(x_lims);
y(y<min(y_lims))=min(y_lims);
y(y>max(y_lims))=max(y_lims);
set(l1,'Xdata',x)
set(l1,'Ydata',y)
set(l1,'selected','off')
end
end
function drag4(src,evnt,action) % drag rectangle edges
switch(action)
case 'start',
pntr=get(gcf,'Pointer');
setappdata(gcf,'pntr',pntr);
set(gcf,'Pointer','hand')
l1 = findobj('tag','Line1');
set(l1,'Selected','on')
%find closest edge
%This has actually been done already in "wbmf"
WBMF_0=get(gcbf,'WindowButtonMotionFcn');
setappdata(gcbf,'WBMF_0',WBMF_0)
set(gcbf,'WindowButtonMotionFcn',{@drag4 ; 'move'})
set(gcbf,'WindowButtonUpFcn',{@drag4 ; 'stop'})
case 'move' %moves closest vertex from original click
l1 = findobj('tag','Line1');
set(l1,'Selected','on')
XData = get(l1,'Xdata');
YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1);
Y = currPt(1,2);
% Retrieve edge
iedge=getappdata(gcf,'iedge');
if all(iedge == [1,2])
XData([1,2,5])=X;
elseif all(iedge == [2,3])
YData([2,3])=Y;
elseif all(iedge == [3,4])
XData([3,4])=X;
elseif all(iedge == [1,4])
YData([1,4,5])=Y;
end
set(l1,'Xdata',XData)
set(l1,'Ydata',YData)
case 'stop'
WBMF_0=getappdata(gcbf,'WBMF_0');
set(gcbf,'WindowButtonMotionFcn',WBMF_0)
set(gcbf,'WindowButtonUpFcn','')
% pntr=getappdata(gcf,'pntr');
% set(gcf,'Pointer',pntr)
set(gcf,'Pointer','arrow')
l1 = findobj('tag','Line1');
%Force line to be within axis limits
x = get(l1,'Xdata');
y = get(l1,'Ydata');
x_lims = get(gca, 'xlim');
y_lims = get(gca, 'ylim');
x(x<min(x_lims))=min(x_lims);
x(x>max(x_lims))=max(x_lims);
y(y<min(y_lims))=min(y_lims);
y(y>max(y_lims))=max(y_lims);
set(l1,'Xdata',x)
set(l1,'Ydata',y)
set(l1,'selected','off')
end
end

Iniciar sesión para comentar.

Más respuestas (1)

Sonomatic Australia
Sonomatic Australia el 31 de Mayo de 2013
I've managed to make a draggable, resize-able rectangle. This is far from perfect but it is a good start to what I need. I guess it's very "inefficient" coding but I'm not worried about that at this stage. Here is the code in case anybody finds it useful or in case anybody is willing to provide some advice for the proper way to go about this kind of programming.
function InteractiveRectangle(x) if nargin <1 x = 'start'; end
switch x case 'start' figure(1); clf axes('nextplot','replacechildren') axis([0 5 0 5]) set(gca,'Units','Normalized') %or Pixels set(gcf,'Units','Normalized') %or Pixels
%% Draw initial rectanlge title('click and drag to draw rectangle') set(gcf,'Pointer','crosshair') k = waitforbuttonpress; point1 = get(gca,'CurrentPoint'); % button down detected finalRect = rbbox; % return figure units point2 = get(gca,'CurrentPoint'); % button up detected point1 = point1(1,1:2); % extract x and y point2 = point2(1,1:2); p1 = min(point1,point2); % calculate locations offset = abs(point1-point2); % and dimensions set(gcf,'Pointer','arrow') x = round([p1(1) p1(1) p1(1)+offset(1) p1(1)+offset(1) p1(1)]) y = round([p1(2) p1(2)+offset(2) p1(2)+offset(2) p1(2) p1(2)])
%force line to be within axis limits (this should be moved to a separate %function) x_lims = get(gca, 'xlim'); y_lims = get(gca, 'ylim'); x(x<min(x_lims))=min(x_lims); x(x>max(x_lims))=max(x_lims); y(y<min(y_lims))=min(y_lims); y(y>max(y_lims))=max(y_lims);
%Plot rectangle as rectangle object % r1=rectangle('Position',rect,... % 'LineWidth',1,... % 'EdgeColor','red',... % 'HandleVisibility','callback');
% Plot rectangle as line object l1 = line(x,y); set(l1,'Tag','Line1') title('') %%set(l1,'Buttondownfcn','drag2(''start'')') %Syntax for setting function in separate m file %set(l1,'Buttondownfcn',{@drag2 ; 'start'}) %Syntax for setting function in the same m file set(gcf,'WindowButtonMotionFcn',@wbmf)
% set(gca,'ButtonDownFcn','InteractiveRectangle(''gcf_bdf'')') case 'gcf_bdf' % disp('button pressed') end end
function in_bounds = getBounds(ax1, position) % % Description : Return the bounds of the supplied axes and identify whether % % supplied position is contained within axes bounds x_lims = get(ax1, 'xlim'); y_lims = get(ax1, 'ylim');
in_bounds = (position(1,1) >= x_lims(1)) && ...
(position(1,1) <= x_lims(2)) && ...
(position(1,2) >= y_lims(1)) && ...
(position(1,2) <= y_lims(2));
end
function wbmf(src,evnt) FP=get(src,'CurrentPoint'); pos1=get(gca,'Position');
% if FP(1) > pos1(1) & FP(1) < pos1(1)+pos1(3) & FP(2) > pos1(2) & FP(2) < pos1(2)+pos1(4) % cursor within axes axlims=get(gca,'XLim'); aylims=get(gca,'YLim'); xscale=abs(diff(axlims))/pos1(3); yscale=abs(diff(aylims))/pos1(4); fp=[(FP(1)-pos1(1))*xscale , (FP(2)-pos1(2))*yscale];
l1 = findobj('tag','Line1'); XData = get(l1,'Xdata'); YData = get(l1,'Ydata');
[IN ON]=inpolygon(fp(1),fp(2),XData,YData);
if IN set(gcf,'Pointer','fleur') title('click and drag to move rectangle') set(gca,'Buttondownfcn',{@drag1 ; 'start'}) %set windowbuttonmotionfnc to drag rectangle else set(gcf,'Pointer','arrow') set(gca,'Buttondownfcn','') end
%Cursor over vertices if any(round(fp(1)*10)==round(XData*10)) & any(round(fp(2)*10)==round(YData*10)) set(l1,'Marker','o') title('click and drag to resize rectangle') set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner %%Write code to distinguish rectangle corners if round(fp(1)*10)==round(min(XData)*10) & round(fp(2)*10)==round(min(YData)*10) set(gcf,'Pointer','botl') set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner elseif round(fp(1)*10)==round(max(XData)*10) & round(fp(2)*10)==round(max(YData)*10) set(gcf,'Pointer','topr') set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner elseif round(fp(1)*10)==round(min(XData)*10) & round(fp(2)*10)==round(max(YData)*10) set(gcf,'Pointer','topl') set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner elseif round(fp(1)*10)==round(max(XData)*10) & round(fp(2)*10)==round(min(YData)*10) set(gcf,'Pointer','botr') set(l1,'Buttondownfcn',{@drag3 ; 'start'}) %set windowbuttonmotionfnc to drag corner end
else set(l1,'Marker','none') end
%Cursor over edges (For rectangles not any polygon) if round(fp(1)*10)==round(min(XData)*10) & fp(2) < max(YData) & fp(2) > min(YData) set(gcf,'Pointer','left') setappdata(gcf,'iedge',[1,2]); set(l1,'Buttondownfcn',{@drag4 ; 'start'}) %set windowbuttonmotionfnc to drag side elseif round(fp(1)*10)==round(max(XData)*10) & fp(2) < max(YData) & fp(2) > min(YData) set(gcf,'Pointer','right') setappdata(gcf,'iedge',[3,4]); set(l1,'Buttondownfcn',{@drag4 ; 'start'}) %set windowbuttonmotionfnc to drag side elseif round(fp(2)*10)==round(min(YData)*10) & fp(1) < max(XData) & fp(1) > min(XData) set(gcf,'Pointer','bottom') setappdata(gcf,'iedge',[1,4]); set(l1,'Buttondownfcn',{@drag4 ; 'start'}) %set windowbuttonmotionfnc to drag side elseif round(fp(2)*10)==round(max(YData)*10) & fp(1) < max(XData) & fp(1) > min(XData) set(gcf,'Pointer','top') setappdata(gcf,'iedge',[2,3]); set(l1,'Buttondownfcn',{@drag4 ; 'start'}) %set windowbuttonmotionfnc to drag side end
end
function drag1(src,evnt,action) % drag entire shape switch(action) case 'start', set(gcf,'Pointer','hand') l1 = findobj('tag','Line1'); set(l1,'Selected','on') XData = get(l1,'Xdata'); YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1); Y = currPt(1,2);
%find closest vertex [minxy ixy]=min(sqrt((X-XData).^2+(Y-YData).^2)); setappdata(gcbf,'ixy',ixy);
fixedoffset=[currPt(1,1)-XData(ixy),currPt(1,2)-YData(ixy)]; setappdata(gcbf,'fixedoffset',fixedoffset);
WBMF_0=get(gcbf,'WindowButtonMotionFcn'); setappdata(gcbf,'WBMF_0',WBMF_0)
set(gcbf,'WindowButtonMotionFcn',{@drag1 ; 'move'}) set(gcbf,'WindowButtonUpFcn',{@drag1 ; 'stop'})
case 'move' l1 = findobj('tag','Line1'); set(l1,'Selected','on') XData = get(l1,'Xdata'); YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint'); ixy=getappdata(gcf,'ixy'); fixedoffset=getappdata(gcf,'fixedoffset');
XData=XData+(currPt(1,1)-XData(ixy)-fixedoffset(1)); YData=YData+(currPt(1,2)-YData(ixy)-fixedoffset(2));
set(l1,'Xdata',XData); set(l1,'Ydata',YData);
case 'stop' WBMF_0=getappdata(gcbf,'WBMF_0'); set(gcbf,'WindowButtonMotionFcn',WBMF_0) set(gcbf,'WindowButtonUpFcn','') set(gcf,'Pointer','fleur') l1 = findobj('tag','Line1'); %Force line to be within axis limits x = get(l1,'Xdata'); y = get(l1,'Ydata'); x_lims = get(gca, 'xlim'); y_lims = get(gca, 'ylim'); x(x<min(x_lims))=min(x_lims); x(x>max(x_lims))=max(x_lims); y(y<min(y_lims))=min(y_lims); y(y>max(y_lims))=max(y_lims); set(l1,'Xdata',x) set(l1,'Ydata',y) set(l1,'selected','off') end end
function drag2(src,evnt,action) % drag individual vertex switch(action) case 'start', pntr=get(gcf,'Pointer'); setappdata(gcf,'pntr',pntr); set(gcf,'Pointer','hand') l1 = findobj('tag','Line1'); set(l1,'Selected','on') XData = get(l1,'Xdata'); YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1); Y = currPt(1,2);
%find closest vertex [minxy ixy]=min(sqrt((X-XData).^2+(Y-YData).^2)); setappdata(gcf,'ixy',ixy);
WBMF_0=get(gcbf,'WindowButtonMotionFcn'); setappdata(gcbf,'WBMF_0',WBMF_0)
set(gcbf,'WindowButtonMotionFcn',{@drag2 ; 'move'}) set(gcbf,'WindowButtonUpFcn',{@drag2 ; 'stop'})
case 'move' %moves closest vertex from original click l1 = findobj('tag','Line1'); set(l1,'Selected','on') XData = get(l1,'Xdata'); YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint'); X = currPt(1,1); Y = currPt(1,2);
ixy=getappdata(gcf,'ixy');
XData(ixy)=X; YData(ixy)=Y;
set(l1,'Xdata',XData) set(l1,'Ydata',YData)
case 'stop' WBMF_0=getappdata(gcbf,'WBMF_0'); set(gcbf,'WindowButtonMotionFcn',WBMF_0) set(gcbf,'WindowButtonUpFcn','') % pntr=getappdata(gcf,'pntr'); % set(gcf,'Pointer',pntr) set(gcf,'Pointer','arrow') l1 = findobj('tag','Line1'); %Force line to be within axis limits x = get(l1,'Xdata'); y = get(l1,'Ydata'); x_lims = get(gca, 'xlim'); y_lims = get(gca, 'ylim'); x(x<min(x_lims))=min(x_lims); x(x>max(x_lims))=max(x_lims); y(y<min(y_lims))=min(y_lims); y(y>max(y_lims))=max(y_lims); set(l1,'Xdata',x) set(l1,'Ydata',y) set(l1,'selected','off') end end
function drag3(src,evnt,action) % drag rectangle corner switch(action) case 'start', pntr=get(gcf,'Pointer'); setappdata(gcf,'pntr',pntr); set(gcf,'Pointer','hand') l1 = findobj('tag','Line1'); set(l1,'Selected','on') XData = get(l1,'Xdata'); YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint');
X = currPt(1,1); Y = currPt(1,2);
%find closest vertex [minxy ixy]=min(sqrt((X-XData).^2+(Y-YData).^2)); setappdata(gcf,'ixy',ixy);
WBMF_0=get(gcbf,'WindowButtonMotionFcn'); setappdata(gcbf,'WBMF_0',WBMF_0)
set(gcbf,'WindowButtonMotionFcn',{@drag3 ; 'move'}) set(gcbf,'WindowButtonUpFcn',{@drag3 ; 'stop'})
case 'move' %moves closest vertex from original click l1 = findobj('tag','Line1'); set(l1,'Selected','on') XData = get(l1,'Xdata'); YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint'); X = currPt(1,1); Y = currPt(1,2);
ixy=getappdata(gcf,'ixy');
if ixy==1 | ixy==5 XData([1,2,5])=X; YData([1,4,5])=Y; elseif ixy == 2 XData([1,2,5])=X; YData([2,3])=Y; elseif ixy == 3 XData([3,4])=X; YData([2,3])=Y; elseif ixy == 4 XData([3,4])=X; YData([1,4,5])=Y; end
set(l1,'Xdata',XData) set(l1,'Ydata',YData)
case 'stop' WBMF_0=getappdata(gcbf,'WBMF_0'); set(gcbf,'WindowButtonMotionFcn',WBMF_0) set(gcbf,'WindowButtonUpFcn','') % pntr=getappdata(gcf,'pntr'); % set(gcf,'Pointer',pntr) set(gcf,'Pointer','arrow') l1 = findobj('tag','Line1'); %Force line to be within axis limits x = get(l1,'Xdata'); y = get(l1,'Ydata'); x_lims = get(gca, 'xlim'); y_lims = get(gca, 'ylim'); x(x<min(x_lims))=min(x_lims); x(x>max(x_lims))=max(x_lims); y(y<min(y_lims))=min(y_lims); y(y>max(y_lims))=max(y_lims); set(l1,'Xdata',x) set(l1,'Ydata',y) set(l1,'selected','off') end end
function drag4(src,evnt,action) % drag rectangle edges switch(action) case 'start', pntr=get(gcf,'Pointer'); setappdata(gcf,'pntr',pntr); set(gcf,'Pointer','hand') l1 = findobj('tag','Line1'); set(l1,'Selected','on') %find closest edge %This has actually been done already in "wbmf"
WBMF_0=get(gcbf,'WindowButtonMotionFcn'); setappdata(gcbf,'WBMF_0',WBMF_0)
set(gcbf,'WindowButtonMotionFcn',{@drag4 ; 'move'}) set(gcbf,'WindowButtonUpFcn',{@drag4 ; 'stop'})
case 'move' %moves closest vertex from original click l1 = findobj('tag','Line1'); set(l1,'Selected','on') XData = get(l1,'Xdata'); YData = get(l1,'Ydata');
currPt=get(gca,'CurrentPoint'); X = currPt(1,1); Y = currPt(1,2);
% Retrieve edge iedge=getappdata(gcf,'iedge');
if all(iedge == [1,2]) XData([1,2,5])=X; elseif all(iedge == [2,3]) YData([2,3])=Y; elseif all(iedge == [3,4]) XData([3,4])=X; elseif all(iedge == [1,4]) YData([1,4,5])=Y; end
set(l1,'Xdata',XData) set(l1,'Ydata',YData)
case 'stop' WBMF_0=getappdata(gcbf,'WBMF_0'); set(gcbf,'WindowButtonMotionFcn',WBMF_0) set(gcbf,'WindowButtonUpFcn','') % pntr=getappdata(gcf,'pntr'); % set(gcf,'Pointer',pntr) set(gcf,'Pointer','arrow') l1 = findobj('tag','Line1'); %Force line to be within axis limits x = get(l1,'Xdata'); y = get(l1,'Ydata'); x_lims = get(gca, 'xlim'); y_lims = get(gca, 'ylim'); x(x<min(x_lims))=min(x_lims); x(x>max(x_lims))=max(x_lims); y(y<min(y_lims))=min(y_lims); y(y>max(y_lims))=max(y_lims); set(l1,'Xdata',x) set(l1,'Ydata',y) set(l1,'selected','off') end end
Thank you, Tyron

Productos

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by