2
votes

I have 2 plots in a MATLAB gui and i want to link them together so a zoom on one plot zooms the other.

Unlike similar questions i have seen on linking plots neither my x data or y data is shared by either graph, but it is related.


My data consists of the heights of land measured by a plane flying over them over a period of 5 seconds.

Plot 1 : The height of land

y: height = [10,9,4,6,3];
x: time = [1,2,3,4,5];

Plot 2 : land coordinates

y: latitude = [10,20,30,40,50];
x: longitude = [11,12,13,14,15];

If the user zooms in the x axis on Plot 1, for example showing the first 3 seconds of flight I want to zoom the x and y-axis of Plot 2 so only the first 3 longitude & latitude coordinates in the longitude & latitude arrays are shown.

Is this possible?

2

2 Answers

3
votes

You'll need a function that does the mapping of height & time to lat & longitude and then sets the limits based on the mapped values.

The following function does this job:

function syncLimits(masterAxes,slaveAxes)
% Sync a slave axes that is plot related data.
% Assumes each data point in slave corresponds with the data point in the
% master at the same index.

% Find limits of controlling plot
xRange = xlim(masterAxes);
% Get x data
x1Data = get(get(masterAxes,'children'),'XData');
% Find data indices corresponding to these limits
indices = x1Data >= xRange(1) & x1Data <= xRange(2);
if any(indices)
    % Set the limits on the slave plot to show the same data range (based
    % on the xData index)
    x2Data = get(get(slaveAxes,'children'),'XData');
    y2Data = get(get(slaveAxes,'children'),'YData');
    minX = min(x2Data(indices));
    maxX = max(x2Data(indices));
    minY = min(y2Data(indices));
    maxY = max(y2Data(indices));
    % Set limits +- eps() so that if a single point is selected
    % x/ylim min/max values aren't identical
    xlim(slaveAxes,[ minX - eps(minX) maxX + eps(maxX)  ]);
    ylim(slaveAxes,[ minY - eps(minY) maxY + eps(maxY)  ]);
end

end

You can then get the height v time plot to call this function whenever it is zoomed or panned.

height = [10,9,4,6,3];
time = [1,2,3,4,5];

latitude = [10,20,30,40,50];
longitude = [11,12,13,14,15];

% Plot Height v Time
h1 = figure;
a1 = gca;
plot(time,height);
title('Height v Time');


% Plot Lat v Long
figure;
a2 = gca;
plot(longitude, latitude);
title('Lat v Long')

% Set-up Callback to sync limits
zH = zoom(h1);
pH = pan(h1);
set(zH,'ActionPostCallback',@(figHandle,axesHandle) syncLimits(axesHandle.Axes,a2));
set(pH,'ActionPostCallback',@(figHandle,axesHandle) syncLimits(axesHandle.Axes,a2));

The code would be simpler if your plots are generated by a function as your could nest the syncLimits function and make use of the time, lat & long data directly. You could also pass this data into the syncLimits function which again would be a bit less code but you only have to write syncLimits once (and I've already done it!).

1
votes

In the case you've posted, the x axes are indeed the same, even if they're not the same variable names, so you can still link them using linkaxes, which only links the limits, not the variables used for plotting.

h_height = figure(1);
plot(h_height,time,height)
h_location = figure(2);
plot(h_location,longitude,latitude)

linkaxes([h_height h_location],'x')

Any change in xlim of one will change the other.