56 views (last 30 days)

Show older comments

Rabih Sokhen
on 13 Apr 2021 at 17:52

hello guys

i am trying to creat a plot with 4 axes, but wen i try to zoom on the following plot, only 2 axes are modifed " the top and right axes"

is there a way to make all the axes change value wen i zoom?

thank you for your support

the following code and plot are :

clear all

clc

x1 = 0:0.1:40;

y1 = 4.*cos(x1)./(x1+2);

x2 = 1:0.2:20;

y2 = x2.^2./x2.^3;

ax1 = axes();

plot(ax1,x1,y1,'-r')

ax1.XColor = 'r';

ax1.YColor = 'r';

ax2 = axes();

plot(ax2,x2,y2,'-k')

ax2.XAxisLocation = 'top';

ax2.YAxisLocation = 'right';

ax2.Color = 'none';

ax1.Box = 'off';

ax2.Box = 'off';

Sree
on 13 Apr 2021 at 19:15

Hope this helps

clear all

clc

x1 = 0:0.1:40;

y1 = 4.*cos(x1)./(x1+2);

x2 = 1:0.2:20;

y2 = x2.^2./x2.^3;

plot(x1,y1)

hold on;

plot(x2,y2)

Adam Danz
on 13 Apr 2021 at 23:21

Edited: Adam Danz
on 15 Apr 2021 at 15:41

Multiple axes with same axis limits

If the xlim and ylim properties are the same between both axes, use linkaxes or linkprop to link the axis properties so changes to one pair of axes will affect the other pair of axes.

See this demo that links two overlaying axes, one that hosts a contour map and another that hosts an image.

Multiple axes with different scales or axis limits

This is more complicated. One solution is to assign a listener that responds to changes to xlim and ylim in one pair of axes and updates the other pair of axes while maintaining axis limit scales. For Matlab r2021a and later, you could use the LimitsChangedFcn instead of a listener.

Follow this demo below to understand critical steps to make this work. This demo is designed for linearly scaled axes (it requires significant modification for log scale axes).

Demo code is attached as an m-file: YokedAxesDemo_DifferentScales.m

1. Create two overlaying axes with different x and y limits

A recommended step that this demo does not include is linking the axis position properties so a figure resize or the addition of a legend, colorbar, or axis lables does not shift one axis position relative to the other. For demos on using linkprop see linkprop demo 1 and linkprop demo 2.

ax1 and ax2 are the two axes handles.

x1 = 0:0.1:40;

y1 = 4.*cos(x1)./(x1+2);

x2 = 1:0.2:20;

y2 = x2.^2./x2.^3;

ax1 = axes();

plot(ax1,x1,y1,'-r')

ax1.XColor = 'r';

ax1.YColor = 'r';

ax2 = axes();

plot(ax2,x2,y2,'-k')

ax2.XAxisLocation = 'top';

ax2.YAxisLocation = 'right';

ax2.Color = 'none';

ax1.Box = 'off';

ax2.Box = 'off';

% Add an intersection marker to visually confirm correct scaling

hold on

plot(ax2, 2.526596, 0.396379, 'bx')

2. Turn off interation to ax1

ax2 is on top and will be the main axis the user interacts with.

Axis interaction is turned off for ax1 to simplify the problem.

ax1.Interactions = [];

ax1.Toolbar.Visible = 'off';

3. Set up a listener that responds to changes to ax2 limits

Any time the XLim or YLim changes in ax2, the listener responds (listener function defined later). See inline comments for more detail.

% Compute scaling factor to convert ax1 scale from ax2 scale

% xyscale is 2x1 factors of [x;y] axes

xyscale = [range(ax1.XLim) / range(ax2.XLim); range(ax1.YLim) / range(ax2.YLim)];

% Store original axis limits for both axes

% axBaseLim is 2x2x2 axis limits of [x;y] axes, [min,max] limits; and

% [ax1,ax2] along the 3rd dimension

axBaseLim = [ax1.XLim; ax1.YLim]; % ax1

axBaseLim(:,:,2) = [ax2.XLim; ax2.YLim]; % ax2

% Assign listener

ax2.UserData.Listener = addlistener(ax2,{'XLim','YLim'}, 'PostSet', ...

@(~,~)axisLimitListener([], [], [ax1,ax2], xyscale, axBaseLim));

4. Fix problem with axis Restore button

The listener responds to user interaction (zoom/pan) as well as programmatically setting the ax2 limits but the restore button in the axis toolbar only restores ax2! That's not cool. Here we customize the restore button callback function so that it updates ax1 after ax2 is restored. If your axes have a custom toolbar, this will replace it with the default toolbar.

% Fix restoreview button

axTB = axtoolbar(ax2,'default');

isRestoreButton = strcmpi({axTB.Children.Icon},'restoreview');

if any(isRestoreButton)

restoreButtonHandle = axTB.Children(isRestoreButton);

originalRestoreFcn = restoreButtonHandle.ButtonPushedFcn;

restoreButtonHandle.ButtonPushedFcn = ...

{@myRestoreButtonCallbackFcn, ax1, originalRestoreFcn, xyscale, axBaseLim};

end

5. Define the listener function

function axisLimitListener(~,~,ax,scalingFactor,axBaseLim)

% Listener callback that responds to x/y axis limit changes to ax2 and

% updates the axis limits to ax1.

% INPUTS

% ax: 1x2 array of axis handles to [ax1,ax2]

% scalingFactor: (see description of xyscale above)

% axBaseLim: (see description of axBaseLim above)

% Convert the lower axis limits from ax2 to values normalized

% by the original axis range. Example: for an axis range of [10,20]

% that was changed to [12,20], the lower limit of 12 is normalized to 0.2;

normLowerLimit = ([ax(2).XLim(1);ax(2).YLim(1)] - axBaseLim(:,1,2))./range(axBaseLim(:,:,2),2);

% Compute the new lower limits to ax1.

newLimits = normLowerLimit.*range(axBaseLim(:,:,1),2) + axBaseLim(:,1,1);

% Compute the new upper limits ax1.

newLimits(:,2) = newLimits(:,1) + [range(ax(2).XLim);range(ax(2).YLim)].*scalingFactor;

% Update ax1 limits

set(ax(1), 'XLim', newLimits(1,:), 'YLim', newLimits(2,:))

end

6. Define the restoration button callback function

This uses resetplotview which is undocumented and may change in future releases.

function myRestoreButtonCallbackFcn(hobj, event, ax1, originalCallback, xyscale, axBaseLim)

% Responds to pressing the restore button in the ax2 toolbar.

% originalCallback is a function handle to the original callback

% function for this button.

% xyscale and axBaseLim are defined elsewhere.

originalCallback(hobj,event) % reset ax2

axisLimitListener([],[],[ax1,event.Axes],xyscale,axBaseLim) % update ax1

end

Adam Danz
on 15 Apr 2021 at 11:30

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

Start Hunting!