MATLAB-风玫瑰图

用MATLAB绘制风玫瑰图,其实有很多函数可以绘制标准的风玫瑰图,可本人做大气环境的,希望添加污染物的变量信息,基于这个博主的帖子,更改了一个变量,并进行微调 MATLAB|风玫瑰图 - 好玩的MATLAB - 博客园

最终成品如图

成品展示

在图片绘制过程中,遇到了填色颜色与colorbar不对应的情况,以及本人在批量出图时需要固定风速的范围,故针对函数进行如下修改:

函数修改部分

函数调用参考:

figure

    title(‘Hefei’,'FontSize',18,'FontName','Times New Roman')

    ax = gca;ax.TitleHorizontalAlignment = 'left';

    w = WindRosePlot(data);

    w.YLabel='Frequency of WD (%)';

    w.LegendTitle='Avg WS';

    w.LegendFontName='Times new Roman';

    w.LegendFontSize=14;

    w.ColorMaps=MPL_hot_r;

%    w.ColorMaps=[0 1 1; 0.2 0.6 0.2];

    w.ColorMapsTitle='MDA8 O_3';

    w.ColorMapsFontSize=14;

    w.AxisTickFontName='Times new Roman';

    w.plot();

函数修改版本:

classdef WindRosePlot

    % ------------------------------------------------

    %  @Author:  好玩的 MATLAB.

    %  @E-mail:  2377389590@qq.com

    %  @WeChat:  idmatlab

    %  @Date:    Oct 30, 2023.

    %  @Version: Matlab R2022b.

    %  % #Respect the fruits of labor. Please note the tweet link and official account name when reprinting. Commercial use is strictly prohibited.

    %  Example:

    %    windDirections = [0.0, 22.5, 45.0, 67.5, 90.0, 112.5, 135.0, 157.5, 180.0, 202.5, 225.0, 247.5, 270.0, 292.5, 315.0, 337.5]';

    %    windFrequency = [10.2, 4, 4, 3.0, 4.0, 3.0, 4.0, 4.0, 7.0, 6.0, 3, 2, 2, 1.0, 3, 5]';

    %    maxWindSpeed = [15, 12, 10, 5, 5, 5,10, 12, 13, 15, 12,5, 5, 10, 12,  15]';

    %    avgWindSpeed = [2.8, 2.0, 1.5, 1.2, 1.4, 1.3, 1.45, 2.00, 2.80, 2.80, 1.50, 1.00, 1.0, 1.0, 1.8, 2.0]';

    %    % dataT = table(windDirections, windFrequency, maxWindSpeed, avgWindSpeed, 'VariableNames', {'风向', '频率', '最大风速', '平均风速'});

    %    data=[windDirections,windFrequency,maxWindSpeed,avgWindSpeed];

    %    w=WindRosePlot(data);

    %    w.plot();

    %-------------------------------------------------

    properties

        fig

        %

        WindDirections;    %风向

        WindFrequency;      %刮风频率

        MaxWindSpeed;      %最大风速

        AvgWindSpeed;      %平均风速

        %

        RGrid='on';        %显示主 r 轴网格线

        ThetaGrid='on';    %显示主 Theta 轴网格线

        MinorRGrid='on';    %显示次 r 轴网格线

        MinorThetaGrid='on';%显示次 Theta 轴网格线

        %

        YLabel='风向频率(%)';

        %  R主网格样式

        RGridLineStyle='-';

        RGridColor=[0,0,0];

        RGridAlpha=1;

        RGridLineWidth=0.5;

        % Theta 主网格样式

        ThetaGridLineStyle='-';

        ThetaGridColor=[0.8 0.8 0.8];

        ThetaGridAlpha=1;

        ThetaGridLineWidth=1.2;

        % R次网格样式

        MinorRGridLineStyle=':';

        MinorRGridColor=[0.55 0.55 0.55];

        MinorRGridAlpha=1;

        MinorRGridLineWidth=0.8;

        % Theta 次网格样式

        MinorThetaGridLineStyle='-.'

        MinorThetaGridColor=[0.55 0.55 0.55];

        MinorThetaGridAlpha=1;

        MinorThetaGridLineWidth=1.2;

        % 刻度样式

        AxisColor=[0,0,0];

        AxisLineWidth=1.5;

        AxisMainTickDir='in';

        AxisMinorTickDir='in';

        AxisTickLength=0.04;

        AxisTickFontSize=12;

        AxisTickFontWeight='normal'%'normal'|'bold'

        AxisTickFontName='Times new Roman';

        AxisFaceAlpha=0.5;

        AxisBackgroundColor=[1,1,1];

        % 颜色条

        ColorMaps=[0.0078, 0.0941, 0.7333; 0.9725, 0.0039, 0.5216];

        ColorMapsTitle='最大风速(m/s)';

        ColorMapsFontName='Times new Roman';

        ColorMapsFontSize=12;

        ColorMapsFontAngle='normal';%'normal' | 'italic'。

        ColorMapsFontWeight='normal'; %'normal'|'bold'

        %legend 图列

        LegendTitle='平均风速(m/s)';

        LegendBackgroundColor=[1,1,1]*.95;

        LegendEdgeColor='none';

        LegendLineWidth=1;

        LegendFontName='Times new Roman';

        LegendFontAngle='italic';%'normal' | 'italic'。

        LegendFontSize=12;

        LegendFontWeight='normal';

        LegendRotation=0;

    end

    methods

        function  obj =WindRosePlot(data)

            obj.fig=gcf;

            obj.fig.Color=[1,1,1];

            obj.WindDirections = data(:,1);

            obj.WindFrequency = data(:,2);

            obj.MaxWindSpeed = data(:,3);

            obj.AvgWindSpeed =data(:,4);

            %-------------------------

            obj.RGrid='on';        obj.RGridLineStyle='-';          obj.RGridColor=[0,0,0];                  obj.RGridAlpha=1;        obj.RGridLineWidth=0.5;

            obj.ThetaGrid='on';    obj.ThetaGridLineStyle='-';      obj.ThetaGridColor=[0.8 0.8 0.8];        obj.ThetaGridAlpha=1;    obj.ThetaGridLineWidth=1.2;

            obj.MinorRGrid='on';    obj.MinorRGridLineStyle=':';    obj.MinorRGridColor=[0.55 0.55 0.55];    obj.MinorRGridAlpha=1;    obj.MinorRGridLineWidth=0.8;

            obj.MinorThetaGrid='on';obj.MinorThetaGridLineStyle='-.';obj.MinorThetaGridColor=[0.55 0.55 0.55];obj.MinorThetaGridAlpha=1;obj.MinorThetaGridLineWidth=1.2;

            obj.ColorMaps = [0.0078, 0.0941, 0.7333; 0.9725, 0.0039, 0.5216];

        end

        function plot(obj)

            maxRadius = ceil(max(obj.WindFrequency));

            minRadius = round(maxRadius / 10);

            dfT=unique(diff(obj.WindDirections));

            allTheta = 0:0.01:360;

            ax = gca;

            hold on; box off; grid off; axis equal;

            ax.YLim = [-maxRadius, maxRadius];

            ax.YMinorTick = 'on';

            ax.XColor = 'none';

            ax.XDir = 'normal';

            ax.TickDir = 'out';

            ax.LineWidth = obj.AxisLineWidth;

            ax.YColor=obj.AxisColor;

            majorTicksY = ax.YTick;

            minorTicksY = (majorTicksY(1:end-1) + majorTicksY(2:end)) / 2;

            diffTicks = unique(diff(majorTicksY));

            maxRadius=max(ax.YTick)+diffTicks/2;

            ax.YLim = [-maxRadius, maxRadius];%重新设定

            ax.YAxis.MinorTickValues = [minorTicksY(1)-diffTicks, minorTicksY, minorTicksY(end)+diffTicks];

            ax.YTickLabel = arrayfun(@(y) sprintf('%d', abs(y)), majorTicksY, 'UniformOutput', false);

            ax.YLabel.String=obj.YLabel;

            ax.YLabel.FontName='Times New Roman';

            ax.YLabel.FontSize=14;

            % =============绘制主要R Theta的极坐标网格线===============================

            %  # RGrid

            majorRadius = majorTicksY(majorTicksY > minRadius);

            if strcmpi(obj.RGrid,'on')

                for i = 1:length(majorRadius)

                    [xMajor, yMajor] = pol2cart(deg2rad(allTheta), majorRadius(i));

                    plot(xMajor, yMajor,'LineStyle',obj.RGridLineStyle,'Color', [obj.RGridColor obj.RGridAlpha], 'LineWidth',obj.RGridLineWidth);

                end

            elseif strcmpi(obj.RGrid,'off')

            end

            %  # ThetaGrid

            majorTheta = obj.WindDirections;

            fullRadius = linspace(minRadius, maxRadius, 1000);

            if strcmpi(obj.ThetaGrid,'on')

                for i = 1:length(majorTheta)

                    [xMajorT, yMajorT] = pol2cart(deg2rad(majorTheta(i)), fullRadius);

                    plot(xMajorT, yMajorT, 'LineStyle',obj.ThetaGridLineStyle, 'Color', [obj.ThetaGridColor obj.ThetaGridAlpha], 'LineWidth', obj.ThetaGridLineWidth);

                end

            elseif  strcmpi(obj.ThetaGrid,'off')

            end

            % 绘制次要R Theta的极坐标网格线

            %  # MinorRGrid

            if strcmpi(obj.MinorRGrid,'on')

                minorRadius = minorTicksY(minorTicksY > minRadius);

                for i = 1:length(minorRadius)

                    [xMinor, yMinor] = pol2cart(deg2rad(allTheta), minorRadius(i));

                    plot(xMinor, yMinor, 'LineStyle',obj.MinorRGridLineStyle,'Color', [obj.MinorRGridColor obj.MinorRGridAlpha], 'LineWidth',obj.MinorRGridLineWidth);

                end

            elseif strcmpi(obj.MinorRGrid,'off')

            end

            %  # MinorThetaGrid

            minorTheta=obj.WindDirections+dfT/2;

            if strcmpi(obj.MinorThetaGrid,'on')

                for i = 1:length(minorTheta)

                    [xMinorT, yMinorT] = pol2cart(deg2rad(minorTheta(i)), fullRadius);

                    plot(xMinorT, yMinorT, 'LineStyle',obj.MinorThetaGridLineStyle, 'Color', [obj.MinorThetaGridColor obj.MinorThetaGridAlpha], 'LineWidth', obj.MinorThetaGridLineWidth);

                end

            elseif strcmpi(obj.MinorThetaGrid,'off')

            end

            % ===================绘制刻度===============================

            % 绘制最外层的极坐标线

            [xOuter, yOuter] = pol2cart(deg2rad(allTheta), max(ax.YTick)+diffTicks/2);

            plot(xOuter, yOuter, '-', 'Color',obj.AxisColor, 'LineWidth', obj.AxisLineWidth);

            fill(xOuter, yOuter,obj.AxisBackgroundColor,'EdgeColor','none','FaceAlpha',obj.AxisFaceAlpha)

            % #主刻度

            if obj.AxisTickLength > 1 || obj.AxisTickLength <= 0

                error('TickLength must be less than 1 and greater than 0.');

            end

            if strcmpi(obj.AxisMainTickDir,'in')

                tickRadius = [maxRadius*(1-obj.AxisTickLength), maxRadius];

            elseif strcmpi(obj.AxisMainTickDir,'out')

                tickRadius = [ maxRadius,maxRadius*(1+obj.AxisTickLength)];

            elseif strcmpi(obj.AxisMainTickDir,'both')

                tickRadius = [maxRadius*(1-obj.AxisTickLength) maxRadius*(1+obj.AxisTickLength)];

            else

                error('Invalid value for mainTickDir. It should be "in", "out", or "both".');

            end

            mainTickTheta= obj.WindDirections+dfT;

            for i = 1:length(mainTickTheta)

                [xMainTick, yMainTick] = pol2cart(deg2rad(mainTickTheta(i)), tickRadius);

                plot(xMainTick, yMainTick, '-', 'Color', obj.AxisColor, 'LineWidth', obj.AxisLineWidth);

            end

            disp(char([20844 20247 21495 58 22909 29609 30340 77 97 116 108 97 98]))

            % #次刻度

            if strcmpi(obj.AxisMinorTickDir,'in')

                tickRadiusMinor = [maxRadius*(1-obj.AxisTickLength/2), maxRadius];

            elseif strcmpi(obj.AxisMinorTickDir,'out')

                tickRadiusMinor = [ maxRadius maxRadius*(1+obj.AxisTickLength/2)];

            elseif strcmpi(obj.AxisMinorTickDir,'both')

                tickRadiusMinor = [maxRadius*(1-obj.AxisTickLength/2), maxRadius*(1+obj.AxisTickLength/2)];

            else

                error('Invalid value for mainTickDir. It should be "in", "out", or "both".');

            end

            minorTickTheta=obj.WindDirections+dfT/2;

            for i = 1:length(minorTickTheta)

                [xMinorTick, yMinorTick] = pol2cart(deg2rad(minorTickTheta(i)), tickRadiusMinor);

                plot(xMinorTick, yMinorTick, '-', 'Color', obj.AxisColor, 'LineWidth', obj.AxisLineWidth*0.8);

            end

            % ==========添加主刻度外的标签===========================

            labelDist = maxRadius *(1+ 0.094); % 设定标签距离为最大半径(1+ 0.094),可以根据需要进行调整

            for i = 1:length(majorTheta)

                adjustedAngle = majorTheta(i); % 从正北方开始,并且顺时针增加 % 从正北方开始,并且顺时针增加

                angle = mod(adjustedAngle, 360); % 确保角度在0-360之间

                [xLabel, yLabel] = pol2cart(deg2rad(90-adjustedAngle), labelDist);

                labelText = sprintf('%.1f°', angle);

                text(xLabel, yLabel, labelText, 'HorizontalAlignment', 'center', ...

                    'VerticalAlignment', 'middle', ...

                    'FontSize',obj.AxisTickFontSize,'FontWeight',obj.AxisTickFontWeight,'FontName',obj.AxisTickFontName, ...

                    'Color',obj.AxisColor);

            end

            %==================添加数据========================

            adjustedWindDirections = 360-obj.WindDirections;

            [xWind, yWind] = pol2cart(deg2rad(adjustedWindDirections+90), obj.WindFrequency);

            colorMapMajor = obj.makeColorMap(obj.ColorMaps, length(obj.MaxWindSpeed));

