В этом примере показано, как создать интерактивный инструмент, который отображает угол между тремя вершинами в полилинейном ROI.
Можно изменить угол путем перетаскивания полилинейных вершин. Когда ROI перемещается, он широковещательно передает событие под названием MovingROI. Путем добавления прослушивателя для того события и функции обратного вызова, которая выполняется, когда событие имеет место, инструмент может измерить и отобразить изменения в углу в режиме реального времени.
Считайте и отобразите изображение.
im = imread('gantrycrane.png');
imshow(im)
Получите размер изображения.
[y,x,~] = size(im);
Получите координаты центра изображения. Пример помещает вершину углового инструмента измерения в центре изображения.
midy = ceil(y/2); midx = ceil(x/2);
Задайте координаты первой точки в полилинейном ROI. Этот пример помещает первую точку в ломаную линию непосредственно выше центра изображения.
firstx = midx; firsty = midy - ceil(y/4);
Задайте координаты третьей точки в полилинейном ROI. Этот пример помещает третью точку в ломаную линию непосредственно справа от центра изображения.
lastx = midx + ceil(x/4); lasty = midy;
Создайте пустое контекстное меню, чтобы заменить меню по умолчанию.
c = uicontextmenu;
Чертите ломаную линию красного цвета по изображению. Задайте координаты этих трех вершин и добавьте метку с инструкциями взаимодействовать с ломаной линией.
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);
Добавьте прослушиватель, который прислушивается к перемещению ROI. Когда прослушиватель обнаруживает перемещение, он вызывает пользовательскую функцию обратного вызова updateAngle
. Эта пользовательская функция задана в разделе "Update Angle Label Using Callback Function".
addlistener(h,'MovingROI',@(src,evt) updateAngle(src,evt));
Полилинейные ROI также поддерживают интерактивное сложение и удаление вершин. Однако угловой инструмент измерения требует точно трех вершин в любое время, таким образом, сложение и удаление вершин являются нежелательными взаимодействиями с ROI. Добавьте прослушиватели, которые прислушиваются к сложению или удалению вершин. Когда вы пытаетесь изменить количество вершин, соответствующий прослушиватель вызывает пользовательскую функцию обратного вызова, чтобы подавить изменение. Эти пользовательские функции, storePositionInUserData
и recallPositionInUserData
, заданы в разделе "Prevent Addition or Deletion of Vertices Using Callback Functions".
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));
Задайте функцию обратного вызова, которая выполняется, когда полилинейный ROI перемещается. Эта функция получает текущее положение этих трех вершин, вычисляет угол в градусах между вершинами и обновляет метку, чтобы отобразить текущий угол поворота.
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 the angle to degrees angleDegrees = (theta * (180/pi)); % Update the label to display the angle src.Label = sprintf('(%1.0f) degrees',angleDegrees); end
Задайте функцию обратного вызова, которая выполняется, когда прослушиватели обнаруживают события 'AddingVertex' или 'DeletingVertex'. Эти события сразу имеют место, прежде чем вершина интереса добавлена к или удалена из ломаной линии. Сохраните текущие три полилинейных вершины в UserData
свойство.
function storePositionInUserData(src,~) src.UserData = src.Position; end
Задайте функцию обратного вызова, которая выполняется, когда прослушиватели обнаруживают события 'VertexAdded' или 'VertexDeleted'. Эти события сразу имеют место после того, как вершина интереса добавлена к или удалена из ломаной линии. Восстановите сохраненный набор трех полилинейных вершин в UserData
свойство.
function recallPositionInUserData(src,~) src.Position = src.UserData; end
addlistener
| drawpolyline
| Polyline