zoukankan      html  css  js  c++  java
  • MATLAB实例:截断坐标轴(Broken Axis)

    MATLAB实例:截断坐标轴(Broken Axis)

    作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/

    更多请看:随笔分类 - MATLAB作图

        有时候,用MATLAB绘制坐标图时会出现有的曲线值都特别大,有的曲线值都很小,但是又想在同一幅图中将他们展示出来,于是需要截断坐标轴的刻度或者改变纵轴的刻度,使其不均匀。本博客写了截断横坐标纵坐标,以及横纵坐标都截断的实例(基本思路是超过截断位置的曲线通通向下或向左平移,在坐标轴上加双斜杠,最后只截取平移后位置之前的曲线,其余部分抛弃掉),并给出了mathworks上两个函数的实例,同时,纵轴刻度不均匀采用对数刻度来解决,也给出了相应的实例,一起看看效果。

    1. 原始图像

    clear; clc; close all;
    % 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/
    % 原始图片
    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);
    
    set(gcf,'color','w') %后面背景变白
    
    xlim([x_min x_max]); %横坐标范围
    xlabel('x'); 
    string='y';
    ylabel(string);
    legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east');  %图例
    saveas(gcf,sprintf('Original image.jpg'),'bmp'); %保存图片
    

    2. 截断横坐标

    clear; clc; close all;
    % 横轴截断后图像
    % 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/
    % 数据
    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);
    
    set(gcf,'color','w') %后面背景变白
    
    xlim([x_min x_max_new]); %横坐标范围
    xlabel('x'); 
    string='y';
    ylabel(string);
    legend('Line-1', 'Line-2', 'Line-3', 'Line-4',  'Location', 'east');  %图例 根据曲线个数修改
    
    % 横坐标截断设置
    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'); %修改坐标名称、字体
    saveas(gcf,sprintf('Break_X_Axis.jpg'),'bmp'); %保存图片

    3. 截断纵坐标

    clear; clc; close all;
    % 纵轴截断后图像
    % 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/
    % 数据
    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);
    
    set(gcf,'color','w') %后面背景变白
    
    xlim([x_min x_max]); %横坐标范围
    xlabel('x'); 
    string='y';
    ylabel(string);
    legend('Line-1', 'Line-2', 'Line-3', 'Line-4',  'Location', 'east');  %图例 根据曲线个数修改
    
    % 纵坐标截断设置
    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'); %修改坐标名称、字体
    saveas(gcf,sprintf('Break_Y_Axis.jpg'),'bmp'); %保存图片
    

    4. 截断横纵坐标

    clear; clc; close all;
    % 横轴截断后图像
    % 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/
    % 数据
    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);
    
    set(gcf,'color','w') %后面背景变白
    
    xlim([x_min x_max_new]); %横坐标范围
    xlabel('x'); 
    string='y';
    ylabel(string);
    legend('Line-1', 'Line-2', 'Line-3', 'Line-4',  'Location', 'east');  %图例 根据曲线个数修改
    
    % 横坐标截断设置
    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'); %修改坐标名称、字体
    saveas(gcf,sprintf('Break_X_Y_Axis.jpg'),'bmp'); %保存图片

        如果改变截断参数值导致程序运行不出来,多半是逻辑运算符出的Bug,所以我在X>x_break_end+eps这种不等判断后加了eps,等式判断符X==x_break_start出Bug改为(X-x_break_start)<eps。欢迎一起交流学习~

    5. 别人家的程序

        在mathworks官网找了两个程序,分别截断横坐标与纵坐标,但还没有同时截断这两个的程序。而且,使用了这两个函数之后,图例显式竟然变暗了,不知道是什么原因,一起看看效果。

        代码来源:www.mathworks.com/matlabcentral/fileexchange/42905-break-x-axiswww.mathworks.com/matlabcentral/fileexchange/45760-break-y-axis

    breakxaxis.m

    % 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

    breakyaxis.m

    % 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
    %
    % From: https://www.mathworks.com/matlabcentral/fileexchange/45760-break-y-axis?s_tid=srchtitle
    % demo: breakyaxis([80 110]); 
    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
    

    demo.m

    clear; clc; close all;
    % 纵轴截断后图像
    % 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/
    % 数据
    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);
    
    set(gcf,'color','w') %后面背景变白
    
    xlim([x_min x_max]); %横坐标范围
    xlabel('x'); 
    string='y';
    ylabel(string);
    legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location','northoutside', 'NumColumns',4);  %图例
    % 调用已有的代码,两个函数只能调用一个,不能同时调用,出错
    breakyaxis([4 9]);  % 截断纵坐标
    % breakxaxis([0.5 0.9]);  %截断横坐标
    saveas(gcf,sprintf('Other_Break_Axis.jpg'),'bmp'); %保存图片
    

    6. 纵轴刻度值不均匀

        如果想要纵轴刻度值不均匀,可以在plot();后面加一句set(gca,'yscale','log')即可,但是对于不是对数取值的图像来说,效果并不是很好,如下图。

    clear; clc; close all;
    % 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/
    % 原始图片
    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);
    set(gca,'yscale','log')
    set(gcf,'color','w') %后面背景变白
    
    xlim([x_min x_max]); %横坐标范围
    xlabel('x'); 
    string='y';
    ylabel(string);
    legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location','northoutside', 'NumColumns',4);  %图例
    saveas(gcf,sprintf('Log image.jpg'),'bmp'); %保存图片
    

    作者:凯鲁嘎吉
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    yii2.0缓存的使用
    yii2.0框架where条件的使用
    yii2.0自带验证码使用
    spring中MessageSource的配置使用方法1[转]
    DOM、JDOM、DOM4J的区别
    探秘Java虚拟机——内存管理与垃圾回收
    MySQL开发规范和原则大全
    Java Classloader机制解析
    Junit之测试顺序---FixMethodOrder
    MySQL的btree索引和hash索引的区别
  • 原文地址:https://www.cnblogs.com/kailugaji/p/14526291.html
Copyright © 2011-2022 走看看