Live line plotting over a surface/mesh/imagesc plot.

28 views (last 30 days)
I have a matrix (size 1000x1000) of height values, that I can view with mesh command. From the same figure (that mesh is displayed) I use ginput to the get the coordinates of the mouse and based on the coordinates I can plot the horizontal and vertical line profiles:
[x y] = ginput(1);
subplot(2, 1, 1)
set(gcf, 'Units', 'Inches', 'Position', [5, 5, 10, 3], 'PaperUnits', 'Inches', 'PaperSize', [16, 9.0])
plot(Zp(:, round(x(1))), 'b-'); title('Vertical'); grid on
subplot(2, 1, 2);
plot(Zp(round(y(1)), :), 'k-'); title('Horizontal');
Now, what I really need is a live line profile plotting, so as I drag the mouse over the mesh figure I can see the two line profiles.
It is like continuously updating the values of x(1) and y(1) and updating figure(2).
Is it even possible? And if so, could anyone guide me with how to do it?
Adam Danz
Adam Danz on 11 Mar 2020
Edited: Adam Danz on 11 Mar 2020
Using imagesc makes much more sense. See the demo below.
Note that this solution merely updates values of the line objects rather than replotting lines. This is much faster and more efficient than replotting lines.

Sign in to comment.

Accepted Answer

Adam Danz
Adam Danz on 11 Mar 2020
Edited: Adam Danz on 12 Mar 2020
Here's a functional demo that uses the WindowButtonMotionFcn property of a figure to capture the mouse position which is used to detect the closest (x,y) coordinates to the mouse within the axes. It continually updates a set of crosshairs that display the coordinates and updates two subplots showing the values along the selected row and column.
See inline comments for details.
Create the data and set up the plot
% Create data
data = peaks(1000);
% Plot data in main axis
ax(1) = subplot(4,1,[1,2]);
imagesc(ax(1), data)
ax(1).YDir = 'Normal';
axis(ax(1),'tight') %required!
ax(1).Parent.WindowState = 'Maximized'; % maximize figure
ax(1).Toolbar.Visible = 'off'; % otherwise, toolbar may hide axis title
xlabel(ax(1), 'x axis lable')
ylabel(ax(1), 'y axis lable')
title(ax(1), 'Data')
% Set up cross hairs at axis edges
gobj(1) = xline(min(xlim(ax(1))), 'k-');
gobj(2) = yline(min(ylim(ax(1))), 'k-');
% Set up subplot 2; do all formatting here
ax(2) = subplot(4,1,3);
gobj(3) = plot(ax(2), 1:size(data,2), nan(1,size(data,2)), '-ko', 'MarkerSize', 4);
xlabel(ax(2), 'x index')
ylabel(ax(2), 'x value')
axis(ax(2), 'tight')
% Set up subplot 3; do all formatting here
ax(3) = subplot(4,1,4);
gobj(4) = plot(ax(3), 1:size(data,1), nan(1,size(data,1)), '-ko', 'MarkerSize', 4);
xlabel(ax(3), 'y index')
ylabel(ax(3), 'y value')
axis(ax(3), 'tight')
% After values are set above, assign windowbuttonmotion fcn
set(ax(1).Parent,'windowbuttonmotionfcn', {@mouseMove, data, ax, gobj});
Define the WindowButtonMotionFcn
function mouseMove(~, ~, data, ax, gobj)
% gobj(1) is xline
% gobj(2) is yline
% gobj(3) is subplot 2 line
% gobj(4) is subplot 3 line
% ax is a vector of subplot handles from top to bottom
% data is the imagesc data
% Get mouse coordinate, round to nearest integer.
C = ax(1).CurrentPoint;
x = round(C(1,1));
y = round(C(1,2));
% If mouse isn't on axis, do nothing.
if x < ax(1).XLim(1) || x > ax(1).XLim(2) || y < ax(1).YLim(1) || y > ax(1).YLim(2)
% Update crosshairs
gobj(1).Value = x;
gobj(1).Label = x;
gobj(2).Value = y;
gobj(2).Label = y;
% Update main title
% title(ax(1), sprintf('(x,y) = (%d, %d)', x, y));
% Update x-subplot
gobj(3).YData = data(x,:);
title(ax(2), sprintf('X = %d', x))
% Update y-subplot
gobj(4).YData = data(:,y);
title(ax(3), sprintf('Y = %d', y))
Addendum: turn on/off interactivity
Press the left mouse button to turn on interactivity and the right mouse button to pause it so that the crosshairs and subplots do not update with mouse motion.
%% Add this section to the first block of code where the figure is created.
% Remove the windowbuttonmotionfcn in that section.
WindowButtonMotionFcnInput = {@mouseMove, data, ax, gobj};
set(ax(1).Parent,'windowbuttondownfcn', {@startStopMouseMove, WindowButtonMotionFcnInput})
%% This function responds to mouse clicks and either assigns
% or removes the windowbuttonmotionfcn
function startStopMouseMove(hobj,~,WindowButtonMotionFcnInput)
buttonID = hobj.SelectionType;
switch buttonID
case 'normal' %left mouse button
% Start interactivity
set(hobj,'windowbuttonmotionfcn', WindowButtonMotionFcnInput);
case 'alt' % right mouse button
% Stop interactivity
set(hobj,'windowbuttonmotionfcn', []);

Sign in to comment.

More Answers (0)


Find more on Line Plots 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!