%            % 根据风速大小对颜色进行排序

            [~, idx] = sort(obj.MaxWindSpeed, 'Ascend');

%            sortedColorMap = colorMapMajor(idx, :);

%            %对于相同的风速值,使用第一个出现的颜色值为其赋色

%            uniqueSpeeds = unique(obj.MaxWindSpeed, 'stable');

%            for i = 1:length(uniqueSpeeds)

%                currentSpeed = uniqueSpeeds(i);

%                indices = find(obj.MaxWindSpeed == currentSpeed);

%                if length(indices) > 1

%                    sortedColorMap(indices, :) = repmat(sortedColorMap(indices(1), :), length(indices), 1);

%                end

%            end

            maxWind = max(obj.MaxWindSpeed);

%            desiredMaxSize=max(obj.AvgWindSpeed);

%            desiredMinSize=min(obj.AvgWindSpeed);

            desiredMaxSize=1;

            desiredMinSize=3;

            for i = 1:length(obj.WindDirections)

%                color = obj.getColorForSpeed(obj.MaxWindSpeed(i), maxWind , colorMapMajor);

                s = obj.mapToMarkerSize(obj.AvgWindSpeed(i), desiredMaxSize, desiredMinSize);

                plot(xWind(i), yWind(i), 'o', 'LineWidth', 1.2, 'MarkerSize',s,...

                    'MarkerEdgeColor', 'k', 'MarkerFaceColor', colorMapMajor(find(idx==i),:));

            end

            % ================添加 colorbar======================================

            colorMapMinor = obj.makeColorMap(obj.ColorMaps, length(obj.MaxWindSpeed)/2);

            colormap(colorMapMinor);

            cBar = colorbar;

            cBar.Position = [.88 .1 .04 .36];

            cBar.LineWidth = 1.2;

            cBar.TickLength = 0.025;

            cBar.Ticks = linspace(floor(min(obj.MaxWindSpeed)),ceil(max(obj.MaxWindSpeed)),length(obj.MaxWindSpeed)/2+1);

            tickLabels = arrayfun(@(x) sprintf('%.1f', x), cBar.Ticks, 'UniformOutput', false);

            cBar.TickLabels = tickLabels;

            cBar.TickDirection = 'both';

            caxis([floor(min(obj.MaxWindSpeed)),ceil(max(obj.MaxWindSpeed))]);

            title(cBar, obj.ColorMapsTitle);

            cBar.FontName= obj.ColorMapsFontName;

            cBar.FontSize=obj.ColorMapsFontSize;

            cBar.FontAngle= obj.ColorMapsFontAngle;

            cBar.FontWeight=obj.ColorMapsFontWeight; %'normal'|'bold'

            % ===============添加 Legend=======================================

            legAx=axes(obj.fig,'Position',[.86 0.55 .1 .36],'Color',[1,1,1],'Box','on');

            title(legAx,obj.LegendTitle,'FontName','Times New Roman','FontSize',14)

            legAx.Color=obj.LegendBackgroundColor;

            legAx.XColor=obj.LegendEdgeColor;legAx.YColor=obj.LegendEdgeColor;

            legAx.XTick=[];legAx.YTick=[];

            legAx.TickLength=[0 0];

            legAx.LineWidth=obj.LegendLineWidth;

            % 定义半径和距离

