Use Polyline to Create An Angle Measurement Tool

This example shows the steps need to create a three-point measurement tool using a Polyline ROI

Display Image and Polyline ROI

Display an image and a polyline at a right angle. We want to prompt the user to manipulate the polyline to measure angles of interest.

im = imread('gantrycrane.png');

% Display image in the axes
imshow(im)

% Get size of image
m = size(im,1);
n = size(im,2);

% Get center point of image for initial positioning
midy = ceil(m/2);
midx = ceil(n/2);

% Position first point vertically above the middle
firstx = midx;
firsty = midy - ceil(m/4);
lastx = midx + ceil(n/4);
lasty = midy;

% Add empty context menu to replace default menu
c = uicontextmenu;

% Create a two-segment right-angle polyline centered in the image
h = drawpolyline('Parent',gca,...
    'Position',[firstx,firsty;midx,midy;lastx,lasty],...
    'Label','Modify angle to begin...',...
    'Color',[0.8,0.2,0.2],...
    'UIContextMenu',c);

% Listen to event that fires as the ROI is being moved
addlistener(h,'MovingROI',@(src,evt) updateAngle(src,evt));

% Intercept attempts to add or remove vertices
addlistener(h,'AddingVertex',@(src,evt) storePositionInUserData(src,evt));
addlistener(h,'VertexAdded',@(src,evt) recallPositionInUserData(src,evt));
addlistener(h,'DeletingVertex',@(src,evt) storePositionInUserData(src,evt));
addlistener(h,'VertexDeleted',@(src,evt) recallPositionInUserData(src,evt));

Update Label in Callback

As the user reshapes the polyline, we want to recompute the angle and update the label displayed.

function updateAngle(src,evt)

% Get the current position
p = evt.CurrentPosition;

% Find the angle
v1 = [p(1,1)-p(2,1), p(1,2)-p(2,2)];
v2 = [p(3,1)-p(2,1), p(3,2)-p(2,2)];
theta = acos(dot(v1,v2)/(norm(v1)*norm(v2)));

% Convert it to degrees
angleDegrees = (theta * (180/pi));

% Update the Label to display the angle
src.Label = sprintf('(%1.0f) degrees',angleDegrees);

end

Prevent Users From Adding or Removing Vertices

The polyline allows users to add and remove vertices; however, an angle measurement tool assumes that there are only three vertices at any time. We want to add listeners to intercept when a user is attempting to add or remove a vertex. In the callback for the 'AddingVertex' and DeletingVertex' events, the vertex of interest has not yet been added or deleted. We will cached the current polyline position in the UserData property and restore it in the callback for the 'VertexAdded' and 'VertexDeleted' events. This will prevent the user from interactively adding or removing vertices for the polyline.

function storePositionInUserData(src,~)

% Before a vertex is added/removed, store the Position in the UserData 
% property
src.UserData = src.Position;

end

function recallPositionInUserData(src,~)

% Restore the previous Position to prevent users from adding/removing
% vertices
src.Position = src.UserData;

end

See Also

| |

Related Topics