Ответ 1
Одним из решений является изменение ограничений осей и '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]);
И это даст те же результаты масштабирования, что и раньше.