Search code examples
matlabmatlab-figure

Three draggable points on a plot


I am trying to create a callback function(s) that does the following:

  1. A user clicks on a line
  2. Each click results in a small circle snapped to the nearest data point
  3. As a new data point (a new circle) is selected, a line is created between the two points (eventually, total of two lines between the three points)
  4. When the third data point is selected, a text box will appear that does a certain calculation based on the three sets of XY coordinates
  5. As the user drags around any of the three points, the calculation in the text box will be updated
  6. I'd like to have any many sets of three points and their associated text box as I want on different sections of the curve

I think I have to use "impoint" to generate the draggable points and to use "bsxfun" for the snapping. I have something in the similar context that uses "imline" and the functions are provided below if it's of any help.

function calc_slope(handle,event)

axis_h = findobj(gcf,'Type','axes');   
line = get(gco);

xdata = line.XData;
ydata = line.YData;

tb_h = text(0,0,'');

fcn_constr = @(pos) imline_snap(pos, [xdata(:) ydata(:)],tb_h); 

imline_h = imline(axis_h, 'PositionConstraintFcn', fcn_constr);

addlistener(imline_h, 'ObjectBeingDestroyed', @(obj,event) delete(tb_h));

function constr_pos = imline_snap(new_pos, positions, tb_h)

[~, ind1] = min(sum(bsxfun(@minus, new_pos(1,:), positions).^2, 2));
[~, ind2] = min(sum(bsxfun(@minus, new_pos(2,:), positions).^2, 2));

constr_pos = [positions(ind1,:); positions(ind2,:)];

    set(tb_h, 'String',...
              sprintf(['    \\DeltaY/\\DeltaX = ',...
                       num2str((constr_pos(2,2)-constr_pos(1,2))/(constr_pos(2,1)-constr_pos(1,1))),...
                       '\n    \\DeltaX = ',num2str(constr_pos(2,1)-constr_pos(1,1)),...
                       ', \\DeltaY = ',num2str(constr_pos(2,2)-constr_pos(1,2))]),...
              'Position', mean(constr_pos));

The core functions were written by @Luis Mendo and even now I can't understand how all these work: all credits to him. Can someone modify the script or create from scratch to accomplish the problem described above?


Solution

  • I resorted to using datacursormode and getCursorInfo. No lines or automatic updating, but points are snapped and draggable.