KS0232
KS0232

Reputation: 157

Getting clicked point coordinates in 3D figure Matlab

I have a 3D figure in Matlab, let's assume it's sphere. What I need, is to get the X, Y, Z values of the point on surface, that I click with the mouse.

r = 10;
[X,Y,Z] = sphere(50); 
X2 = X * r;
Y2 = Y * r;
Z2 = Z * r;
figure();
props.FaceColor = 'texture';
props.EdgeColor = 'none';
props.FaceLighting = 'phong';
sphere = surf(X2,Y2,Z2,props);
axis equal
hold on

clicked_point = [?,?,?];

enter image description here

So in this example I want the clicked_point to be equal to [-3.445,-7.32,5.878].

I've tried with such solution:

clear all;
close all;
r = 10;
[X,Y,Z] = sphere(50);
X2 = X * r;
Y2 = Y * r;
Z2 = Z * r;
fig = figure();
props.FaceColor = 'texture';
props.EdgeColor = 'none';
props.FaceLighting = 'phong';
sphere = surf(X2,Y2,Z2,props);
axis equal

dcm_obj = datacursormode(fig);
set(dcm_obj,'DisplayStyle','datatip',...
'SnapToDataVertex','off','Enable','on')
c_info = getCursorInfo(dcm_obj);

while length(c_info) < 1
    datacursormode on
    c_info = getCursorInfo(dcm_obj);
end

But after that I can't even click on the sphere to display any data on figure. How can I get X, Y, Z in script? If not, how can I detect that the mouse click has already occured in Matlab?

Upvotes: 2

Views: 710

Answers (1)

Hoki
Hoki

Reputation: 11812

It is not clear whether you want the clicked_point variable to reside in the base workspace or if that is going to be part of a GUI.

I'll give you a solution for the base workspace.

The trick is to just add the bit of code you need to the UpdateFcn of the datacursormode object.

Save a function getClickedPoint.m somewhere visible on your MATLAB path:

function output_txt = getClickedPoint(obj,event_obj)
% Display the position of the data cursor
% obj          Currently not used (empty)
% event_obj    Handle to event object
% output_txt   Data cursor text string (string or cell array of strings).

pos = get(event_obj,'Position');
output_txt = {['X: ',num2str(pos(1),4)],...
    ['Y: ',num2str(pos(2),4)]};

% If there is a Z-coordinate in the position, display it as well
if length(pos) > 2
    output_txt{end+1} = ['Z: ',num2str(pos(3),4)];
end

assignin('base','clicked_point',pos)

All this code is actually a copy of the default function used by data cursors. The only modifications are:

  • I changed the name (obviously you want it to be unique)
  • I added the last line of code

This last line of code use assignin to transfer the position of the cursor into a variable (named clicked_point) in the base workspace.

Armed with that, keep your code which generate the sphere (although I recommend you change the name of the surface object to something else than sphere as this is a built in MATLAB function), and we just have to modify the datacursormode object to instruct it to use our getClickedPoint function:

[X,Y,Z] = sphere(50);
r = 10 ; X2 = X * r; Y2 = Y * r; Z2 = Z * r;
fig = figure ;
hs  = surf(X2,Y2,Z2,'FaceColor','texture','EdgeColor','none','FaceLighting','phong');
axis equal

%% Assign custom update function to dcm
dcm_obj = datacursormode(fig);
set(dcm_obj,'SnapToDataVertex','off','Enable','on','UpdateFcn',@getClickedPoint)

Now the first time you click on the sphere, the variable clicked_point will be created in the workspace with the coordinates of the point. And every time you click again on the sphere the variable will be updated:

enter image description here


If this is to be applied with a GUI, use the same technique but instead of assignin, I would recommend to use the setappdata function. (you can read Share Data Among Callbacks to have details about how this works.)

Upvotes: 2

Related Questions