MATLAB | 全网唯一!使用MATLAB绘制各类螺旋图

文摘   其他   2024-05-01 22:23   山东  
请尊重原创劳动成果
转载请注明本文链接
及文章作者:slandarer

全网唯一,MATLAB绘制各类螺旋图,还在为X轴过长而困扰吗?把X轴盘起来就可以优雅的绘图!!今天带来的是由本人开发的SSpiral MATLAB 工具包,真的是好久不见了,这次一登上账号就发现已经放开了留言功能,大家可以在文末留言互动试试,本期工具函数绘图效果:

工具函数放在最后,先看基本用法:


使用教程

1 坐标区域创建

使用SSpiral(gca)的形式创建坐标区域,通过obj.set()函数设置各种属性:

% Create spiral-axes
SS = SSpiral(gca);

设置螺旋角度范围:

% Set theta limit
SS.set('TLim',[0,3*360])  

SS.set('TLim',[120,3*360])

设置X轴Y轴范围:

% Set X-axis limit and Y-axis limit
SS.set('XLim',[0,120], 'YLim',[0,10])

自定义刻度:

SS.set('XTick',0:5:120)

调整刻度线长度:

% Set ticks and minor-ticks length
SS.set('TickLength',[.2,.15])

隐藏次刻度线:

SS.set('XMinorTick','off')

2 柱状图绘制

多次使用obj.bar()函数,画好多组柱状图:

figure('Units','normalized''Position',[.1,.1,.6,.75])

% Create spiral-axes
SS1 = SSpiral(gca);
SS1.set('TLim',[0,2*360+180], 'XLim',[0,200]+.5'YLim',[0,1], 'XTick',0:5:200)  

X = rand(1,200);
SS1.bar(X);
SS1.bar(X./2);
SS1.bar(X./4);

legend({'AAA','BBB'}, 'FontSize',12'FontName','Times New Roman')

画一组柱状图但是正负数不同颜色:

figure('Units','normalized''Position',[.1,.1,.6,.75])

% Create spiral-axes
SS2 = SSpiral(gca);
SS2.set('TLim',[0,2*360+180], 'XLim',[0,200]+.5'YLim',[-.5,.5], 'XTick',0:5:200)  

X = rand(1,200) - .5;
X1 = X.*(X>0);
X2 = X.*(X<0);
SS2.bar(X1);
SS2.bar(X2);

legend({'AAA','BBB'}, 'FontSize',12'FontName','Times New Roman')

3 标签及背景色

figure('Units','normalized''Position',[.1,.1,.6,.75])
% Create spiral-axes
SS2 = SSpiral(gca);
SS2.set('TLim',[0,2*360+180], 'XLim',[0,200]+.5'YLim',[0,1], 'XTick',0:5:200)  

% Set background color to light-blue
SS2.set('BackgroundColor',[228,243,245]./255)

X = rand(1,200);
SS2.bar(X, 'FaceColor',[253,193,202]./255'EdgeColor','w');

% Set tick-labels font
SS2.set('TickLabelFont', {'FontSize',10'FontName','Times New Roman''Color',[0,0,.5]})

4 堆叠柱状图

很简单就是输入多列的数据:

figure('Units','normalized''Position',[.1,.1,.6,.75])

% Create spiral-axes
SS1 = SSpiral(gca);
SS1.set('TLim',[0,2*360+180], 'XLim',[0,200]+.5'YLim',[0,2], 'XTick',0:5:200)  

X = rand(200,2);
SS1.bar(X, 'FaceColor',[0.46,0.67,0.180.30,0.74,0.93]);
legend({'AAA','BBB'}, 'FontSize',12'FontName','Times New Roman')




% =========================================================================
figure('Units','normalized''Position',[.1,.1,.6,.75])

% Create spiral-axes
SS2 = SSpiral(gca);
SS2.set('TLim',[0,2*360+180], 'XLim',[0,200]+.5'YLim',[-1,1], 'XTick',0:5:200)  

X = rand(200,2)-.5;
SS2.bar(X, 'FaceColor',[0.46,0.67,0.180.30,0.74,0.93]);
legend({'AAA','BBB'}, 'FontSize',12'FontName','Times New Roman')

5 面积图

基础绘制:

% area diagram on spiral-axes
figure('Units','normalized''Position',[.1,.1,.6,.75])
SS1 = SSpiral(gca);
SS1.set('TLim',[0,2*360+180], 'XLim',[1,200], 'YLim',[0,1], 'XTick',0:5:200)  
Y = rand(200,1);
SS1.area(1:200,Y);


