MATLAB Answers

Is it possible to display a crosshair everytime a point is marked with the data cursor tool in MATLAB R2010b?

33 views (last 30 days)
Shigeru Sasao
Shigeru Sasao on 13 Jan 2011
In many popular plotting tools, clicking on a point in a plot results in a crosshair (2 perpendicular lines at that point). Is it possible to have this functionality with the data cursor tool?

Answers (1)

Kenneth Eaton
Kenneth Eaton on 22 Jan 2011
You can achieve this by modifying the 'UpdateFcn' property of the datacursormode object. This function is normally used to format the text appearing in the data cursor, but you can modify the default function and add additional code to create and update a set of crosshairs. I've included a sample function data_cursor_cross at the end of this post that will add crosshairs in 2-D and 3-D for multiple datatips:
You can use this function in one of two ways:
  • Via the UI: Turn on the Data Cursor tool by pressing the button on the figure menu, create a new datatip, right click on the datatip, select the menu option "Select Text Update Function...", and then select the data_cursor_cross m-file.
  • Via code: Run the following code after creating the figure and each datatip you subsequently add will have crosshairs:
dcmObj = datacursormode(gcf);
set(dcmObj,'UpdateFcn',@data_cursor_cross,'Enable','on');
And here's the function data_cursor_cross:
function output_txt = data_cursor_cross(~,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).
% Create the data cursor text string:
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
% Find the hggroup object that goes with the event:
posArgs = {'XData',pos(1),'YData',pos(2)};
if length(pos) > 2
posArgs(5:6) = {'ZData',pos(3)};
end
hMarker = findall(0,'Tag','DataTipMarker','Type','line',posArgs{:});
hGroup = get(hMarker,'Parent');
% If hGroup is a cell array, it means more than one data cursor is at the
% given position. Since there is no clear way to distinguish them, the
% crosshairs for both should be initialized/updated:
if iscell(hGroup)
cellfun(@update_crosshairs,hGroup);
else
update_crosshairs(hGroup);
end
%--- Begin nested functions -----------------------------------------------
function update_crosshairs(hObject)
if isappdata(hObject,'DataCursorCrosshairs')
% Update the crosshairs:
hCrosshairs = getappdata(hObject,'DataCursorCrosshairs');
if length(hCrosshairs) > 2
set(hCrosshairs(1),'YData',pos([2 2]),'ZData',pos([3 3]));
set(hCrosshairs(2),'XData',pos([1 1]),'ZData',pos([3 3]));
set(hCrosshairs(3),'XData',pos([1 1]),'YData',pos([2 2]));
else
set(hCrosshairs(1),'YData',pos([2 2]));
set(hCrosshairs(2),'XData',pos([1 1]));
end
else
% Get the axes limits, create the crosshairs, set the crosshair
% handles as application data for the hggroup object, and set the
% DeleteFcn of the hggroup object so it removes the crosshairs:
hAxes = get(hObject,'Parent');
xLimits = xlim(hAxes);
yLimits = ylim(hAxes);
if length(pos) > 2
zLimits = zlim(hAxes);
hX = line('XData',xLimits,'YData',pos([2 2]),'ZData',pos([3 3]));
hY = line('XData',pos([1 1]),'YData',yLimits,'ZData',pos([3 3]));
hZ = line('XData',pos([1 1]),'YData',pos([2 2]),'ZData',zLimits);
hCrosshairs = [hX hY hZ];
else
hX = line('XData',xLimits,'YData',pos([2 2]));
hY = line('XData',pos([1 1]),'YData',yLimits);
hCrosshairs = [hX hY];
end
setappdata(hObject,'DataCursorCrosshairs',hCrosshairs);
set(hObject,'DeleteFcn',...
@(src,event) delete(hCrosshairs(ishandle(hCrosshairs))));
end
end
end

Community Treasure Hunt

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

Start Hunting!