Одно из решений для вас - изменить свойства осей и 'DataAspectRatio'
так, чтобы десятилетие на одной оси равнялось десятилетию на другой.Вот как вы можете это сделать для вашего примера:
loglog(2.^[1:20]*1e10,(2.^[1:20]).^2); %# Plot your sample data
xLimits = [1e10 1e16]; %# Limits for the x axis
yLimits = [1 1e12]; %# Limits for the y axis
logScale = diff(yLimits)/diff(xLimits); %# Scale between the x and y ranges
powerScale = diff(log10(yLimits))/... %# Scale between the x and y powers
diff(log10(xLimits));
set(gca,'Xlim',xLimits,'YLim',yLimits,... %# Set the limits and the
'DataAspectRatio',[1 logScale/powerScale 1]); %# data aspect ratio
set(gca,'XTick',[1e10 1e12 1e14 1e16]); %# Change the x axis tick marks
И вот результирующий график:
Обратите внимание, что пробел между 10 Отметки 0 и 10 2 на оси y охватывают то же количество пикселей, что и пространство между отметками 10 10 и 10 12 наось x, таким образом, делая десятилетие на одной оси равным десятилетию на другой.
Если вы не хотите изменять пределы осей, а вместо этого хотите использовать ограничения по умолчанию, выбранные MATLAB, выможно просто получить ограничения по осям для выполнения вычислений:
xLimits = get(hAxes,'XLim');
yLimits = get(hAxes,'YLim');
Однако, чтобы отключить режим автоматического изменения размера осей в MATLAB, вам все равно придется либо установить ограничения по осям на те же значения или установите свойства режима ограничения на 'manual'
при обновлении свойства 'DataAspectRatio'
:
set(gca,'Xlim',xLimits,'YLim',yLimits,...
'DataAspectRatio',[1 logScale/powerScale 1]);
%# OR...
set(gca,'XLimMode','manual','YLimMode','manual',...
'DataAspectRatio',[1 logScale/powerScale 1]);
Если все это кажется большой работой, вы можетеупростить вещи, поместив все это в функцию.На самом деле я буду отправлять функцию decades_equal
в MathWorks File Exchange на основе кода в этом ответе.На данный момент, это урезанная версия (т.е. без проверки ошибок или помощи), которую вы можете использовать:
function decades_equal(hAxes,xLimits,yLimits)
if (nargin < 2) || isempty(xLimits)
xLimits = get(hAxes,'XLim');
end
if (nargin < 3) || isempty(yLimits)
yLimits = get(hAxes,'YLim');
end
logScale = diff(yLimits)/diff(xLimits);
powerScale = diff(log10(yLimits))/diff(log10(xLimits));
set(hAxes,'Xlim',xLimits,...
'YLim',yLimits,...
'DataAspectRatio',[1 logScale/powerScale 1]);
end
И вы можете вызвать функцию следующим образом:
loglog(2.^[1:20]*1e10,(2.^[1:20]).^2); %# Plot your sample data
decades_equal(gca); %# Make the decades equal sizes
Как это работает ...
Вам может быть интересно, что за логика стоит за тем, как я выбрал коэффициенты масштабирования выше.При попытке сделать отображаемый размер десятилетия равным для каждой оси, мы должны учитывать как количество, так и размеры десятилетий в пределах диапазонов осей.В приведенном выше коде я в основном вычисляю средний размер десятилетия для каждой оси, а затем использую отношения средних размеров десятилетия для соответствующего масштабирования осей.Например, diff(yLimits)
дает общий размер оси y, а diff(log10(yLimits))
- количество отображаемых на оси y десятилетий (то есть степеней десяти).
Это может быть легче увидеть, если яизмените порядок действий в приведенном выше коде следующим образом:
yDecade = diff(yLimits)/diff(log10(yLimits)); %# Average y decade size
xDecade = diff(xLimits)/diff(log10(xLimits)); %# Average x decade size
set(gca,'XLim',xLimits,'YLim',yLimits,...
'DataAspectRatio',[1 yDecade/xDecade 1]);
И это даст те же результаты масштабирования, что и раньше.