Convert CurrentPoint to X and Y Value.

This is where we are getting stuck. We would appreciate any insight.
We have a basic figure (linear plot using: and we are using ‘CurrentPoint’ in the code to extract a value from the graph.
Here is the input:
function FcnName(src,evnt,a)
cp = get(gcf, 'CurrentPoint')
disp('click down!!!!')
disp(a)
end
Here is the output:
cp = 341 257
but what we need is the "real" x and y value. Is there a way to accomplish this?
Amanda

1 Comment

What are "real x and y values"? Realtive to the AXES, in screen coordinates or in the real world?

Sign in to comment.

 Accepted Answer

x=get(gco,'Xdata');
y=get(gco,'Ydata')

6 Comments

I didn't know about gco, but it appears to point to the current object on the figure/gui. If they clicked a button whose callback called some functions (like get() or whatever), then is the "current object" the button they just clicked on, or is it still the axes that they plotted to some time prior to that?
If you don't select any object, it will return an empty value. You must click inside the axis to point the plot. If you click outside the axis, gco will point a figure, then it will give an error.
Why use gco instead of gca? Also, I though XData returned the whole array, not just the point closest to the current point (the point where the user clicked to indicate which x,y point they wanted information on). Is that not right? Just trying to learn because I don't do that kind of thing often...
get(gca,'Xdata')
Error: The name 'Xdata' is not an accessible property for an instance of class 'axes'.
to get all axes properties, Type
set(gca)
To get just the current point coordinate, there is a function ginput
If you select the axes, gco do the same thing then gca, if you select a figure, gco is the same then gcf
I guess I'm still not seeing it. Let's say a user plotted, say, 1:10, and then the user clicked in the middle of the plot. The user wanted to retrieve the coordinate (5,5) but instead got some kind of pixel coordinates like 341,257 (like the poster said). I'm just not seeing how your code turns the 341,257 into 5,5. But whatever - I don't have the code like Amanda does and she said it works for her so that's what counts.

Sign in to comment.

More Answers (3)

Jan
Jan on 8 Feb 2013
Edited: Jan on 4 Nov 2019
I guess that you do not want the coordinates relative to the figure, but relative to the data in an AXES object. Then:
CP = get(gca, 'CurrentPoint');
x = CP(1);
y = CP(2);
The CurrentPoint property of the axes replies a 2x3 array, which defines the viewing line through a 3D scene. But in standard 2D view, the CP(1, 1:2) contain the current 2D position already. This property is the "location of last button click, in axes data units", see Doc: axes_props.

1 Comment

Thank you so much, Jan. You saved my life...orz

Sign in to comment.

Image Analyst
Image Analyst on 8 Feb 2013
Edited: Image Analyst on 8 Feb 2013
Amanda, give this a try. It will plot some data points, then ask you to click near one, and it will tell you which point of your data that you clicked closest to.
% Plot data - a line from (1,1) to (10,10).
h=plot(1:10, 'bs-')
grid on;
axis equal;
xlim([0 11]);
ylim([0 11]);
datacursormode on;
% Enlarge figure to full screen.
screenSize = get(0,'ScreenSize')
set(gcf, 'units','pixels','outerposition', screenSize);
% Ask user to click on a point.
uiwait(msgbox('Click near any data point'));
% Print the x,y coordinates - will be in plot coordinates
[x,y] = ginput(1) % Will be close to 5,5 but not exactly.
% Mark where they clicked with a cross.
hold on;
plot(x,y, 'r+', 'MarkerSize', 20, 'LineWidth', 3);
% Print the coordinate, but this time in figure space.
% Coordinates will be way different, like 267, 196 instead of 5,5.
cpFigure = get(gcf, 'CurrentPoint')
cpAxis = get(gca, 'CurrentPoint')
% Print coordinates on the plot.
label = sprintf('(%.1f, %.1f) = (%.1f, %.1f) in figure space', x, y, cpFigure(1), cpFigure(2));
text(x+.2, y, label);
% Tell use what ginput, cpFigure, and cpAxis are.
message = sprintf('ginput = (%.3f, %.3f)\nCP Axis = [%.3f, %.3f\n %.3f, %.3f]\nCP Figure = (%.3f, %.3f)\n',...
x, y, cpAxis(1,1), cpAxis(1,2), cpAxis(2,1), cpAxis(2,2), cpFigure(1), cpFigure(2));
uiwait(msgbox(message));
% Retrieve the x and y data from the plot
xdata = get(h, 'xdata')
ydata = get(h, 'ydata')
% Scan the actual ploted points, figuring out which one comes closest to 5,5
distances = sqrt((x-xdata).^2+(y-ydata).^2)
[minValue minIndex] = min(distances)
% Print the distances next to each data point
for k = 1 : length(xdata)
label = sprintf('D = %.2f', distances(k));
text(xdata(k)+.2, ydata(k), label, 'FontSize', 14);
end
% Draw a line from her point to the closest point.
plot([x xdata(minIndex)], [y, ydata(minIndex)], 'r-');
% Tell her what data point she clicked closest to
message = sprintf('You clicked closest to point (%d, %d)',...
xdata(minIndex), ydata(minIndex));
helpdlg(message);

7 Comments

Sometimes I get too overly optimistic when an answer is posted. Thanks a lot. This is working. I appreciate the help.
@IA and Amanda, I wrote code to do this a while back and then wondered why the heck it wasn't working and why what above won't work: If you're x-axis ranges from 1:10 and y-axis ranges from 1:10000, then a very small change in y has way more weight than x so clicking was consistently not working.
I had to rewrite the code so that each point was a unique line with a 'ButtonDownFcn' that did whatever it was I needed.
I was surprise that the 'ButtonDownFcn' was not used in the code. This gives me the overall view.
Sean, I tried it for 1-10,000 and it seemed to work, though I did have to remove the "axis equal" statement. I had put that in because of the way it scaled the x axis wider than the y axis and it looked like it wasn't picking the right "nearest point" even though it was, and the distance calculations proved it. When I put in axis equal it was obvious. So anyway, I'm not able to get the code to not work. If you tell me where to click such that it finds the wrong point, I'll try it.
Make sure you have a bunch of points that are whatever in 'x' but not in y
x = rand(1,500)*10;
y = rand(1,500)*10000;
Now click near a point that has a second point at about the same y but much different x.
I'll see if I can find my code.
OK I see what you mean. My code does calculate the closest point numerically but it may not APPEAR to be the closest point on the screen because it's so compressed vertically. So if you click on a point in the middle of the screen, the closest point may be only 0.5 away but that appears way on the other side of the plot, while one that appears right next to the point, but may actually be 50 units away, and that is probably the one the user wanted to specify. It's closer on the screen but farther away numerically.
Dear Image Analyst,
This was actually a great tutorial for what I was thinking if it was possible to do in matlab. Is it possible to extend this code for clicking in 3D and finding the closest data point? I appreciate your guidance...
Baha

Sign in to comment.

I think you just have to change gcf to gca.
The coordinates you are getting are relative to the whole figure object and not the current axes.
If you use:
cp = get(gca, 'CurrentPoint')
you should get the coordinates according to the X and Y axis assigned to the plot area

1 Comment

Since v2019a the datatips have been very intrusive. This feature snaps to the plot line and a small gray dot indicates the closest point on the line. If I hold the cursor, a datatip pops up with the X and Y values of the graph. It should be possible to retrieve these values. Idealy we shuld be able to suppress the datatip and keep the snap function and use the 'snapped' X and Y values in a function. All this would require getting hold of the handle of the datatip object. However, if I leave the graph and go to the command window (datatip still visible) I cannot find the datatip with
datatiphandle = findobj( gca, 'Type', 'datatip')
or with ch = get( gca, 'Children')
I can find datatip handles with
datatiphandle = findall(gcf,'Type','hggroup')
But these handles don't have the X and Y values reaily availabe and the property list does not look like the properies of a datatip generated by the function datatip. For one: the 'type' attribute is different.
How can we grab a datatip that we can see and is often annoyingly and persistently displayed over a line graph and either interogate it for X and Y line coorodinates or make it invisible?

Sign in to comment.

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!