有时候,用MATLAB绘制坐标图时会出现有的曲线值都特别大,有的曲线值都很小,但是又想在同一幅图中将他们展示出来,于是需要截断坐标轴的刻度或者改变纵轴的刻度,使其不均匀。此时,就需要对横坐标或纵坐标进行截断。
1 方法一
参考:博客-MATLAB实例:截断坐标轴(Broken Axis)
1.1 原始图形
MATLAB相关代码如下:
clear;
clc;
close all;
%% 原始图片
data=[2.3 2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3 2.5 2.1 2 1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3 3 3 3 3 2.5
10.8 10.6 10.5 10.2 10.1 10.1 10.1 10.1 10.1 9.1
];
x_min = 0.1; % 横坐标刻度最小值
x_interval = 0.1; % 横坐标刻度间隔距离
x_max = 1; % 横坐标刻度最大值
%% 绘图
X = x_min:x_interval:x_max;
h = plot(X, data(1, :), 'k*-', X, data(2, :), 'g^-', X, data(3, :), 'r-s', X, data(4, :), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east'); %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4);
text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95], 'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
saveas(gcf,sprintf('Original image.jpg'),'bmp'); %保存图片
图形如下:
1.2 截断横坐标
MATLAB相关代码如下:
clear;
clc;
close all;
%% 横轴截断后图像
% 数据
format short g
data=[2.3 2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3 2.5 2.1 2 1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3 3 3 3 3 2.5
10.8 10.6 10.5 10.2 10.1 10.1 10.1 10.1 10.1 9.1
];
%% 参数设置
x_min = 0.1; % 横轴刻度最小值
x_interval = 0.1; % 横坐标两个刻度间隔距离
x_break_start = 0.5; % 截断的开始值
x_break_end = 0.9; % 截断的结束值
x_break_end = x_break_end-x_interval;
x_max = length(data(1, :))*x_interval+x_min-x_interval; %横轴刻度最大值
X = x_min:x_interval:x_max;
adjust_value=0.4*x_interval; %微调截断处x坐标
% 超过截断结束位置的那些曲线统统向左平移uptate_num个长度
data(:, find(abs(X-x_break_start)<eps)+1:(end-round((x_break_end-x_break_start)/x_interval)))=data(:, X>x_break_end+eps);
x_max_new=x_max-x_break_end+x_break_start;
X=x_min:x_interval:x_max_new;
new_range=round(x_max_new/x_interval);
%% 绘图
% 根据曲线的个数进行修改,这里曲线是4条
h=plot(X, data(1, 1:new_range), 'k*-', X, data(2, 1:new_range), 'g^-', X, data(3, 1:new_range), 'r-s', X, data(4, 1:new_range), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max_new]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east'); %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4);
% 横坐标截断设置
xlimit=get(gca,'xlim');
location_X=(x_break_start+adjust_value-xlimit(1))/diff(xlimit);
t1=text(location_X, 0,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
t2=text(location_X, 1,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
% 重新定义横坐标刻度
xtick=x_min:x_interval:x_max_new;
set(gca,'xtick',xtick);
xtick(xtick>x_break_start+eps)=xtick(xtick>x_break_start+eps)+x_break_end-x_break_start;
for i=1:length(xtick)
xticklabel{i}=sprintf('%.1f',xtick(i));
end
set(gca,'xTickLabel', xticklabel, 'FontSize', 12, 'FontName', 'Times New Roman'); %修改坐标名称、字体
text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95], 'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
saveas(gcf,sprintf('Break_X_Axis.jpg'),'bmp'); %保存图片
图形如下:
1.3 截断纵坐标
MATLAB相关代码如下:
clear;
clc;
close all;
%% 纵轴截断后图像
% 数据
data=[2.3 2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3 2.5 2.1 2 1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3 3 3 3 3 2.5
10.8 10.6 10.5 10.2 10.1 10.1 10.1 10.1 10.1 9.1
];
%% 参数设置
x_min=0.1; %横坐标刻度最小值
x_interval=0.1; %横坐标刻度间隔距离
x_max=1; %横坐标刻度最大值
y_interval=1; %纵坐标两个刻度间隔距离
y_max=11; %纵轴刻度最大值
y_break_start=4; % 截断的开始值
y_break_end=9; % 截断的结束值
X=x_min:x_interval:x_max;
adjust_value=0.4*y_interval; %微调截断处y坐标
uptate_num=y_break_end-y_break_start-y_interval; %最高处曲线向下平移大小
% 超过截断结束位置的那些曲线统统向下平移uptate_num个长度
for i=1:length(data(:, 1))
if data(i, :)>y_break_end
data(i, :)=data(i, :)-uptate_num;
end
end
%% 绘图
% 根据曲线的个数进行修改,这里曲线是4条
h=plot(X, data(1, :), 'k*-', X, data(2, :), 'g^-', X, data(3, :), 'r-s', X, data(4, :), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east'); %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4);
% 纵坐标截断设置
ylimit=get(gca,'ylim');
location_Y=(y_break_start+adjust_value-ylimit(1))/diff(ylimit);
t1=text(0, location_Y,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
set(t1,'rotation',90);
t2=text(1, location_Y,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
set(t2,'rotation',90);
% 重新定义纵坐标刻度
ytick=0:y_interval:y_max;
set(gca,'ytick',ytick);
ytick(ytick>y_break_start+eps)=ytick(ytick>y_break_start+eps)+uptate_num;
for i=1:length(ytick)
yticklabel{i}=sprintf('%d',ytick(i));
end
set(gca,'yTickLabel', yticklabel, 'FontSize', 12, 'FontName', 'Times New Roman'); %修改坐标名称、字体
text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95], 'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
saveas(gcf,sprintf('Break_Y_Axis.jpg'),'bmp'); %保存图片
图形如下:
1.4 截断横纵坐标
MATLAB相关代码如下:
clear;
clc;
close all;
%% 横轴截断后图像
% 数据
data=[2.3 2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3 2.5 2.1 2 1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3 3 3 3 3 2.5
10.8 10.6 10.5 10.2 10.1 10.1 10.1 10.1 10.1 9.1
];
%% 参数设置
x_min=0.1; %横轴刻度最小值
x_interval=0.1; %横坐标两个刻度间隔距离
x_break_start=0.5; % 截断的开始值
x_break_end=0.9; % 截断的结束值
y_interval=1; %纵坐标两个刻度间隔距离
y_max=11; %纵轴刻度最大值
y_break_start=4; % 截断的开始值
y_break_end=9; % 截断的结束值
x_break_end=x_break_end-x_interval;
x_max=length(data(1, :))*x_interval+x_min-x_interval; %横轴刻度最大值
X=x_min:x_interval:x_max;
adjust_value_x=0.4*x_interval; %微调截断处x坐标
adjust_value_y=0.4*y_interval; %微调截断处y坐标
uptate_num=y_break_end-y_break_start-y_interval; %最高处曲线向下平移大小
% 超过截断结束位置的那些曲线统统向左平移uptate_num个长度
data(:, find(abs(X-x_break_start)<eps)+1:(end-round((x_break_end-x_break_start)/x_interval)))=data(:, X>x_break_end+eps);
% 超过截断结束位置的那些曲线统统向下平移uptate_num个长度
for i=1:length(data(:, 1))
if data(i, :)>y_break_end
data(i, :)=data(i, :)-uptate_num;
end
end
x_max_new=x_max-x_break_end+x_break_start;
X=x_min:x_interval:x_max_new;
new_range=round(x_max_new/x_interval);
%% 绘图
% 根据曲线的个数进行修改,这里曲线是4条
h=plot(X, data(1, 1:new_range), 'k*-', X, data(2, 1:new_range), 'g^-', X, data(3, 1:new_range), 'r-s', X, data(4, 1:new_range), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max_new]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east'); %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4);
% 横坐标截断设置
xlimit=get(gca,'xlim');
location_X=(x_break_start+adjust_value_x-xlimit(1))/diff(xlimit);
t1=text(location_X, 0,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
t2=text(location_X, 1,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
% 重新定义横坐标刻度
xtick=x_min:x_interval:x_max_new;
set(gca,'xtick',xtick);
xtick(xtick>x_break_start+eps)=xtick(xtick>x_break_start+eps)+x_break_end-x_break_start;
for i=1:length(xtick)
xticklabel{i}=sprintf('%.1f',xtick(i));
end
% 纵坐标截断设置
ylimit=get(gca,'ylim');
location_Y=(y_break_start+adjust_value_y-ylimit(1))/diff(ylimit);
t1=text(0, location_Y,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
set(t1,'rotation',90);
t2=text(1, location_Y,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
set(t2,'rotation',90);
% 重新定义纵坐标刻度
ytick=0:y_interval:y_max;
set(gca,'ytick',ytick);
ytick(ytick>y_break_start+eps)=ytick(ytick>y_break_start+eps)+uptate_num;
for i=1:length(ytick)
yticklabel{i}=sprintf('%d',ytick(i));
end
set(gca,'xTickLabel', xticklabel, 'yTickLabel', yticklabel, 'FontSize', 12, 'FontName', 'Times New Roman'); %修改坐标名称、字体
text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95], 'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
saveas(gcf,sprintf('Break_X_Y_Axis.jpg'),'bmp'); %保存图片
图形如下:
2 方法二
mathworks官网代码:
截断横坐标-Break X Axis
截断纵坐标-Break Y Axis
2.1 截断横坐标
2.1.1 案例
MATLAB相关代码如下:
clear;
clc;
close all;
%% 纵轴截断后图像
% 数据
data=[2.3 2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3 2.5 2.1 2 1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3 3 3 3 3 2.5
10.8 10.6 10.5 10.2 10.1 10.1 10.1 10.1 10.1 9.1
];
%% 参数设置
x_min=0.1; %横坐标刻度最小值
x_interval=0.1; %横坐标刻度间隔距离
x_max=1; %横坐标刻度最大值
X=x_min:x_interval:x_max;
h=plot(X, data(1, :), 'k*-', X, data(2, :), 'g^-', X, data(3, :), 'r-s', X, data(4, :), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east'); %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4,'color','k');
% text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95], 'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
%% 调用已有的代码,两个函数只能调用一个,不能同时调用,出错
% breakyaxis([4 9]); % 截断纵坐标
breakxaxis([0.5 0.9]); %截断横坐标
saveas(gcf,sprintf('Other_Break_Axis.jpg'),'bmp'); %保存图片
图形如下:
2.1.2 调用函数
调用代码:
breakyaxis([minXvalue,maxXvalue])
函数代码:
% breakxaxes splits data in an axes so that data is in a left and right pane.
%
% breakXAxes(splitXLim) splitXLim is a 2 element vector containing a range
% of x values from splitXLim(1) to splitXLim(2) to remove from the axes.
% They must be within the current xLimis of the axes.
%
% breakXAxes(splitXLim,splitWidth) splitWidth is the distance to
% seperate the left and right side. Units are the same as
% get(AX,'uints') default is 0.015
%
% breakXAxes(splitXLim,splitWidth,yOverhang) yOverhang stretches the
% axis split graphic to extend past the top and bottom of the plot by
% the distance set by YOverhang. Units are the same as get(AX,'units')
% default value is 0.015
%
% breakXAxes(AX, ...) performs the operation on the axis specified by AX
%
function breakInfo = breakxaxis(varargin)
%Validate Arguements
if nargin < 1 || nargin > 4
error('Wrong number of arguements');
end
if isscalar(varargin{1}) && ishandle(varargin{1})
mainAxes = varargin{1};
argOffset = 1;
argCnt = nargin - 1;
if ~strcmp(get(mainAxes,'Type'),'axes')
error('Handle object must be Type Axes');
end
else
mainAxes = gca;
argOffset = 0;
argCnt = nargin;
end
if (strcmp(get(mainAxes,'XScale'),'log'))
error('Log X Axes are not supported');
end
if (argCnt < 3)
yOverhang = 0.015;
else
yOverhang = varargin{3 + argOffset};
if numel(yOverhang) ~= 1 || ~isreal(yOverhang) || ~isnumeric(yOverhang)
error('YOverhang must be a scalar number');
elseif (yOverhang < 0)
error('YOverhang must not be negative');
end
yOverhang = double(yOverhang);
end
if (argCnt < 2)
splitWidth = 0.015;
else
splitWidth = varargin{2 + argOffset};
if numel(yOverhang) ~= 1 || ~isreal(yOverhang) || ~isnumeric(yOverhang)
error('splitWidth must be a scalar number');
elseif (yOverhang < 0)
error('splitWidth must not be negative');
end
splitWidth = double(splitWidth);
end
splitXLim = varargin{1 + argOffset};
if numel(splitXLim) ~= 2 || ~isnumeric(splitXLim) || ~isreal(yOverhang)
error(splitXLim,'Must be a vector length 2');
end
splitXLim = double(splitXLim);
mainXLim = get(mainAxes,'XLim');
if (any(splitXLim >= mainXLim(2)) || any(splitXLim <= mainXLim(1)))
error('splitXLim must be in the range given by get(AX,''XLim'')');
end
mainPosition = get(mainAxes,'Position');
if (splitWidth > mainPosition(3) )
error('Split width is too large')
end
%We need to create 4 axes
% leftAxes - is used for the left x axis and left pane data
% rightAxes - is used to the right x axis and right pane data
% annotationAxes - is used to display the y axis and title
% breakAxes - this is an axes with the same size and position as main
% is it used to draw a seperator between the left and right side
%Grab Some Parameters from the main axis (e.g the one we are spliting)
mainXLim = get(mainAxes,'XLim');
mainYLim = get(mainAxes,'YLim');
mainPosition = get(mainAxes,'Position');
mainParent = get(mainAxes,'Parent');
mainWidth = mainPosition(3); %Positions have the format [left bottom width height]
%mainXRange = mainXLim(2) - mainXLim(1);
mainFigure = get(mainAxes,'Parent');
mainYColor = get(mainAxes,'YColor');
mainLineWidth = get(mainAxes,'LineWidth');
figureColor = get(mainFigure,'Color');
mainYTickLabelMode = get(mainAxes,'YTickLabelMode');
mainXLabel = get(mainAxes,'XLabel');
mainXDir = get(mainAxes,'XDir');
mainLayer = get(mainAxes,'Layer');
%Save Main Axis Z Order
figureChildren = get(mainFigure,'Children');
zOrder = find(figureChildren == mainAxes);
%Calculate where axesLeft and axesRight will be layed on screen
%And their respctive XLimits
leftXLimTemp = [mainXLim(1) splitXLim(1)];
rightXLimTemp = [splitXLim(2) mainXLim(2)];
leftXRangeTemp = leftXLimTemp(2) - leftXLimTemp(1);
rightXRangeTemp = rightXLimTemp(2) - rightXLimTemp(1);
leftWidthTemp = leftXRangeTemp / (leftXRangeTemp + rightXRangeTemp) * (mainWidth - splitWidth);
rightWidthTemp = rightXRangeTemp / (leftXRangeTemp + rightXRangeTemp) * (mainWidth - splitWidth);
leftStretch = (leftWidthTemp + splitWidth/2) / leftWidthTemp;
leftXRange = leftXRangeTemp * leftStretch;
leftWidth = leftWidthTemp * leftStretch;
rightStretch = (rightWidthTemp + splitWidth/2) / rightWidthTemp;
rightXRange = rightXRangeTemp * rightStretch;
rightWidth = rightWidthTemp * rightStretch;
leftXLim = [mainXLim(1) mainXLim(1)+leftXRange];
rightXLim = [mainXLim(2)-rightXRange mainXLim(2)];
if (strcmp(mainXDir, 'normal'))
leftPosition = mainPosition;
leftPosition(3) = leftWidth;
rightPosition = mainPosition;
rightPosition(1) = mainPosition(1) + leftWidth;
rightPosition(3) = rightWidth;
else
%Left Axis will actually go on the right side a vise versa
rightPosition = mainPosition;
rightPosition(3) = rightWidth;
leftPosition = mainPosition;
leftPosition(1) = mainPosition(1) + rightWidth;
leftPosition(3) = leftWidth;
end
%Create the Annotations layer, if the Layer is top, draw the axes on
%top (e.g. after) drawing the left and right pane
if strcmp(mainLayer,'bottom')
annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent)
end
%Create and position the leftAxes. Remove all Y Axis Annotations, the
%title, and a potentially offensive tick mark
leftAxes = copyobj(mainAxes,mainParent);
set(leftAxes,'Position', leftPosition, ...
'XLim', leftXLim, ...
'YLim', mainYLim, ...
'YGrid' ,'off', ...
'YMinorGrid', 'off', ...
'YMinorTick','off', ...
'YTick', [], ...
'YTickLabel', [], ...
'box','off');
if strcmp(mainLayer,'bottom')
set(leftAxes,'Color','none');
end
delete(get(leftAxes,'YLabel'));
delete(get(leftAxes,'XLabel'));
delete(get(leftAxes,'Title'));
if strcmp(mainYTickLabelMode,'auto')
xTick = get(leftAxes,'XTick');
set(leftAxes,'XTick',xTick(1:(end-1)));
end
%Create and position the rightAxes. Remove all Y Axis annotations, the
%title, and a potentially offensive tick mark
rightAxes = copyobj(mainAxes,mainParent);
set(rightAxes,'Position', rightPosition, ...
'XLim', rightXLim, ...
'YLim', mainYLim, ...
'YGrid' ,'off', ...
'YMinorGrid', 'off', ...
'YMinorTick','off', ...
'YTick', [], ...
'YTickLabel', [], ...
'box','off');
if strcmp(mainLayer,'bottom')
set(rightAxes,'Color','none');
end
delete(get(rightAxes,'YLabel'));
delete(get(rightAxes,'XLabel'));
delete(get(rightAxes,'Title'));
if strcmp(mainYTickLabelMode,'auto')
xTick = get(rightAxes,'XTick');
set(rightAxes,'XTick',xTick(2:end));
end
%Create the Annotations layer, if the Layer is top, draw the axes on
%top (e.g. after) drawing the left and right pane
if strcmp(mainLayer,'top')
annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent);
set(annotationAxes, 'Color','none');
end
%Create breakAxes, remove all graphics objects and hide all annotations
breakAxes = copyobj(mainAxes,mainParent);
children = get(breakAxes,'Children');
for i = 1:numel(children)
delete(children(i));
end
set(breakAxes,'Color','none');
%Stretch the breakAxes vertically to cover the horzontal axes lines
orignalUnits = get(breakAxes,'Units');
set(breakAxes,'Units','Pixel');
breakPosition = get(breakAxes,'Position');
nudgeFactor = get(breakAxes,'LineWidth');
breakPosition(4) = breakPosition(4) + nudgeFactor;
set(breakAxes,'Position',breakPosition);
set(breakAxes,'Units',orignalUnits);
%Stretch the breakAxes vertically to create an overhang for sylistic
%effect
breakPosition = get(breakAxes,'Position');
breakPosition(2) = breakPosition(2) - yOverhang;
breakPosition(4) = breakPosition(4) + 2*yOverhang;
set(breakAxes,'Position',breakPosition);
%Create a sine shaped patch to seperate the 2 sides
breakXLim = [mainPosition(1) mainPosition(1)+mainPosition(3)];
set(breakAxes,'xlim',breakXLim);
theta = linspace(0,2*pi,100);
yPoints = linspace(mainYLim(1),mainYLim(2),100);
amp = splitWidth/2 * 0.9;
xPoints1 = amp * sin(theta) + mainPosition(1) + leftWidthTemp;
xPoints2 = amp * sin(theta) + mainPosition(1) + mainPosition(3) - rightWidthTemp;
patchPointsX = [xPoints1 xPoints2(end:-1:1) xPoints1(1)];
patchPointsY = [yPoints yPoints(end:-1:1) yPoints(1)];
patch(patchPointsX,patchPointsY ,figureColor,'EdgeColor',figureColor,'Parent',breakAxes);
%Create A Line To Delineate the left and right edge of the patch
line('xData',xPoints1,'ydata',yPoints,'Parent',breakAxes,'Color',mainYColor,'LineWidth',mainLineWidth);
line('xData',xPoints2,'ydata',yPoints,'Parent',breakAxes,'Color',mainYColor,'LineWidth',mainLineWidth);
set(breakAxes,'Visible','off');
%Make the old main axes invisiable
invisibleObjects = RecursiveSetVisibleOff(mainAxes);
%Preserve the z-order of the figure
uistack([leftAxes rightAxes breakAxes annotationAxes],'down',zOrder-1)
%Set the rezise mode to position so that we can dynamically change the
%size of the figure without screwing things up
set([leftAxes rightAxes breakAxes annotationAxes],'ActivePositionProperty','Position');
%Playing with the titles labels etc can cause matlab to reposition
%the axes in some cases. Mannually force the position to be correct.
set([breakAxes annotationAxes],'Position',mainPosition);
%Save the axes so we can unbreak the axis easily
breakInfo = struct();
breakInfo.leftAxes = leftAxes;
breakInfo.rightAxes = rightAxes;
breakInfo.breakAxes = breakAxes;
breakInfo.annotationAxes = annotationAxes;
breakInfo.invisibleObjects = invisibleObjects;
end
function list = RecursiveSetVisibleOff(handle)
list = [];
list = SetVisibleOff(handle,list);
end
function list = SetVisibleOff(handle, list)
if (strcmp(get(handle,'Visible'),'on'))
set(handle,'Visible','off');
list = [list handle];
end
children = get(handle,'Children');
for i = 1:numel(children)
list = SetVisibleOff(children(i),list);
end
end
function annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent)
%Create Annotation Axis, Remove graphics objects, XAxis annotations
%(except XLabel) and make background transparent
annotationAxes = copyobj(mainAxes,mainParent);
set(annotationAxes,'YLimMode','Manual');
children = get(annotationAxes,'Children');
for i = 1:numel(children)
delete(children(i));
end
%Save the xLabelpostion because it will move when we delete xAxis
%ticks
xLabel = get(annotationAxes,'XLabel');
xLabelPosition = get(xLabel,'Position');
set(annotationAxes,'XGrid' ,'off', ...
'XMinorGrid', 'off', ...
'XMinorTick','off', ...
'XTick', [], ...
'XTickLabel', []);
%Restore the pevious label postition
set(xLabel,'Position',xLabelPosition);
end
2.2 截断纵坐标
2.2.1 案例
MATLAB相关代码如下:
clear;
clc;
close all;
%% 纵轴截断后图像
% 数据
data=[2.3 2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3 2.5 2.1 2 1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3 3 3 3 3 2.5
10.8 10.6 10.5 10.2 10.1 10.1 10.1 10.1 10.1 9.1
];
%% 参数设置
x_min=0.1; %横坐标刻度最小值
x_interval=0.1; %横坐标刻度间隔距离
x_max=1; %横坐标刻度最大值
X=x_min:x_interval:x_max;
h=plot(X, data(1, :), 'k*-', X, data(2, :), 'g^-', X, data(3, :), 'r-s', X, data(4, :), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east'); %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4,'color','k');
% text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95], 'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
%% 调用已有的代码,两个函数只能调用一个,不能同时调用,出错
breakyaxis([4 9]); % 截断纵坐标
saveas(gcf,sprintf('Other_Break_Axis.jpg'),'bmp'); %保存图片
图形如下:
2.2.2 调用函数
调用代码:
breakyaxis([minYvalue,maxYvalue])
函数代码:文章来源:https://www.toymoban.com/news/detail-460257.html
% breakyaxes splits data in an axes so that data is in a low and high pane.
%
% breakYAxes(splitYLim) splitYLim is a 2 element vector containing a range
% of y values from splitYLim(1) to splitYLim(2) to remove from the axes.
% They must be within the current yLimis of the axes.
%
% breakYAxes(splitYLim,splitHeight) splitHeight is the distance to
% seperate the low and high side. Units are the same as
% get(AX,'uints') default is 0.015
%
% breakYAxes(splitYLim,splitHeight,xOverhang) xOverhang stretches the
% axis split graphic to extend past the top and bottom of the plot by
% the distance set by XOverhang. Units are the same as get(AX,'units')
% default value is 0.015
%
% breakYAxes(AX, ...) performs the operation on the axis specified by AX
%
function breakInfo = breakyaxis(varargin)
%Validate Arguements
if nargin < 1 || nargin > 4
error('Wrong number of arguements');
end
if isscalar(varargin{1}) && ishandle(varargin{1})
mainAxes = varargin{1};
argOffset = 1;
argCnt = nargin - 1;
if ~strcmp(get(mainAxes,'Type'),'axes')
error('Handle object must be Type Axes');
end
else
mainAxes = gca;
argOffset = 0;
argCnt = nargin;
end
if (strcmp(get(mainAxes,'XScale'),'log'))
error('Log X Axes are not supported');
end
if (argCnt < 3)
xOverhang = 0.015;
else
xOverhang = varargin{3 + argOffset};
if numel(xOverhang) ~= 1 || ~isreal(xOverhang) || ~isnumeric(xOverhang)
error('XOverhang must be a scalar number');
elseif (xOverhang < 0)
error('XOverhang must not be negative');
end
xOverhang = double(xOverhang);
end
if (argCnt < 2)
splitHeight = 0.015;
else
splitHeight = varargin{2 + argOffset};
if numel(xOverhang) ~= 1 || ~isreal(xOverhang) || ~isnumeric(xOverhang)
error('splitHeight must be a scalar number');
elseif (xOverhang < 0)
error('splitHeight must not be negative');
end
splitHeight = double(splitHeight);
end
splitYLim = varargin{1 + argOffset};
if numel(splitYLim) ~= 2 || ~isnumeric(splitYLim) || ~isreal(xOverhang)
error(splitYLim,'Must be a vector length 2');
end
splitYLim = double(splitYLim);
mainYLim = get(mainAxes,'YLim');
if (any(splitYLim >= mainYLim(2)) || any(splitYLim <= mainYLim(1)))
error('splitYLim must be in the range given by get(AX,''YLim'')');
end
mainPosition = get(mainAxes,'Position');
if (splitHeight > mainPosition(3) )
error('Split width is too large')
end
%We need to create 4 axes
% lowAxes - is used for the low y axis and low pane data
% highAxes - is used to the high y axis and high pane data
% annotationAxes - is used to display the x axis and title
% breakAxes - this is an axes with the same size and position as main
% is it used to draw a seperator between the low and high side
%Grab Some Parameters from the main axis (e.g the one we are spliting)
mainYLim = get(mainAxes,'YLim');
mainXLim = get(mainAxes,'XLim');
mainPosition = get(mainAxes,'Position');
mainParent = get(mainAxes,'Parent');
mainHeight = mainPosition(4); %Positions have the format [low bottom width height]
%mainYRange = mainYLim(2) - mainYLim(1);
mainFigure = get(mainAxes,'Parent');
mainXColor = get(mainAxes,'XColor');
mainLineWidth = get(mainAxes,'LineWidth');
figureColor = get(mainFigure,'Color');
mainXTickLabelMode = get(mainAxes,'XTickLabelMode');
mainYLabel = get(mainAxes,'YLabel');
mainYDir = get(mainAxes,'YDir');
mainLayer = get(mainAxes,'Layer');
%Save Main Axis Z Order
figureChildren = get(mainFigure,'Children');
zOrder = find(figureChildren == mainAxes);
%Calculate where axesLow and axesHigh will be layed on screen
%And their respctive YLimits
lowYLimTemp = [mainYLim(1) splitYLim(1)];
highYLimTemp = [splitYLim(2) mainYLim(2)];
lowYRangeTemp = lowYLimTemp(2) - lowYLimTemp(1);
highYRangeTemp = highYLimTemp(2) - highYLimTemp(1);
lowHeightTemp = lowYRangeTemp / (lowYRangeTemp + highYRangeTemp) * (mainHeight - splitHeight);
highHeightTemp = highYRangeTemp / (lowYRangeTemp + highYRangeTemp) * (mainHeight - splitHeight);
lowStretch = (lowHeightTemp + splitHeight/2) / lowHeightTemp;
lowYRange = lowYRangeTemp * lowStretch;
lowHeight = lowHeightTemp * lowStretch;
highStretch = (highHeightTemp + splitHeight/2) / highHeightTemp;
highYRange = highYRangeTemp * highStretch;
highHeight = highHeightTemp * highStretch;
lowYLim = [mainYLim(1) mainYLim(1)+lowYRange];
highYLim = [mainYLim(2)-highYRange mainYLim(2)];
if (strcmp(mainYDir, 'normal'))
lowPosition = mainPosition;
lowPosition(4) = lowHeight;
highPosition = mainPosition; %(!!!) look here for position indices!
highPosition(2) = mainPosition(2) + lowHeight;
highPosition(4) = highHeight;
else
%Low Axis will actually go on the high side a vise versa
highPosition = mainPosition;
highPosition(4) = highHeight;
lowPosition = mainPosition;
lowPosition(2) = mainPosition(2) + highHeight;
lowPosition(4) = lowHeight;
end
%Create the Annotations layer, if the Layer is top, draw the axes on
%top (e.g. after) drawing the low and high pane
if strcmp(mainLayer,'bottom')
annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent)
end
%Create and position the lowAxes. Remove all X Axis Annotations, the
%title, and a potentially offensive tick mark
lowAxes = copyobj(mainAxes,mainParent);
set(lowAxes,'Position', lowPosition, ...
'YLim', lowYLim, ...
'XLim', mainXLim, ...
'XGrid' ,'off', ...
'XMinorGrid', 'off', ...
'XMinorTick','off', ...
'XTick', [], ...
'XTickLabel', [], ...
'box','off');
if strcmp(mainLayer,'bottom')
set(lowAxes,'Color','none');
end
delete(get(lowAxes,'XLabel'));
delete(get(lowAxes,'YLabel'));
delete(get(lowAxes,'Title'));
if strcmp(mainXTickLabelMode,'auto')
yTick = get(lowAxes,'YTick');
set(lowAxes,'YTick',yTick(1:(end-1)));
end
%Create and position the highAxes. Remove all X Axis annotations, the
%title, and a potentially offensive tick mark
highAxes = copyobj(mainAxes,mainParent);
set(highAxes,'Position', highPosition, ...
'YLim', highYLim, ...
'XLim', mainXLim, ...
'XGrid' ,'off', ...
'XMinorGrid', 'off', ...
'XMinorTick','off', ...
'XTick', [], ...
'XTickLabel', [], ...
'box','off');
if strcmp(mainLayer,'bottom') %(!!!) is it only about layers?
set(highAxes,'Color','none');
end
delete(get(highAxes,'XLabel'));
delete(get(highAxes,'YLabel'));
delete(get(highAxes,'Title'));
if strcmp(mainXTickLabelMode,'auto')
yTick = get(highAxes,'YTick');
set(highAxes,'YTick',yTick(2:end));
end
%Create the Annotations layer, if the Layer is top, draw the axes on
%top (e.g. after) drawing the low and high pane
if strcmp(mainLayer,'top')
annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent);
set(annotationAxes, 'Color','none');
end
%Create breakAxes, remove all graphics objects and hide all annotations
breakAxes = copyobj(mainAxes,mainParent);
children = get(breakAxes,'Children');
for i = 1:numel(children)
delete(children(i));
end
set(breakAxes,'Color','none');
%Stretch the breakAxes horizontally to cover the vertical axes lines
orignalUnits = get(breakAxes,'Units');
set(breakAxes,'Units','Pixel');
breakPosition = get(breakAxes,'Position');
nudgeFactor = get(breakAxes,'LineWidth');
breakPosition(3) = breakPosition(3) + nudgeFactor;
set(breakAxes,'Position',breakPosition);
set(breakAxes,'Units',orignalUnits);
%Stretch the breakAxes horizontally to create an overhang for sylistic
%effect
breakPosition = get(breakAxes,'Position');
breakPosition(1) = breakPosition(1) - xOverhang;
breakPosition(3) = breakPosition(3) + 2*xOverhang;
set(breakAxes,'Position',breakPosition);
%Create a sine shaped patch to seperate the 2 sides
breakYLim = [mainPosition(2) mainPosition(2)+mainPosition(4)];
set(breakAxes,'ylim',breakYLim);
theta = linspace(0,2*pi,100);
xPoints = linspace(mainXLim(1),mainXLim(2),100);
amp = splitHeight/2 * 0.9;
yPoints1 = amp * sin(theta) + mainPosition(2) + lowHeightTemp;
yPoints2 = amp * sin(theta) + mainPosition(2) + mainPosition(4) - highHeightTemp;
patchPointsY = [yPoints1 yPoints2(end:-1:1) yPoints1(1)];
patchPointsX = [xPoints xPoints(end:-1:1) xPoints(1)];
patch(patchPointsX,patchPointsY ,figureColor,'EdgeColor',figureColor,'Parent',breakAxes); %use of pathc(!!!)?
%Create A Line To Delineate the low and high edge of the patch
line('yData',yPoints1,'xdata',xPoints,'Parent',breakAxes,'Color',mainXColor,'LineWidth',mainLineWidth);
line('yData',yPoints2,'xdata',xPoints,'Parent',breakAxes,'Color',mainXColor,'LineWidth',mainLineWidth);
set(breakAxes,'Visible','off');
%Make the old main axes invisiable
invisibleObjects = RecursiveSetVisibleOff(mainAxes);
%Preserve the z-order of the figure
uistack([lowAxes highAxes breakAxes annotationAxes],'down',zOrder-1)
%Set the rezise mode to position so that we can dynamically change the
%size of the figure without screwing things up
set([lowAxes highAxes breakAxes annotationAxes],'ActivePositionProperty','Position');
%Playing with the titles labels etc can cause matlab to reposition
%the axes in some cases. Mannually force the position to be correct.
set([breakAxes annotationAxes],'Position',mainPosition);
%Save the axes so we can unbreak the axis easily
breakInfo = struct();
breakInfo.lowAxes = lowAxes;
breakInfo.highAxes = highAxes;
breakInfo.breakAxes = breakAxes;
breakInfo.annotationAxes = annotationAxes;
breakInfo.invisibleObjects = invisibleObjects;
end
function list = RecursiveSetVisibleOff(handle)
list = [];
list = SetVisibleOff(handle,list);
end
function list = SetVisibleOff(handle, list)
if (strcmp(get(handle,'Visible'),'on'))
set(handle,'Visible','off');
list = [list handle];
end
children = get(handle,'Children');
for i = 1:numel(children)
list = SetVisibleOff(children(i),list);
end
end
function annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent)
%Create Annotation Axis, Remove graphics objects, YAxis annotations
%(except YLabel) and make background transparent
annotationAxes = copyobj(mainAxes,mainParent);
set(annotationAxes,'XLimMode','Manual');
children = get(annotationAxes,'Children');
for i = 1:numel(children)
delete(children(i));
end
%Save the yLabelpostion because it will move when we delete yAxis
%ticks
yLabel = get(annotationAxes,'YLabel');
yLabelPosition = get(yLabel,'Position');
set(annotationAxes,'YGrid' ,'off', ...
'YMinorGrid', 'off', ...
'YMinorTick','off', ...
'YTick', [], ...
'YTickLabel', []);
%Restore the pevious label postition
set(yLabel,'Position',yLabelPosition);
end
参考
1.博客-MATLAB实例:截断坐标轴(Broken Axis)文章来源地址https://www.toymoban.com/news/detail-460257.html
到了这里,关于【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!