In the previous post, we look at how we can draw different shapes on an axes using context menu and the MATLAB build-in function such as imline, imrect, etc.
The nice thing about the build-in functions is that they are fully implemented, meaning that they can be resized, dragged, and they even have context menu on their own which allows one to change the color and some other properties.
However, one thing I hate about the functions is the little rectangle boxes appear as the end points. I understand they are there to show you where you can click to move the points, but they should at least provide an option to turn the rectangle boxes visible or invisible. I fail to see any benefits of having the rectangle boxes on the final print out. I tried and failed to find any ways to remove the rectangle boxes, so in this post, we are going to code our own function for drawing the different shapes, without the annoying rectangles. (TAKE THAT!!! MATHWORKS).
The context menu created in the previous post can be re-used here. Instead of calling the imline or imrect functions when the corresponding menu items are selected, we are just going to create our own function to draw the desired shapes. Note that at this point, we will not be worry about all the fancy stuff, such as the figure pointer, line color, ability to resize, etc.
Design of the action sequence:
1. User selects "Line" from the context menu of the axes, which activates the line drawing mode.
2. Whenever the button is pressed in the line drawing mode, a line object is created on the axes.
3. As the user moves the mouse on the axes while holding the button down, the line object is continuously updated with the current location as the end point.
4. Whenever the users release the button, the line object is finalized and the line drawing mode ends.
The draw_line function shown at the bottom can fulfill the action sequence described above. Note that we are using WindowButtonDownFcn, WindowButtonMotionFcn and WindowButtonUpFcn to track the various mouse actions, and the corresponding GUI response is realized using nested/sub functions. You can try out this function easily using the code "plot(rand(1,10)); draw_line(fh,ah);". To implement functions that draw other shapes, the same structure can be followed, and changes only have to be made for the drawing of the shapes, which can be complicated at times depending on what you want to draw.
Video demo
The sample GUI can be downloaded here.
function draw_line(fh, ah)
% DRAW_LINE(FH, AH) draws a line on an existing axes interactively.
%
% Input:
% fh - handle of the figure that contains the axes
% ah - handle of the axes to be drawn on
%
% Wei Shang
% wei.shang@unb.ca
% University of New Brunswick
% get the boundaries on the axes
x_bounds = get(ah, 'xlim'); y_bounds = get(ah, 'ylim');
% enter line drawing mode by attaching buttonDown function
set(fh, 'WindowButtonDownFcn', @buttonDown);
function buttonDown(fh, dummy)
% This function is called when the mouse button is pressed.
% It will create a line object based on the location of where the
% button pressed action occured.
% get the location of the action
p = get(ah,'currentpoint');
x1 = p(1,1); y1 = p(1,2);
% create a line object that starts and ends at the same point.
lh = line([x1,x1], [y1,y1], 'linestyle', ':');
% atttach buttonMove function
set(fh,'WindowButtonMotionFcn',@buttonMove);
% attach buttonUp function
set(fh,'WindowButtonUpFcn', @buttonUp);
function buttonMove(fh, dummy)
% This function is called when the mouse button moved while
% being pressed.
% obtain end points of the line
X = get(lh,'XData'); Y = get(lh,'YData');
% obtain new points as the new mouse pointer location
p = get(ah,'currentpoint');
x2 = p(1,1); y2 = p(1,2);
% check and make sure they are within the bounds, if not force
% the end point to be within the bound
if x2 < x_bounds(1)
x2 = x_bounds(1);
elseif x2 > x_bounds(2);
x2 = x_bounds(2);
end
if y2 < y_bounds(1)
y2 = y_bounds(1);
elseif y2 > y_bounds(2)
y2 = y_bounds(2);
end
% update the line object with the
X(2) = x2; Y(2) = y2;
set(lh, 'XData', X, 'YData', Y);
end % ends buttonMove function
function buttonUp(fh, dummy)
% This function finalize the line object and ends line drawing
% mode.
% set line object's line style to solid line
set(lh,'linestyle','-');
% set various mouse actions to null
set(fh, 'WindowButtonMotionFcn', '');
set(fh, 'WindowButtonUpFcn', '');
set(fh, 'WindowButtonDownFcn', '');
end % ends buttonUp function
end % ends buttonDown function
end % ends draw_line function
No comments:
Post a Comment