Reputation: 157
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 = [?,?,?];
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
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:
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:
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