fnery
fnery

Reputation: 758

MATLAB: How to store clicked coordinates using ButtonDownFcn

Goal: To perform several clicks in one figure, containing an image displayed with imshow and save the coordinates of the "clicked" point(s), to be used in further operations.

Notes: I know about the functions getpts/ginput but I would like to perform this without using them. Is this possible using ButtonDownFcn? (see the following code)

function testClicks
img = ones(300); % image to display
h   = imshow(img,'Parent',gca);
set(h,'ButtonDownFcn',{@ax_bdfcn});

function ax_bdfcn(varargin)
a = get(gca,'CurrentPoint');
x = a(1,1);
y = a(1,2);

At this stage the variables x and y only "live" inside ax_bdfcn. How can I make them available in the testClicks function? Is this possible using ButtonDownFcn? Is this a good approach?

Thanks a lot.

EDIT1: Thanks for the answer Shai. But I still cannot accomplish what I intended.

function [xArray, yArray] = testClicks()
img = ones(300); % image to display
h   = imshow(img,'Parent',gca);
x = [];
y = [];
xArray = [];
yArray = [];
stop = 0;
while stop == 0;
    set(h,'ButtonDownFcn',{@ax_bdfcn});
    xArray = [xArray x];
    yArray = [yArray y];
        if length(xArray)>15
            stop = 1;
        end
end

    function ax_bdfcn(varargin)
        a = get(gca, 'CurrentPoint');
        assignin('caller', 'x',  a(1,1) );
        assignin('caller', 'y',  a(1,2) );
    end
end % must have end for nested functions

This code (buggy!) is the closest I can get to what I want (after all the clicking, having an array with the x and y coordinates of the clicked points). I am clealy not understanding the mechanics for the implementation of this task. Any help?

Upvotes: 2

Views: 5924

Answers (1)

Shai
Shai

Reputation: 114796

There are several ways

  1. Using nested functions

    function testClicks
       img = ones(300); % image to display
       h   = imshow(img,'Parent',gca);
       set(h,'ButtonDownFcn',{@ax_bdfcn});
       x = []; % define "scope" of x and y 
       y = [];  
    
       % call back as nested function
       function ax_bdfcn(varargin)
           a = get(gca,'CurrentPoint');
           x = a(1,1); % set x and y at caller scope due to "nested"ness of function
           y = a(1,2);
       end  % close nested function
    end % must have end for nested functions
    
  2. Using assignin

    function ax_bdfcn(varargin)
         a = get(gca, 'CurrentPoint');
         assignin('caller', 'x',  a(1) );
         assignin('caller', 'y',  a(2) ); 
    
  3. Using 'UserData' property of figure handle

    function ax_bdfcn(varargin)
         a = get(gca, 'CurrentPoint');
         set( gcf, 'UserData', a(1:2) );
    

    'UserData' can be accessed (as long as the figure is alive) using cp = get( gcf, 'UserData');.

EDIT:
An example of a way to "communicate" the clicked locations to 'base' workspace

function ax_bdfcn(varargin)
   a = get(gca,'CurrentPoint');
   % the hard part - assign points to base
   if evalin('base', 'exist(''xArray'',''var'')')
      xArray = evalin('base','xArray');
   else 
      xArray = [];
   end
   xArray = [xArray a(1)]; % add the point
   assignin('base','xArray',xArray); % save to base
   % do the same for yArray

After calling testClicks there are NO xArray or yArray variables in the workspace (at least there shouldn't). After the first click these two variables will "miraculously" be created. After every other click these two arrays will increase their size until you close the figure.

Upvotes: 3

Related Questions