В этом примере показано, как создать интерактивный инструмент, отображающий угол между тремя вершинами в окупаемости инвестиций полилинии.
Угол можно изменить, щелкнув и перетащив вершины полилинии. Когда ROI перемещается, он транслирует событие с именем MovingROI. Добавляя прослушиватель для этого события и функцию обратного вызова, которая выполняется при возникновении события, инструмент может измерять и отображать изменения угла в реальном времени.
Чтение и отображение изображения.
im = imread('gantrycrane.png');
imshow(im)

Получение размера изображения.
[y,x,~] = size(im);
Получение координат центра изображения. В примере вершина инструмента измерения угла размещается в центре изображения.
midy = ceil(y/2); midx = ceil(x/2);
Укажите координаты первой точки в окупаемости инвестиций полилинии. В этом примере первая точка размещается в полилинии непосредственно над центром изображения.
firstx = midx; firsty = midy - ceil(y/4);
Укажите координаты третьей точки в окупаемости инвестиций полилинии. В этом примере третья точка размещается в полилинии непосредственно справа от центра изображения.
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. Эта пользовательская функция определена в разделе «Обновление метки угла с помощью функции обратного вызова».
addlistener(h,'MovingROI',@(src,evt) updateAngle(src,evt));
Полилинии ROI также поддерживают интерактивное добавление и удаление вершин. Однако инструмент измерения угла требует ровно три вершины в любой момент времени, поэтому сложение и удаление вершин являются нежелательными взаимодействиями с ROI. Добавьте прослушиватели, которые прослушивают добавление или удаление вершин. При попытке изменить число вершин соответствующий прослушиватель вызывает пользовательскую функцию обратного вызова для подавления изменения. Эти пользовательские функции, storePositionInUserData и recallPositionInUserData, определены в разделе «Предотвращение добавления или удаления вершин с помощью функций обратного вызова».
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));
Определите функцию обратного вызова, выполняемую при перемещении окупаемости инвестиций полилинии. Эта функция извлекает текущее положение трех вершин, вычисляет угол в градусах между вершинами и обновляет метку для отображения текущего угла поворота.
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 «» или «» StartVertex «». Эти события происходят непосредственно перед добавлением или удалением интересующей вершины из полилинии. Сохранить текущие три вершины полилинии в UserData собственность.
function storePositionInUserData(src,~) src.UserData = src.Position; end
Определите функцию обратного вызова, выполняемую при обнаружении прослушивателями событий VertexAdded или VertexDeleted. Эти события происходят сразу после добавления или удаления интересующей вершины из полилинии. Восстановление сохраненного набора из трех вершин полилинии в UserData собственность.
function recallPositionInUserData(src,~) src.Position = src.UserData; end
addlistener | drawpolyline | Polyline