% =========================================================================
% area diagrams on spiral-axes
figure('Units','normalized''Position',[.1,.1,.6,.75])
SS2 = SSpiral(gca);
SS2.set('TLim',[0,2*360+180], 'XLim',[1,200], 'YLim',[0,1], 'XTick',0:5:200)  
Y = rand(200,2);
SS2.area(1:200,Y(:,1));
SS2.area(1:200,Y(:,2));

正负数部分不同颜色:

% Different colors in the positive and negative parts
figure('Units','normalized''Position',[.1,.1,.6,.75])
SS3 = SSpiral(gca);
SS3.set('TLim',[0,2*360+180], 'XLim',[1,200], 'YLim',[-.5,.5], 'XTick',0:5:200)  
Y = rand(200,1)-.5;
Y = interp1(1:200, Y ,(1:.1:200).');
SS3.area(1:.1:200,Y.*(Y>0));
SS3.area(1:.1:200,Y.*(Y<0));

堆叠面积图:

% 堆叠面积图
% stacked-area diagram
figure('Units','normalized''Position',[.1,.1,.6,.75])
SS4 = SSpiral(gca);
SS4.set('TLim',[0,2*360+180], 'XLim',[1,200], 'YLim',[0,1.8], 'XTick',0:5:200)  
Y = rand(200,2);
SS4.area(1:200,Y);
legend({'AAA','BBB'}, 'FontSize',12'FontName','Times New Roman')

含负数堆叠面积图:

% 含有负数的堆叠面积图
% Containing negative numbers stacked-area diagram
figure('Units','normalized''Position',[.1,.1,.6,.75])
SS5 = SSpiral(gca);
SS5.set('TLim',[0,2*360+180], 'XLim',[1,200], 'YLim',[-1,1], 'XTick',0:5:200)  
Y = rand(200,2)-.5;
Y = interp1(1:200, Y ,1:.1:200);
SS5.area(1:.1:200,Y);

6 折线图与标签格式

通过设置TickLabelFormat属性来设置标签格式,应该输入一个将数值转化为字符串的函数,通过XTickLabel,YTickLabel设置标签文本:

figure('Units','normalized''Position',[.1,.1,.6,.75])


SS = SSpiral(gca);
SS.set('TLim',[0,3*360], 'XLim',[0,240], 'YLim',[0,1], 'XTick',0:20/3:240)  


Y = rand(121,2);
SS.plot(repmat((0:2:240)',[1,2]),Y, 'LineWidth',1'Marker''o');


pause(1)
% 修改标签格式为最简分数
% Change the label format to the simplest fraction
SS.set('TickLabelFormat',@(x) strtrim(rats(x)))

pause(1)
% 修改标签格式为指定字符串
strCell = [num2cell(char(32*ones(1,25))),{'January','February','March','April','May','June','July','August','September','October','November','December'}];
SS.set('XTickLabel',strCell)
SS.set('TickLabelFont',{'FontSize',14'FontName','Times New Roman'})

7 散点图

figure('Units','normalized''Position',[.1,.1,.6,.75])
SS = SSpiral(gca);
SS.set('TLim',[0,2*360+180], 'XLim',[1,200], 'YLim',[0,1], 'XTick',0:5:200)  

Y = rand(1,100);
SS.scatter(1:2:200,Y,'filled''CData',[129,170,174]./255'Marker','o');

8 高亮区域

使用obj.xregion(lim)obj.yregion(lim)函数:

figure('Units','normalized''Position',[.1,.1,.6,.75])
SS = SSpiral(gca);
SS.set('TLim',[0,2*360+180], 'XLim',[1,200], 'YLim',[0,1], 'XTick',0:5:200)  

% X-region and Y-region
SS.xregion([50,100]);
SS.yregion([.7,1], 'FaceColor',[129,170,174]./255)

9 综合运用:聚类树

rng(3)

% draw dendrogram
Data = rand(200,3);
N = 5;
Z = linkage(Data,'average');
T = cluster(Z,'maxclust',N);
cutoff = median([Z(end-(N-1),3), Z(end-(N-2),3)]);
[LineSet, ~, order] = dendrogram(Z, 0'Orientation''top');
XSet = reshape([LineSet(:).XData], 4, []);
YSet = reshape([LineSet(:).YData], 4, []);
YSet = max(max(YSet))-YSet;
close all


figure('Units','normalized''Position',[.1,.1,.6,.75])
SS = SSpiral(gca);
SS.set('TLim',[0,2*360+180], 'XLim',[0,200]+.5'YLim',[0,max(max(YSet))], 'XTick',0:5:200
% use function obj.line to draw lines with different length
SS.line(XSet, YSet, 'Color','k''LineWidth',1);


CList = [ 0.3569    0.0784    0.0784
    0.6784    0.4471    0.1725
    0.1020    0.3882    0.5176
    0.1725    0.4196    0.4392
    0.2824    0.2275    0.2902
         0         0         0];
TT = T(order);
classNum = unique(TT, 'stable');
for i = 1:N
    tX = [find(TT==classNum(i),1,'first')-.5find(TT==classNum(i),1,'last')+.5];
    lgdHdl(i) = SS.xregion(tX, 'FaceColor',CList(i,:), 'FaceAlpha',.4);
end

legend(lgdHdl, {'Set-S','Set-L','Set-A','Set-N','Set-M'})

工具函数完整代码

classdef SSpiral < handle
% Copyright (c) 2024, Zhaoxu Liu / slandarer
% =========================================================================
% @author : slandarer
% 公众号  : slandarer随笔
% 知乎    : slandarer
% -------------------------------------------------------------------------
% Zhaoxu Liu / slandarer (2024). Spiral diagram 
% (https://www.mathworks.com/matlabcentral/fileexchange/164966-spiral-diagram), 
% MATLAB Central File Exchange. Retrieved May 1, 2024.
    properties
        ax,
        XLim, XTick, XMinorTick = 'on';
        YLim, YTick,
        Height = 1;
        BackgroundColor = [239,239,239]./255
        TLim = [02*360]
        TickLength = [.055.02];
        TickColor = [0,0,0];
        TickWidth = 1;
        XTickLabel
        YTickLabel
        TickLabelFont = {'FontSize',10'FontName','Times New Roman'}
        TickLabelFormat = @(x) num2str(x)
        arginList = {'XLim''YLim''TLim''XTick''YTick''Height',...
                      'BackgroundColor''TickLength''TickColor''TickWidth',...
                      'TickLabelFont''TickLabelFormat''TickLabel', ...
                      'XMinorTick''YMinorTick''XTickLabel''YTickLabel'}
        ColorOrder = [    0.2392    0.4627    0.6392
            0.3686    0.6784    0.7451
            0.3686    0.6314    0.4627
            0.6549    0.3804    0.1373
            0.4784    0.2510    0.0941
            0.7059    0.5529    0.2824
            0.4627    0.4902    0.4627];
        ColorOrderIndex = 1;
        BkgHdl, XTickHdl, XMinorTickHdl, YTickHdlS, YTickHdlE
    end
% =========================================================================
    methods
        function obj = SSpiral(ax)
            if nargin < 1, ax = gca; end
            obj.ax = ax;
            obj.ax.NextPlot = 'add';
            obj.ax.XGrid = 'off';
            obj.ax.YGrid = 'off';
            obj.ax.Box = 'off';
            obj.ax.XColor = 'none';
            obj.ax.YColor = 'none';
            obj.ax.DataAspectRatio = [1,1,1];
            help SSpiral
            obj.drawAxes(0)
        end
% =========================================================================
        function set(obj, varargin)
            for i = 1:2:(length(varargin)-1)
                tid = ismember(obj.arginList, varargin{i});
                if any(tid)
                obj.(obj.arginList{tid}) = varargin{i+1};
                end
            end
            obj.drawAxes(1)
        end
% =========================================================================
        function drawAxes(obj, flag)
            tT  = linspace(obj.TLim(1), obj.TLim(2), ceil(abs(diff(obj.TLim)))+10)./180.*pi;
            tX1 = (3.77 + 1.4.*abs(tT-obj.TLim(1)./180.*pi)).*cos(tT);
            tY1 = (3.77 + 1.4.*abs(tT-obj.TLim(1)./180.*pi)).*sin(tT);
            tL  = vecnorm([tX1;tY1]);
            tX2 = tX1./tL.*(tL + obj.Height.*2.*pi);
            tY2 = tY1./tL.*(tL + obj.Height.*2.*pi);
            tX  = [tX1, tX2(end:-1:1)];
            tY  = [tY1, tY2(end:-1:1)];
            if flag == 0 
                obj.BkgHdl = fill(obj.ax, tX,tY,obj.BackgroundColor, 'EdgeColor','none');
                obj.BkgHdl.Annotation.LegendInformation.IconDisplayStyle='off';
                
            else
                set(obj.BkgHdl, 'XData',tX, 'YData',tY, 'FaceColor',obj.BackgroundColor)
            end
            if ~isempty(obj.XLim) && ~isempty(obj.YLim)
                if isempty(obj.XTick)
                    tXT = obj.getTick(obj.XLim, (abs(diff(obj.TLim))/360)*10);
                else 
                    tXT = obj.XTick;
                    tXT(tXT<obj.XLim(1)) = [];
                    tXT(tXT>obj.XLim(2)) = [];
                end
                if isempty(obj.YTick)
                    tYT = obj.getTick(obj.YLim, 2);
                else
                    tYT = obj.XTick;
                    tYT(tYT<obj.YLim(1)) = [];
                    tYT(tYT>obj.YLim(2)) = [];
                end
                % ---------------------------------------------------------
                tMXTD = diff(tXT);
                tMXT  = tXT(1) - tMXTD(1) : tMXTD(1)/5 : tXT(end) + tMXTD(1);
                tMXT(tMXT<obj.XLim(1)) = [];
                tMXT(tMXT>obj.XLim(2)) = [];
                % ---------------------------------------------------------
                tT  = (tXT-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
                tT  = tT./180.*pi;
                tX1 = (3.77 + 1.4.*abs(tT-obj.TLim(1)./180.*pi)).*cos(tT);
                tY1 = (3.77 + 1.4.*abs(tT-obj.TLim(1)./180.*pi)).*sin(tT);
                tL  = vecnorm([tX1; tY1]);
                tX2 = tX1./tL.*(tL + obj.Height.*2.*pi);
                tY2 = tY1./tL.*(tL + obj.Height.*2.*pi);
                tX3 = tX1./tL.*(tL + obj.Height.*2.*pi + obj.TickLength(1).*2.*pi);
                tY3 = tY1./tL.*(tL + obj.Height.*2.*pi + obj.TickLength(1).*2.*pi);
                tX  = [tX2; tX3; tX2.*nan]; tX = tX(:);
                tY  = [tY2; tY3; tY2.*nan]; tY = tY(:);
                % ---------------------------------------------------------
                tMT  = (tMXT-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
                tMT  = tMT./180.*pi;
                tMX1 = (3.77 + 1.4.*abs(tMT-obj.TLim(1)./180.*pi)).*cos(tMT);
                tMY1 = (3.77 + 1.4.*abs(tMT-obj.TLim(1)./180.*pi)).*sin(tMT);
                tML  = vecnorm([tMX1; tMY1]);
                tMX2 = tMX1./tML.*(tML + obj.Height.*2.*pi);
                tMY2 = tMY1./tML.*(tML + obj.Height.*2.*pi);
                tMX3 = tMX1./tML.*(tML + obj.Height.*2.*pi + obj.TickLength(2).*2.*pi);
                tMY3 = tMY1./tML.*(tML + obj.Height.*2.*pi + obj.TickLength(2).*2.*pi);
                tMX  = [tMX2; tMX3; tMX2.*nan]; tMX = tMX(:);
                tMY  = [tMY2; tMY3; tMY2.*nan]; tMY = tMY(:);
                % ---------------------------------------------------------
                if isempty(obj.XTickHdl)
                    obj.XTickHdl = plot(tX, tY, 'Color',obj.TickColor, 'LineWidth',obj.TickWidth);
                    obj.XTickHdl.Annotation.LegendInformation.IconDisplayStyle='off';
                else
                    set(obj.XTickHdl, 'XData',tX, 'YData',tY, 'Color',obj.TickColor, 'LineWidth',obj.TickWidth)
                end
                if isempty(obj.XMinorTickHdl)
                    obj.XMinorTickHdl = plot(tMX, tMY, 'Color',obj.TickColor, 'LineWidth',obj.TickWidth, 'Visible',obj.XMinorTick);
                    obj.XMinorTickHdl.Annotation.LegendInformation.IconDisplayStyle='off';
                else
                    set(obj.XMinorTickHdl, 'XData',tMX, 'YData',tMY, 'Color',obj.TickColor, 'LineWidth',obj.TickWidth, 'Visible',obj.XMinorTick)
                end
                % ---------------------------------------------------------
                tObj = findobj(obj.ax,'Tag','SSpiralTxt'); delete(tObj);
                for i = 1:length(tX3)
                    tR = -90+tT(i)/pi*180;
                    if isempty(obj.XTickLabel)
                        tLbl = obj.TickLabelFormat(tXT(i));
                    else
                        tLbl = obj.XTickLabel{min(i,length(obj.XTickLabel))};
                    end
                    if mod(tT(i)/pi*180360) >180
                        tR = tR +180;
                        text(obj.ax,tX3(i),tY3(i),tLbl,...
                        'HorizontalAlignment','center''VerticalAlignment','top',...
                        'Rotation', tR, obj.TickLabelFont{:},'Tag','SSpiralTxt')
                    else
                        text(obj.ax,tX3(i),tY3(i),tLbl,...
                        'HorizontalAlignment','center''VerticalAlignment','bottom',...
                        'Rotation', tR, obj.TickLabelFont{:},'Tag','SSpiralTxt')
                    end      
                end
                % ---------------------------------------------------------
                tX1 = cos(obj.TLim(1)/180*pi).*((tYT-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77);
                tY1 = sin(obj.TLim(1)/180*pi).*((tYT-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77);
                tT = (obj.TLim(1) - 2.*((diff(obj.TLim)>0)-.5).*(90 + 15))/180*pi;
                tX2 = tX1 + cos(tT).*obj.TickLength(1).*2.*pi;
                tY2 = tY1 + sin(tT).*obj.TickLength(1).*2.*pi;
                tX3 = tX1 + cos(tT).*obj.TickLength(1).*1.5.*2.*pi;
                tY3 = tY1 + sin(tT).*obj.TickLength(1).*1.5.*2.*pi;
                tX  = [tX1; tX2; tX2.*nan]; tX = tX(:);
                tY  = [tY1; tY2; tY2.*nan]; tY = tY(:);
                if isempty(obj.YTickHdlS)
                    obj.YTickHdlS= plot(tX, tY, 'Color',obj.TickColor, 'LineWidth',obj.TickWidth);
                    obj.YTickHdlS.Annotation.LegendInformation.IconDisplayStyle='off';
                else
                    set(obj.YTickHdlS, 'XData',tX, 'YData',tY, 'Color',obj.TickColor, 'LineWidth',obj.TickWidth)
                end
                tR = tT/pi*180;
                for i = 1:length(tX2)
                    if isempty(obj.YTickLabel)
                        tLbl = obj.TickLabelFormat(tYT(i));
                    else
                        tLbl = obj.YTickLabel{min(i,length(obj.YTickLabel))};
                    end
                    if mod(tR, 360) > 90 && mod(tR, 360) < 270
                        text(obj.ax,tX3(i),tY3(i),tLbl,...
                            'HorizontalAlignment','right''VerticalAlignment','middle',...
                            'Rotation', tR + 180, obj.TickLabelFont{:},'Tag','SSpiralTxt')
                    else
                        text(obj.ax,tX3(i),tY3(i),tLbl,...
                            'HorizontalAlignment','left''VerticalAlignment','middle',...
                            'Rotation', tR, obj.TickLabelFont{:},'Tag','SSpiralTxt')
                    end

                end
                % ---------------------------------------------------------
                tX1 = cos(obj.TLim(2)/180*pi).*((tYT-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((obj.TLim(2)-obj.TLim(1))./180.*pi));
                tY1 = sin(obj.TLim(2)/180*pi).*((tYT-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((obj.TLim(2)-obj.TLim(1))./180.*pi));
                tT  = (obj.TLim(2) + 2.*((diff(obj.TLim)>0)-.5).*(90))/180*pi;
                tX2 = tX1 + cos(tT).*obj.TickLength(1).*2.*pi;
                tY2 = tY1 + sin(tT).*obj.TickLength(1).*2.*pi;
                tX3 = tX1 + cos(tT).*obj.TickLength(1).*1.5.*2.*pi;
                tY3 = tY1 + sin(tT).*obj.TickLength(1).*1.5.*2.*pi;
                tX  = [tX1; tX2; tX2.*nan]; tX = tX(:);
                tY  = [tY1; tY2; tY2.*nan]; tY = tY(:);
                if isempty(obj.YTickHdlE)
                    obj.YTickHdlE = plot(tX, tY, 'Color',obj.TickColor, 'LineWidth',obj.TickWidth);
                    obj.YTickHdlE.Annotation.LegendInformation.IconDisplayStyle='off';
                else
                    set(obj.YTickHdlE, 'XData',tX, 'YData',tY, 'Color',obj.TickColor, 'LineWidth',obj.TickWidth)
                end
                tR = tT/pi*180;
                for i = 1:length(tX2)
                    if isempty(obj.YTickLabel)
                        tLbl = obj.TickLabelFormat(tYT(i));
                    else
                        tLbl = obj.YTickLabel{min(i,length(obj.YTickLabel))};
                    end
                    if mod(tR, 360) > 90 && mod(tR, 360) < 270
                        text(obj.ax,tX3(i),tY3(i),tLbl,...
                            'HorizontalAlignment','right''VerticalAlignment','middle',...
                            'Rotation', tR + 180, obj.TickLabelFont{:},'Tag','SSpiralTxt')
                    else
                        text(obj.ax,tX3(i),tY3(i),tLbl,...
                            'HorizontalAlignment','left''VerticalAlignment','middle',...
                            'Rotation', tR, obj.TickLabelFont{:},'Tag','SSpiralTxt')
                    end

                end
            end
            axis tight
            obj.ax.XLim = obj.ax.XLim + [-1,1].*max(obj.ax.XLim).*.1;
            obj.ax.YLim = obj.ax.YLim + [-1,1].*max(obj.ax.YLim).*.1;
        end
% =========================================================================
        function ticks = getTick(~, XLim, N)
            tXS = abs(diff(XLim)) / N;
            tXN = ceil(log(tXS) / log(10));
            tXS = round(round(tXS / 10^(tXN-2)) / 5) * 5 * 10^(tXN-2);
            tON = ceil(log(abs(XLim(1))) / log(10));
            tON(isinf(tON)) = 1;
            tOS = round(round(XLim(1) / 10^(tON-2)) / 5) * 5 * 10^(tON-2);
            ticks = tOS:tXS:XLim(2);
        end
% =========================================================================
        function barHdl = bar(obj, Y, varargin)
            arginListBar = {'FaceColor''EdgeColor''FaceAlpha''EdgeAlpha',...
                            'LineWidth''BarWidth''CData'};
            barProp.FaceColor = [];
            barProp.EdgeColor = [0,0,0];
            barProp.FaceAlpha = 1;
            barProp.EdgeAlpha = 1;
            barProp.LineWidth = .5;
            barProp.BarWidth = 1;
            if isempty(varargin) || ischar(varargin{1})
                if size(Y,1) == 1
                    barProp.XData = 1:size(Y,2);
                    barProp.YData = Y;
                else
                    barProp.XData = 1:size(Y,1);
                    barProp.YData = Y.';
                end
            else
                barProp.XData = Y(:).';
                barProp.YData = varargin{1}; varargin(1) = [];
                if size(barProp.XData,1) == 1
                else
                    barProp.YData = barProp.YData.';
                end
            end

            for i = 1:2:(length(varargin)-1)
                tid = ismember(arginListBar, varargin{i});
                if any(tid)
                    barProp.(arginListBar{tid}) = varargin{i+1};
                end
            end
            % if isempty(barProp.FaceColor)
            %     if size(barProp.YData,1) > 1
            %         barProp.FaceColor = obj.ColorOrder(mod(obj.ColorOrderIndex + (0:size(areaProp.YData,1)-1) -1, size(obj.ColorOrder,1)) + 1, :);
            %         obj.ColorOrderIndex = obj.ColorOrderIndex + size(areaProp.YData,1);
            %     else
            %         barProp.FaceColor = obj.ColorOrder(mod(obj.ColorOrderIndex-1, size(obj.ColorOrder,1)) + 1, :);
            %         obj.ColorOrderIndex = obj.ColorOrderIndex + 1;
            %     end
            % end
            if isempty(barProp.FaceColor)
                barProp.FaceColor = obj.ColorOrder(mod(obj.ColorOrderIndex + (0:size(barProp.YData,1)-1-1size(obj.ColorOrder,1)) + 1, :);
                obj.ColorOrderIndex = obj.ColorOrderIndex + size(barProp.YData,1);
            end
            bX1 = linspace(-.5.*barProp.BarWidth, .5.*barProp.BarWidth, 50);
            CY1 = zeros(1,size(barProp.YData,2));
            CY2 = zeros(1,size(barProp.YData,2));
            % if size(barProp.YData,1) > 1
                for i = 1:size(barProp.YData,1)
                    tX = repmat(barProp.XData(:), [1,100]) + repmat([bX1, bX1(end:-1:1)], [size(barProp.YData,2),1]);
                    tY = [repmat(barProp.YData(i,:).', [1,50]), zeros(size(barProp.YData,2),50)] + repmat(CY1(:).*(barProp.YData(i,:).'>0) + CY2(:).*(barProp.YData(i,:).'<0), [1,100]);
                    CY1 = CY1 + barProp.YData(i,:).*(barProp.YData(i,:)>0);
                    CY2 = CY2 + barProp.YData(i,:).*(barProp.YData(i,:)<0);
                    tT = (tX-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
                    tR = (tY-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((tT-obj.TLim(1))./180.*pi);
                    tT = tT.'; tR = tR.';
                    barHdl(i,:) = fill(obj.ax, cos(tT./180.*pi).*tR,sin(tT./180.*pi).*tR, barProp.FaceColor(i,:), 'EdgeColor',barProp.EdgeColor,...
                        'LineWidth',barProp.LineWidth, 'FaceAlpha',barProp.FaceAlpha, 'EdgeAlpha',barProp.EdgeAlpha);
                    for j = 2:length(barHdl)
                        barHdl(i,j).Annotation.LegendInformation.IconDisplayStyle='off';
                    end
                end
            % else
            %     % for i = 1:size(barProp.YData,2)
            %     %     tX = barProp.XData(i) + [-.5.*barProp.BarWidth, bX, .5.*barProp.BarWidth];
            %     %     tY = [barProp.YData(i), zeros(1,50), barProp.YData(i)];
            %     %     tT = (tX-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
            %     %     tR = (tY-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((tT-obj.TLim(1))./180.*pi);
            %     %     barHdl(i) = fill(obj.ax, cos(tT/180*pi).*tR,sin(tT/180*pi).*tR, barProp.FaceColor, 'EdgeColor',barProp.EdgeColor,...
            %     %         'LineWidth',barProp.LineWidth, 'FaceAlpha',barProp.FaceAlpha, 'EdgeAlpha',barProp.EdgeAlpha);
            %     % end
            %     tX = repmat(barProp.XData(:), [1,100]) + repmat([bX1, bX1(end:-1:1)], [size(barProp.YData,2),1]);
            %     tY = [repmat(barProp.YData(:), [1,50]), zeros(size(barProp.YData,2),50)];
            %     tT = (tX-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
            %     tR = (tY-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((tT-obj.TLim(1))./180.*pi);
            %     tT = tT.'; tR = tR.';
            %     barHdl = fill(obj.ax, cos(tT./180.*pi).*tR,sin(tT./180.*pi).*tR, barProp.FaceColor, 'EdgeColor',barProp.EdgeColor,...
            %         'LineWidth',barProp.LineWidth, 'FaceAlpha',barProp.FaceAlpha, 'EdgeAlpha',barProp.EdgeAlpha);
            %     for i = 2:length(barHdl)
            %         barHdl(i).Annotation.LegendInformation.IconDisplayStyle='off';
            %     end
            % end
        end

        function areaHdl = area(obj, X, Y, varargin)
            arginListBar = {'FaceColor''EdgeColor''FaceAlpha''EdgeAlpha',...
                            'LineWidth''BarWidth''CData'};
            areaProp.FaceColor = [];
            areaProp.EdgeColor = 'none';
            areaProp.FaceAlpha = .5;
            areaProp.EdgeAlpha = 1;
            areaProp.LineWidth = .5;
            areaProp.XData = X(:).';
            areaProp.YData = Y.';
            for i = 1:2:(length(varargin)-1)
                tid = ismember(arginListBar, varargin{i});
                if any(tid)
                    areaProp.(arginListBar{tid}) = varargin{i+1};
                end
            end
            if isempty(areaProp.FaceColor)
                areaProp.FaceColor = obj.ColorOrder(mod(obj.ColorOrderIndex + (0:size(areaProp.YData,1)-1-1size(obj.ColorOrder,1)) + 1, :);
                obj.ColorOrderIndex = obj.ColorOrderIndex + size(areaProp.YData,1);
            end
            bX1 = linspace(areaProp.XData(1), areaProp.XData(end), length(areaProp.XData)*10);
            CY1 = zeros(1length(areaProp.XData)*10);
            CY2 = zeros(1length(areaProp.XData)*10);
            for i = 1:size(areaProp.YData,1)
                tX = [bX1, bX1(end:-1:1)];
                tYq = interp1(areaProp.XData, areaProp.YData(i,:), bX1);
                tY = [tYq, zeros(1,length(bX1))] + [CY1,CY1(end:-1:1)].*([tYq,tYq(end:-1:1)]>0) + [CY2,CY2(end:-1:1)].*([tYq,tYq(end:-1:1)]<0);%repmat(CY1.*(tYq>0) + CY2.*(tYq<0), [1,2]);
                CY1 = CY1 + tYq.*(tYq>0);
                CY2 = CY2 + tYq.*(tYq<0);
                tT = (tX-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
                tR = (tY-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((tT-obj.TLim(1))./180.*pi);
                areaHdl(i) = fill(obj.ax, cos(tT./180.*pi).*tR,sin(tT./180.*pi).*tR, areaProp.FaceColor(i,:), 'EdgeColor',areaProp.EdgeColor,...
                        'LineWidth',areaProp.LineWidth, 'FaceAlpha',areaProp.FaceAlpha, 'EdgeAlpha',areaProp.EdgeAlpha);
            end
        end
        function plotHdl = plot(obj, X, Y, varargin)
            if any(size(X) == 1)
                tN = length(X);
            else
                tN = size(X,1);
            end
            tTq = linspace(1, tN, (tN-1)*10+1);
            tX = interp1(1:tN, X, tTq);
            tY = interp1(1:tN, Y, tTq);
            tT = (tX-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
            tR = (tY-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((tT-obj.TLim(1))./180.*pi);
            plotHdl = plot(obj.ax, cos(tT./180.*pi).*tR,sin(tT./180.*pi).*tR, 'MarkerIndices',1:10:(tN-1)*10+1, varargin{:});
        end
        function lineHdl = line(obj, X, Y, varargin)
            if any(size(X) == 1)
                tN = length(X);
            else
                tN = size(X,1);
            end
            for i = 1:size(Y,2)
                tNq = ceil((max(max(X(:,i)))-min(min(X(:,i))))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)))/2+10;
                tTq = linspace(1, tN, tNq);
                tX = interp1(1:tN, X(:,i), tTq);
                tY = interp1(1:tN, Y(:,i), tTq);
                tT = (tX-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
                tR = (tY-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((tT-obj.TLim(1))./180.*pi);
                lineHdl(i) = plot(obj.ax, cos(tT./180.*pi).*tR,sin(tT./180.*pi).*tR, varargin{:},'Marker','none');
            end
        end
        function scatterHdl = scatter(obj, X, Y, varargin)
            tT = (X-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)).*2.*((diff(obj.TLim)>0)-.5) + obj.TLim(1);
            tR = (Y-obj.YLim(1))./abs(diff(obj.YLim)).*(obj.Height.*2.*pi) + 3.77 + 1.4.*abs((tT-obj.TLim(1))./180.*pi);
            scatterHdl = scatter(obj.ax, cos(tT./180.*pi).*tR,sin(tT./180.*pi).*tR, varargin{:});
        end
        function regionHdl = xregion(obj, Lim, varargin)
            Lim = (Lim-obj.XLim(1))./abs(diff(obj.XLim)).*abs(diff(obj.TLim)) + obj.TLim(1);
            tT  = linspace(Lim(1), Lim(2), ceil(abs(diff(Lim)))+10)./180.*pi;
            tX1 = (3.77 + 1.4.*abs(tT-obj.TLim(1)./180.*pi)).*cos(tT);
            tY1 = (3.77 + 1.4.*abs(tT-obj.TLim(1)./180.*pi)).*sin(tT);
            tL  = vecnorm([tX1;tY1]);
            tX2 = tX1./tL.*(tL + obj.Height.*2.*pi);
            tY2 = tY1./tL.*(tL + obj.Height.*2.*pi);
            tX  = [tX1, tX2(end:-1:1)];
            tY  = [tY1, tY2(end:-1:1)];
            regionHdl = fill(obj.ax, tX,tY, [114,146,184]./255'EdgeColor','none''FaceAlpha',.5, varargin{:});
        end
        function regionHdl = yregion(obj, Lim, varargin)
            tT  = linspace(obj.TLim(1), obj.TLim(2), ceil(abs(diff(obj.TLim)))+10)./180.*pi;
            tX1 = (3.77 + 1.4.*abs(tT-obj.TLim(1)./180.*pi)).*cos(tT);
            tY1 = (3.77 + 1.4.*abs(tT-obj.TLim(1)./180.*pi)).*sin(tT);
            tL  = vecnorm([tX1;tY1]);
            tX2 = tX1./tL.*(tL + obj.Height.*2.*pi.*(Lim(1)-obj.YLim(1))./abs(diff(obj.YLim)));
            tY2 = tY1./tL.*(tL + obj.Height.*2.*pi.*(Lim(1)-obj.YLim(1))./abs(diff(obj.YLim)));
            tX3 = tX1./tL.*(tL + obj.Height.*2.*pi.*(Lim(2)-obj.YLim(1))./abs(diff(obj.YLim)));
            tY3 = tY1./tL.*(tL + obj.Height.*2.*pi.*(Lim(2)-obj.YLim(1))./abs(diff(obj.YLim)));
            tX  = [tX2, tX3(end:-1:1)];
            tY  = [tY2, tY3(end:-1:1)];
            regionHdl = fill(obj.ax, tX,tY, [114,146,184]./255'EdgeColor','none''FaceAlpha',.5, varargin{:});
        end
    end
end


以上已经是完整代码,未经允许本代码请勿作商业用途,引用的话可以引用我file exchange上的链接,可使用如下格式:

  • Zhaoxu Liu / slandarer (2024). Spiral diagram (https://www.mathworks.com/matlabcentral/fileexchange/164966-spiral-diagram), MATLAB Central File Exchange. Retrieved May 1, 2024.

若转载请保留以上file exchange链接及本文链接!!!!!

该工具可通过上述fileexchange链接获取,或者通过以下gitee仓库下载:



slandarer随笔
slandarer个人公众号,目前主要更新MATLAB相关内容。
 最新文章