%            legR=linspace(ceil(min(obj.AvgWindSpeed))-1,ceil(max(obj.AvgWindSpeed)),5);

%            d =ceil(ceil(max(obj.AvgWindSpeed))/2);

            legR=linspace(1,3,5);

            d =ceil(3/2);

            legY = zeros(1, length(legR));

            totalHeight = sum(2.*legR) + d*(length(legR)-1);

            legY(1) = totalHeight/2 - legR(1);

            for i = 2:length(legR)

                legY(i) = legY(i-1) - 2*legR(i-1) - d;

            end

            % 绘制圆形

            hold on;

            for i = 1:length(legR)

                rectangle('Position',[-legR(i), legY(i)-legR(i), 2*legR(i), 2*legR(i)], 'Curvature', [1, 1],'LineWidth',1.5,'FaceColor', 'white');

                text(max(legR) + 0.9, legY(i), sprintf('%.1f', legR(i)), ...

                    "FontName",obj.LegendFontName,"FontSize",obj. LegendFontSize,'FontAngle',obj.LegendFontAngle, ...

                    'FontWeight',obj.LegendFontWeight,'Rotation',obj.LegendRotation);

            end

            axis equal;

            xlim([-max(legR)*1.2 max(legR)*1.2]);

            ylim([(legY(end)-legR(end))*1.1 (legY(1)+legR(1))*1.1]);

            hold off;

        end

    end

    methods(Access=private)

        function color = getColorForSpeed(obj,speed, maxSpeed, colorMap)

            idx = round((speed / maxSpeed) * size(colorMap, 1));

            idx = min(max(idx, 1), size(colorMap, 1)); % 保证idx在正确的范围内

            color = colorMap(idx, :);

        end

        function s = mapToMarkerSize(obj,speed, maxSize, minSize)

            normalized = (speed - minSize)/(maxSize -minSize);

            s = minSize + normalized * (maxSize - minSize);

            s=s*10;

        end

        function cMap=makeColorMap(obj,colorlist,num)

            color.Num= num;

            color.list=colorlist;

            for col=1:size(color.list,2)

                x=1:size(color.list,1);

                xi=linspace(1,size(color.list,1),color.Num);

                color.map(:,col)=interp1(x,color.list(:,col),xi);

            end

            cMap=color.map;

        end

    end

end

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容