Multi x plot, linked zoom and indipendent pan
2 次查看(过去 30 天)
显示 更早的评论
Hi guys, my goal is to have a plot with two x axes and at least two y axes and to be able to pan one indipentently from the other but with linked zoom on the X axis. Suppose to have two time signal, one shorter than the other, and you want to move one over the other to compare them at a precise moment. I have tried linkprop and linkaxes in some ways but the result is that I managed to link zoom and pan together but not to decouple them. To be clear, the aim is: plot 2 signal with different X and Y, zoom them at the same level, horizontal pan one indipendently from the other.
Thanks in advance guys
0 个评论
回答(1 个)
Just Manuel
2021-1-27
编辑:Just Manuel
2021-1-27
I've run into the same problem. There does not seem to be a convenient way to do this. I have worked around it using ActionPreCallback and ActionPostCallback on the zoom object.
As matlab only feeds those callbacks with the handle to the figure being zoomed and the handle to the axes being zoomed, you have to remember the original limits yourself.
Another issue is that you can not have a return value in the callbacks, so you have to implement some kind of out parameter. I created a handle wrapper for that.
Here's an example how i used it (tested in R2018a):
% generate some sample data
x1 = 1:0.1:20;
x2 = x1(20:80);
x3 = x1(30:120);
y1 = sin(x1);
y2 = sin(x2 + 1);
y3 = sin(x3 - 2);
% plot data using axes with transparent background on top on each other
% see https://ch.mathworks.com/help/matlab/creating_plots/graph-with-multiple-x-axes-and-y-axes.html
figure();
line(x1, y1);
ax(1) = gca;
ax(1).XColor = 'b';
ax(2) = axes('Position',ax(1).Position, 'XAxisLocation','top', 'Color','none');
ax(2).XColor = 'r';
line(x2, y2, 'Parent',ax(2), 'Color', 'r');
ax(3) = axes('Position',ax(1).Position, 'XAxisLocation','origin', 'Color','none');
ax(3).XColor = [0.5 0 0.1];
line(x3, y3, 'Parent',ax(3), 'Color',[0.5 0 0.1]);
linkaxes(ax, 'y');
% synchronize limits
xlim(ax(2), xlim(ax(1)));
xlim(ax(3), xlim(ax(1)));
% instatniate a handle containing a cell array with the current limits
originalLimitsHandle = HandleWrapper({xlim(ax(1)), xlim(ax(2)), xlim(ax(3))});
z = zoom;
% update current limits before the zoom happens
z.ActionPreCallback = {@updateLimits, ax, originalLimitsHandle};
% update the limits of the other axes after the zoom has happened
z.ActionPostCallback = {@linkXZoom, ax, originalLimitsHandle};
function updateLimits(fig, ax, linkedAxes, originalLimitsHandle)
for n = 1:length(linkedAxes)
originalLimitsHandle.Property{n} = xlim(linkedAxes(n));
end
end
function linkXZoom(fig, ax, linkedAxes, originalLimitsHandle)
% determine which axes was zoomed (source)
zoomedIndex = find(eq(ax.Axes, linkedAxes));
originalSourceLimits = originalLimitsHandle.Property{zoomedIndex};
newSourceLimits = xlim(ax.Axes);
% determine offsets to calculate new limits
offset = newSourceLimits(1) - originalSourceLimits(1);
limitWidth = newSourceLimits(2) - newSourceLimits(1);
for n = 1:length(linkedAxes)
% only update the non-zoomed axes (targets)
if n ~= zoomedIndex
% calculate new limits
originalTargetLimits = xlim(linkedAxes(n));
newTargetLimits = [originalTargetLimits(1) + offset, ...
originalTargetLimits(1) + offset + limitWidth];
% do the zooming by setting the calculated x limits
xlim(linkedAxes(n), newTargetLimits);
end
end
end
And that's the handle wrapper class:
classdef HandleWrapper < handle
%HANDLEWRAPPER wraps a property within a handle
% can be used as an pointer parameter in functions
properties
Property
end
methods
function obj = HandleWrapper(property)
if nargin ~= 0
obj.Property = property;
end
end
end
end
Hope that hepls you (and any other poor soul encountering the same problem)
Cheers Manuel
1 个评论
Just Manuel
2021-1-27
This vexed me. I extended the functionality and packed it into a single class. It now behaves similarly to linkaxes.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Data Exploration 的更多信息
产品
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!