MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

这篇具有很好参考价值的文章主要介绍了MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

整了个大活,写了一个能够生成非常精致三元相图的函数,这种图主要用于展示三种变量之间的比例,本期实验绘制效果如下:

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

编写不易,这个工具写的脑壳痛,求多多点赞,依旧先介绍咋使用,工具函数放在最后,同时提供gitee及fileexchange下载链接,若是日后代码更改会在这俩仓库同步更改。


教程部分

1 三元相坐标区域创建

就一行代码就可以创建:

% 初始化三元相图(Init ternary plot)
STA1=STernary();

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


2 set 设置坐标区域最基本属性

set函数可以设置很多坐标区域属性,比如背景颜色Color

% 背景色变为灰色(Set the background color to gray)
set(STA1,'Color',[.9,.9,.9]);

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

比如设置ABC三个轴标签A_Label,B_Label,C_Label的文本:

% 设置标签文本(Set Label string)
set(STA1,'A_Label','String','AAAAA')
set(STA1,'B_Label','String','BBBBB')
set(STA1,'C_Label','String','CCCCC')

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


3 基本绘图

常见的 plot fill scatter contour contourf text 这些绘图函数都可以用,不过需要首字母大写并加个S,继续前面的代码往后写,画个散点图并增添图例:

% 绘制散点图(Draw scatter plot)
A=rand(1,20);
B=rand(1,20);
C=rand(1,20);
STA1.SScatter(A,B,C,40,'filled','CData',[0,0,0]);
legend()

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


4 set 设置其它属性

ABC各个轴、主刻度、次刻度、主网格、次网格、轴标签、刻度标签全部可以由set函数设置,这里仅举A相关的例子,BC轴就把A字母换换就好:

以下两种设置方式等价:

  • set(STA,‘XXX’,‘prop’,…)
  • STA.set(‘XXX’,‘prop’,…)
% 设置A轴颜色和粗细(Set A_Axis's 'Color' and 'LineWidth')
set(STA1,'A_Axis','Color',[0,0,.8],'LineWidth',3)
% 设置A轴主网格颜色和粗细(Set A_Grid's 'Color' and 'LineWidth')
set(STA1,'A_Grid','Color',[0,0,.8],'LineWidth',1.2)
% 设置A轴次网格颜色线形
set(STA1,'A_MinorGrid','Color',[0,0,.8],'LineStyle','-.')
% 设置A轴主刻度颜色
set(STA1,'A_Tick','Color',[0,0,.8])
% 设置A轴次刻度颜色
set(STA1,'A_MinorTick','Color',[0,0,.8])
% 设置A轴刻度标签字体和颜色
set(STA1,'A_TickLabel','Color',[0,0,.8],'FontSize',16)
% 设置A轴标签字体和颜色及位置以及文本内容
set(STA1,'A_Label','Color',[0,0,.8],'FontSize',18,'Position',[.88,.6],'String',{'Ternary plot';'by Slandarer'})

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


5 一些不常设置属性

重新构造一个坐标区域对象叭,不用之前那个灰灰的啦,首先是将标签移动到侧面:

STA2=STernary();

% 将标签移动到侧边(Move the label to the side)
STA2.label2Side();

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

设置主次刻度长度,设置刻度值/网格值/刻度标签文本:

% 设置刻度长度(Set tick length)
STA2.set('TickLenth',[.035,.02])

% 设置刻度值/网格值/刻度标签
% 'GridValues'/'TickValues'
% 'MinorGridValues'/'MinorTickValues'
% 'A_TickLabelStr'/'B_TickLabelStr'/'C_TickLabelStr'
STA2.set('MinorGridValues',5:5:100)
STA2.set('MinorTickValues',2.5:2.5:100)
STA2.set('A_TickLabelStr',{'20%','40%','60%','80%','100%'})

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


6 折线图基础绘图及绘图解读

折线图使用SPlot函数绘制:

% 初始化三元相图(Init ternary plot)
STA=STernary();

% 绘制折线图及散点(Draw lines and scatter)
STA.SPlot([2,2],[3,0],[5,8],'LineWidth',4,'Color',[.8,0,0]);
STA.SPlot([2,7],[3,3],[5,0],'LineWidth',4,'Color',[0,.8,0]);
STA.SPlot([2,0],[3,5],[5,5],'LineWidth',4,'Color',[0,0,.8]);
STA.SScatter(2,3,5,180,'filled','CData',[1,1,1],'MarkerEdgeColor',[0,0,0],'LineWidth',2);

% 绘制文本(Draw text)
STA.SText(2+1,3,5,'(20%,30%,50%)','FontSize',16,'FontName','Cambria')

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

由图所示圆点比例为2:3:5那么平行于A轴网格的线会与A轴交在20%处,相应平行于B轴网格的线与B轴交在30%处。。。。。。同时实际上三条直线的长度也是呈2:3:5的比例的。


7 气泡图绘制

非常简单就几行代码:

% 初始化三元相图(Init ternary plot)
STA=STernary();

% 随机构造数据(Randomly generated data)
A=rand(1,50);
B=rand(1,50);
C=rand(1,50);
sz=rand(1,50);

% 绘制气泡图(Draw bubble chart)
STA.SBubblechart(A,B,C,sz,'CData',A);

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

想改配色直接colormap即可:

colormap(bone)

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


8 等高线图与填充等高线图

绘图第四个参数是网格划分点数,若是填[]即为默认值分为90段计算核密度,正常画等高线图会填满整个三角:

% 初始化三元相图(Init ternary plot)
STA=STernary();

% 随机构造数据(Randomly generated data)
A=rand(1,30);
B=rand(1,30);
C=rand(1,30);

STA.SContourf(A,B,C,[],15,'LineWidth',1);

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

咋低于一定值不画呢,可以获取绘图的高度返回值Z,自定义要画等高线的高度:

% 获取核密度范围并等分(Obtain the range of ksdensity and divide it equally)
[~,Z]=STA.SContourf(A,B,C,[],15,'Visible','off');
levels=linspace(.5,max(max(Z)),15);

% 依据等值线绘制等高线及等高线填充(Draw contour and contourf by levels)
CfHdl=STA.SContourf(A,B,C,[],levels,'LineWidth',1);

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

多个绘图绘制图例可以直接legend(),但这里我们有一个被隐藏的contourf,建议直接把想要画在图例上的图形句柄放在一个矩阵里:

  • legend([A,B,C],{‘A’,‘B’,‘C’})
% 获取核密度范围并等分(Obtain the range of ksdensity and divide it equally)
[~,Z]=STA.SContourf(A,B,C,[],15,'Visible','off');
levels=linspace(.5,max(max(Z)),15);

% 依据等值线绘制等高线及等高线填充(Draw contour and contourf by levels)
CfHdl=STA.SContourf(A,B,C,[],levels,'LineWidth',1);
CHdl=STA.SContour(A,B,C,[],levels,'LineWidth',1,'EdgeColor',[0,0,0]);
SHdl=STA.SScatter(A,B,C,40,'filled','CData',[0,0,0]);

% 绘制图例(Draw legend)
legend([CfHdl,CHdl,SHdl],{'contourf','contour','scatter'},'FontSize',14,'FontName','Cambria')

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

改个颜色(这就是封面图):

colormap(turbo)

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


9 变量范围及凸包

变量应该是非负的,建议自己先处理好数据,当然懒得写函数可以使用该工具自带的归一化工具:

  • ABC=STA.SNorm(ABC)

可以将每一列分别映射到0-1,每一列最小值映射到0,最大值映射到1.

  • ABC=STA.SNormByLim(ABC,[Amin,Amax,Bmin,Bmax,Cmin,Cmax])

该函数可以预先设置变量范围比如你的数据是0-50范围但是这组数据最大值就是45,那么SNorm函数会把45映射到1,但是SNormByLim函数就能把45映射到0.9。

变量范围映射并绘制散点图

% 初始化三元相图(Init ternary plot)
STA=STernary();

% 随机构造数据(Randomly generated data)
Pnt1=mvnrnd([10,30,10],[15 0 0;0 20 0;0 0 12],80);
Pnt2=mvnrnd([30,10,15],[25 0 0;0 15 0;0 0 40],80);
Pnt3=mvnrnd([25,10,35],[35 0 0;0 20 0;0 0 30],80);

% 数据归一化(Normalization)
Pnt1=STA.SNormByLim(Pnt1,[-5,50,-5,50,-5,50]);
Pnt2=STA.SNormByLim(Pnt2,[-5,50,-5,50,-5,50]);
Pnt3=STA.SNormByLim(Pnt3,[-5,50,-5,50,-5,50]);

% 绘制散点图(Draw scatter)
propCell={80,'filled','LineWidth',1,'MarkerEdgeColor',[1 1 1]*.3,'MarkerFaceColor'};
STA.SScatter(Pnt1(:,1),Pnt1(:,2),Pnt1(:,3),propCell{:},[0.4,0.76,0.65]);
STA.SScatter(Pnt2(:,1),Pnt2(:,2),Pnt2(:,3),propCell{:},[1,0.55,0.38]);
STA.SScatter(Pnt3(:,1),Pnt3(:,2),Pnt3(:,3),propCell{:},[0.55,0.63,0.8]);

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)

凸包绘制本来想让大家用被注释掉的写法,想了想还是算了,注释掉的写法依旧能用,但我将其内置了:

% 已废弃写法(Obsolete method)
% % 计算凸包(Get convhull)
% [X1,Y1]=STA.ternData(Pnt1(:,1),Pnt1(:,2),Pnt1(:,3));
% [X2,Y2]=STA.ternData(Pnt2(:,1),Pnt2(:,2),Pnt2(:,3));
% [X3,Y3]=STA.ternData(Pnt3(:,1),Pnt3(:,2),Pnt3(:,3));
% [ind1,~]=convhull([X1,Y1]);
% [ind2,~]=convhull([X2,Y2]);
% [ind3,~]=convhull([X3,Y3]);
% 
% % 绘制凸包(Draw convhull)
% STA.SFill(Pnt1(ind1,1),Pnt1(ind1,2),Pnt1(ind1,3),[0.4,0.76,0.65],'FaceAlpha',.2,'LineWidth',2,'EdgeColor',[0.4,0.76,0.65]./2);
% STA.SFill(Pnt2(ind2,1),Pnt2(ind2,2),Pnt2(ind2,3),[1,0.55,0.38],'FaceAlpha',.2,'LineWidth',2,'EdgeColor',[1,0.55,0.38]./2);
% STA.SFill(Pnt3(ind3,1),Pnt3(ind3,2),Pnt3(ind3,3),[0.55,0.63,0.8],'FaceAlpha',.2,'LineWidth',2,'EdgeColor',[0.55,0.63,0.8]./2);

% 绘制凸包(Draw convhull)
STA.SConvhull(Pnt1(:,1),Pnt1(:,2),Pnt1(:,3),[0.4,0.76,0.65],'FaceAlpha',.2,'LineWidth',2,'EdgeColor',[0.4,0.76,0.65]./2);
STA.SConvhull(Pnt2(:,1),Pnt2(:,2),Pnt2(:,3),[1,0.55,0.38],'FaceAlpha',.2,'LineWidth',2,'EdgeColor',[1,0.55,0.38]./2);
STA.SConvhull(Pnt3(:,1),Pnt3(:,2),Pnt3(:,3),[0.55,0.63,0.8],'FaceAlpha',.2,'LineWidth',2,'EdgeColor',[0.55,0.63,0.8]./2);

% 绘制图例(Draw legend)
legend({'Data1','Data2','Data3','convex1','convex2','convex3'},'FontSize',14,'FontName','Cambria')

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


10 利用nan同时绘制多条折线

没错我也考虑了减少循环的一些措施,工具函数支持适当加入nan将折线断开以同时绘制多条折线:

% 初始化三元相图(Init ternary plot)
STA=STernary();


A=rand(1,20);
B=rand(1,20);
C=rand(1,20);

A=[A;A*0+mean(A);A.*nan];
B=[B;B*0+mean(B);B.*nan];
C=[C;C*0+mean(C);C.*nan];
% 绘制折线图(Draw Line)
STA.SScatter(A,B,C,40,'filled','CData',[0,0,0]);

% 绘制散点图(Draw scatter plot)
STA.SPlot(A(:),B(:),C(:),'LineWidth',1,'Color',[0,0,0]);

MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)


工具函数完整代码

classdef STernary < handle
% Copyright (c) 2023, Zhaoxu Liu / slandarer
% =========================================================================
% @author : slandarer
% gzh  : slandarer随笔
% -------------------------------------------------------------------------
% Zhaoxu Liu / slandarer (2023). ternary 
% (https://www.mathworks.com/matlabcentral/fileexchange/127958-ternary), 
% MATLAB Central File Exchange. 检索来源 2023/4/18.
    properties
        ax % 三元相图所在坐标区域
        BkgHdl,LabelSep=.001;Color=[1,1,1];
        TriLHdl;TriRHdl
        TickLenth=[.02,.01];
        TickValues=20:20:100;
        GridValues=20:20:100;
        MinorTickValues=5:5:100;
        MinorGridValues=10:10:90;
        A_Axis,B_Axis,C_Axis;
        A_Grid,B_Grid,C_Grid;
        A_Tick,B_Tick,C_Tick;
        A_Label,B_Label;C_Label;
        A_MinorGrid,B_MinorGrid,C_MinorGrid;
        A_MinorTick,B_MinorTick,C_MinorTick;
        A_TickLabel,B_TickLabel,C_TickLabel;
        % A_LabelStr='A-Axis';
        % B_LabelStr='B-Axis';
        % C_LabelStr='C-Axis';
        A_TickLabelStr={'20','40','60','80','100'};
        B_TickLabelStr={'20','40','60','80','100'};
        C_TickLabelStr={'20','40','60','80','100'};
    end
    methods
% Create Ternary Axes =====================================================
        function obj=STernary(ax)
            if nargin<1,ax=gca;end
            obj.ax=ax;
            obj.ax.NextPlot='add';
            obj.ax.XLim=[0-1/40,1+1/40];
            obj.ax.YLim=[0-1/40,sqrt(3)/2+sqrt(3)/80];
            obj.ax.XGrid='off';
            obj.ax.YGrid='off';
            obj.ax.Box='off';
            obj.ax.DataAspectRatio=[1,1,1];
            obj.ax.XColor='none';
            obj.ax.YColor='none';
            % Draw Background >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            obj.BkgHdl=fill(obj.ax,[0,1,1/2],[0,0,sqrt(3)/2],[1,1,1],'EdgeColor','none');
            obj.TriLHdl=fill(obj.ax,[0,1/2+1/40,0],[0,sqrt(3)/2+1/40*sqrt(3),sqrt(3)/2+1/40*sqrt(3)],[1,1,1],'EdgeColor','none');
            obj.TriRHdl=fill(obj.ax,[1,1/2-1/40,1],[0,sqrt(3)/2+1/40*sqrt(3),sqrt(3)/2+1/40*sqrt(3)],[1,1,1],'EdgeColor','none');
            obj.BkgHdl.Annotation.LegendInformation.IconDisplayStyle='off';
            obj.TriLHdl.Annotation.LegendInformation.IconDisplayStyle='off';
            obj.TriRHdl.Annotation.LegendInformation.IconDisplayStyle='off';
            % Draw Minor Grid >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            obj.MinorGridValues=setdiff(obj.MinorGridValues,obj.GridValues);
            AMGX=[1-obj.MinorGridValues./200;obj.MinorGridValues./200;obj.MinorGridValues.*nan];
            AMGY=[obj.MinorGridValues./200.*sqrt(3);obj.MinorGridValues./200.*sqrt(3);obj.MinorGridValues.*nan];
            obj.A_MinorGrid=plot(obj.ax,AMGX(:),AMGY(:),'LineWidth',.5,'Color',[0,0,0,.2],'LineStyle','-');
            obj.A_MinorGrid.Annotation.LegendInformation.IconDisplayStyle='off';
            %
            BMGX=[1/2-obj.MinorGridValues./200;1-obj.MinorGridValues./100;obj.MinorGridValues.*nan];
            BMGY=[sqrt(3)/2-obj.MinorGridValues./200.*sqrt(3);obj.MinorGridValues.*0;obj.MinorGridValues.*nan];
            obj.B_MinorGrid=plot(obj.ax,BMGX(:),BMGY(:),'LineWidth',.5,'Color',[0,0,0,.2],'LineStyle','-');
            obj.B_MinorGrid.Annotation.LegendInformation.IconDisplayStyle='off';
            %
            CMGX=[obj.MinorGridValues./100;1/2+obj.MinorGridValues./200;obj.MinorGridValues.*nan];
            CMGY=[obj.MinorGridValues.*0;1/2.*sqrt(3)-obj.MinorGridValues./200.*sqrt(3);obj.MinorGridValues.*nan];
            obj.C_MinorGrid=plot(obj.ax,CMGX(:),CMGY(:),'LineWidth',.5,'Color',[0,0,0,.2],'LineStyle','-');
            obj.C_MinorGrid.Annotation.LegendInformation.IconDisplayStyle='off';
            % Draw Grid >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            AGX=[1-obj.GridValues./200;obj.GridValues./200;obj.GridValues.*nan];
            AGY=[obj.GridValues./200.*sqrt(3);obj.GridValues./200.*sqrt(3);obj.GridValues.*nan];
            obj.A_Grid=plot(obj.ax,AGX(:),AGY(:),'LineWidth',.8,'Color',[0,0,0,.7],'LineStyle','-');
            obj.A_Grid.Annotation.LegendInformation.IconDisplayStyle='off';
            %
            BGX=[1/2-obj.GridValues./200;1-obj.GridValues./100;obj.GridValues.*nan];
            BGY=[sqrt(3)/2-obj.GridValues./200.*sqrt(3);obj.GridValues.*0;obj.GridValues.*nan];
            obj.B_Grid=plot(obj.ax,BGX(:),BGY(:),'LineWidth',.8,'Color',[0,0,0,.7],'LineStyle','-');
            obj.B_Grid.Annotation.LegendInformation.IconDisplayStyle='off';
            %
            CGX=[obj.GridValues./100;1/2+obj.GridValues./200;obj.GridValues.*nan];
            CGY=[obj.GridValues.*0;1/2.*sqrt(3)-obj.GridValues./200.*sqrt(3);obj.GridValues.*nan];
            obj.C_Grid=plot(obj.ax,CGX(:),CGY(:),'LineWidth',.8,'Color',[0,0,0,.7],'LineStyle','-');
            obj.C_Grid.Annotation.LegendInformation.IconDisplayStyle='off';
            % Draw Minor Tick >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            obj.MinorTickValues=setdiff(obj.MinorTickValues,obj.TickValues);
            AMTX=[1-obj.MinorTickValues./200;1-obj.MinorTickValues./200+cos(0).*obj.TickLenth(2);obj.MinorTickValues.*nan];
            AMTY=[obj.MinorTickValues./200.*sqrt(3);obj.MinorTickValues./200.*sqrt(3)+sin(0).*obj.TickLenth(2);obj.MinorTickValues.*nan];
            obj.A_MinorTick=plot(obj.ax,AMTX(:),AMTY(:),'LineWidth',.8,'Color',[0,0,0]);
            obj.A_MinorTick.Annotation.LegendInformation.IconDisplayStyle='off';
            %
            BMTX=[1/2-obj.MinorTickValues./200;1/2-obj.MinorTickValues./200+cos(2*pi/3).*obj.TickLenth(2);obj.MinorTickValues.*nan];help STernary
            BMTY=[sqrt(3)/2-obj.MinorTickValues./200.*sqrt(3);sqrt(3)/2-obj.MinorTickValues./200.*sqrt(3)+sin(2*pi/3).*obj.TickLenth(2);obj.MinorTickValues.*nan];
            obj.B_MinorTick=plot(obj.ax,BMTX(:),BMTY(:),'LineWidth',.8,'Color',[0,0,0]);
            obj.B_MinorTick.Annotation.LegendInformation.IconDisplayStyle='off';
            %
            CMTX=[obj.MinorTickValues./100;obj.MinorTickValues./100+cos(-2*pi/3).*obj.TickLenth(2);obj.MinorTickValues.*nan];
            CMTY=[obj.MinorTickValues.*0;obj.MinorTickValues.*0+sin(-2*pi/3).*obj.TickLenth(2);obj.MinorTickValues.*nan];
            obj.C_MinorTick=plot(obj.ax,CMTX(:),CMTY(:),'LineWidth',.8,'Color',[0,0,0]);
            obj.C_MinorTick.Annotation.LegendInformation.IconDisplayStyle='off';
            % Draw Tick >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            ATX=[1-obj.TickValues./200;1-obj.TickValues./200+cos(0).*obj.TickLenth(1);obj.TickValues.*nan];
            ATY=[obj.TickValues./200.*sqrt(3);obj.TickValues./200.*sqrt(3)+sin(0).*obj.TickLenth(1);obj.TickValues.*nan];
            obj.A_Tick=plot(obj.ax,ATX(:),ATY(:),'LineWidth',1.2,'Color',[0,0,0]);
            obj.A_Tick.Annotation.LegendInformation.IconDisplayStyle='off';
            %
            BTX=[1/2-obj.TickValues./200;1/2-obj.TickValues./200+cos(2*pi/3).*obj.TickLenth(1);obj.TickValues.*nan];
            BTY=[sqrt(3)/2-obj.TickValues./200.*sqrt(3);sqrt(3)/2-obj.TickValues./200.*sqrt(3)+sin(2*pi/3).*obj.TickLenth(1);obj.TickValues.*nan];
            obj.B_Tick=plot(obj.ax,BTX(:),BTY(:),'LineWidth',1.2,'Color',[0,0,0]);
            obj.B_Tick.Annotation.LegendInformation.IconDisplayStyle='off';
            %
            CTX=[obj.TickValues./100;obj.TickValues./100+cos(-2*pi/3).*obj.TickLenth(1);obj.TickValues.*nan];
            CTY=[obj.TickValues.*0;obj.TickValues.*0+sin(-2*pi/3).*obj.TickLenth(1);obj.TickValues.*nan];
            obj.C_Tick=plot(obj.ax,CTX(:),CTY(:),'LineWidth',1.2,'Color',[0,0,0]);
            obj.C_Tick.Annotation.LegendInformation.IconDisplayStyle='off';
            % Draw Axis >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            obj.A_Axis=plot(obj.ax,[1,1/2],[0,sqrt(3)/2],'Color',[0,0,0],'LineWidth',1.2);
            obj.B_Axis=plot(obj.ax,[1/2,0],[sqrt(3)/2,0],'Color',[0,0,0],'LineWidth',1.2);
            obj.C_Axis=plot(obj.ax,[0,1],[0,0],'Color',[0,0,0],'LineWidth',1.2);
            obj.A_Axis.Annotation.LegendInformation.IconDisplayStyle='off';
            obj.B_Axis.Annotation.LegendInformation.IconDisplayStyle='off';
            obj.C_Axis.Annotation.LegendInformation.IconDisplayStyle='off';
            % Draw Tick Label >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            for i=1:length(obj.TickValues)
                obj.A_TickLabel{i}=text(obj.ax,...
                    1-obj.TickValues(i)./200+cos(0).*(obj.TickLenth(1)+.01),...
                    obj.TickValues(i)./200.*sqrt(3)+sin(0).*(obj.TickLenth(1)+.01),...
                    obj.A_TickLabelStr{i},'FontName','Cambria','FontSize',12);
                obj.B_TickLabel{i}=text(obj.ax,...
                    1/2-obj.TickValues(i)./200+cos(2*pi/3).*(obj.TickLenth(1)+.01),...
                    sqrt(3)/2-obj.TickValues(i)./200.*sqrt(3)+sin(2*pi/3).*(obj.TickLenth(1)+.01),...
                    obj.B_TickLabelStr{i},'FontName','Cambria','FontSize',12,...
                    'Rotation',-60,'HorizontalAlignment','right');
                obj.C_TickLabel{i}=text(obj.ax,...
                    obj.TickValues(i)./100+cos(-2*pi/3).*(obj.TickLenth(1)+.01),...
                    sin(-2*pi/3).*(obj.TickLenth(1)+.01),...
                    obj.C_TickLabelStr{i},'FontName','Cambria','FontSize',12,...
                    'Rotation',60,'HorizontalAlignment','right');
            end
            % Draw Label >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            obj.A_Label=text(obj.ax,1/2+cos(pi/2).*obj.LabelSep,sqrt(3)/2+sin(pi/2).*obj.LabelSep,'A-Axis',...
                'FontName','Cambria','FontSize',16,'HorizontalAlignment','center','VerticalAlignment','bottom');
            obj.B_Label=text(obj.ax,cos(-5*pi/6).*obj.LabelSep,sin(-5*pi/6).*obj.LabelSep,'B-Axis',...
                'FontName','Cambria','FontSize',16,'HorizontalAlignment','right','VerticalAlignment','top');
            obj.C_Label=text(obj.ax,1+cos(-pi/6).*obj.LabelSep,sin(-pi/6).*obj.LabelSep,'C-Axis',...
                'FontName','Cambria','FontSize',16,'HorizontalAlignment','left','VerticalAlignment','top');
        end
% Copyright (c) 2023, Zhaoxu Liu / slandarer
% =========================================================================
% @author : slandarer
% gzh  : slandarer随笔
% -------------------------------------------------------------------------
% Zhaoxu Liu / slandarer (2023). ternary 
% (https://www.mathworks.com/matlabcentral/fileexchange/127958-ternary), 
% MATLAB Central File Exchange. 检索来源 2023/4/18.
% Set Ternary Axes ========================================================
        % function setColor(obj,color)
        %     set(obj.BkgHdl,'FaceColor',color);
        % end
% -------------------------------------------------------------------------
        function set(obj,hdlName,varargin)
            if isa(obj.(hdlName),'double')||(length(obj.(hdlName))>1&&(isa(obj.(hdlName){1},'char')||isa(obj.(hdlName){1},'string')))
                switch true
                    case isequal(hdlName,'Color')
                        obj.Color=varargin{:};
                        set(obj.BkgHdl,'FaceColor',varargin{:});
                    case isequal(hdlName,'TickLenth')
                        obj.TickLenth=varargin{:};
                    case isequal(hdlName(end-2:end),'ues')
                        obj.(hdlName)=varargin{:};
                    case isequal(hdlName(end-2:end),'Str')
                        obj.(hdlName)=varargin{:};
                end
                % Renew Minor Grid >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                obj.MinorGridValues=setdiff(obj.MinorGridValues,obj.GridValues);
                AMGX=[1-obj.MinorGridValues./200;obj.MinorGridValues./200;obj.MinorGridValues.*nan];
                AMGY=[obj.MinorGridValues./200.*sqrt(3);obj.MinorGridValues./200.*sqrt(3);obj.MinorGridValues.*nan];
                set(obj.A_MinorGrid,'XData',AMGX(:),'YData',AMGY(:));
                %
                BMGX=[1/2-obj.MinorGridValues./200;1-obj.MinorGridValues./100;obj.MinorGridValues.*nan];
                BMGY=[sqrt(3)/2-obj.MinorGridValues./200.*sqrt(3);obj.MinorGridValues.*0;obj.MinorGridValues.*nan];
                set(obj.B_MinorGrid,'XData',BMGX(:),'YData',BMGY(:));
                %
                CMGX=[obj.MinorGridValues./100;1/2+obj.MinorGridValues./200;obj.MinorGridValues.*nan];
                CMGY=[obj.MinorGridValues.*0;1/2.*sqrt(3)-obj.MinorGridValues./200.*sqrt(3);obj.MinorGridValues.*nan];
                set(obj.C_MinorGrid,'XData',CMGX(:),'YData',CMGY(:));
                % Renew Grid >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                AGX=[1-obj.GridValues./200;obj.GridValues./200;obj.GridValues.*nan];
                AGY=[obj.GridValues./200.*sqrt(3);obj.GridValues./200.*sqrt(3);obj.GridValues.*nan];
                set(obj.A_Grid,'XData',AGX(:),'YData',AGY(:));
                %
                BGX=[1/2-obj.GridValues./200;1-obj.GridValues./100;obj.GridValues.*nan];
                BGY=[sqrt(3)/2-obj.GridValues./200.*sqrt(3);obj.GridValues.*0;obj.GridValues.*nan];
                set(obj.B_Grid,'XData',BGX(:),'YData',BGY(:));
                %
                CGX=[obj.GridValues./100;1/2+obj.GridValues./200;obj.GridValues.*nan];
                CGY=[obj.GridValues.*0;1/2.*sqrt(3)-obj.GridValues./200.*sqrt(3);obj.GridValues.*nan];
                set(obj.C_Grid,'XData',CGX(:),'YData',CGY(:));
                % Renew Minor Tick >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                obj.MinorTickValues=setdiff(obj.MinorTickValues,obj.TickValues);
                AMTX=[1-obj.MinorTickValues./200;1-obj.MinorTickValues./200+cos(0).*obj.TickLenth(2);obj.MinorTickValues.*nan];
                AMTY=[obj.MinorTickValues./200.*sqrt(3);obj.MinorTickValues./200.*sqrt(3)+sin(0).*obj.TickLenth(2);obj.MinorTickValues.*nan];
                set(obj.A_MinorTick,'XData',AMTX(:),'YData',AMTY(:));
                %
                BMTX=[1/2-obj.MinorTickValues./200;1/2-obj.MinorTickValues./200+cos(2*pi/3).*obj.TickLenth(2);obj.MinorTickValues.*nan];
                BMTY=[sqrt(3)/2-obj.MinorTickValues./200.*sqrt(3);sqrt(3)/2-obj.MinorTickValues./200.*sqrt(3)+sin(2*pi/3).*obj.TickLenth(2);obj.MinorTickValues.*nan];
                set(obj.B_MinorTick,'XData',BMTX(:),'YData',BMTY(:));
                %
                CMTX=[obj.MinorTickValues./100;obj.MinorTickValues./100+cos(-2*pi/3).*obj.TickLenth(2);obj.MinorTickValues.*nan];
                CMTY=[obj.MinorTickValues.*0;obj.MinorTickValues.*0+sin(-2*pi/3).*obj.TickLenth(2);obj.MinorTickValues.*nan];
                set(obj.C_MinorTick,'XData',CMTX(:),'YData',CMTY(:));
                % Renew Tick >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                ATX=[1-obj.TickValues./200;1-obj.TickValues./200+cos(0).*obj.TickLenth(1);obj.TickValues.*nan];
                ATY=[obj.TickValues./200.*sqrt(3);obj.TickValues./200.*sqrt(3)+sin(0).*obj.TickLenth(1);obj.TickValues.*nan];
                set(obj.A_Tick,'XData',ATX(:),'YData',ATY(:));
                %
                BTX=[1/2-obj.TickValues./200;1/2-obj.TickValues./200+cos(2*pi/3).*obj.TickLenth(1);obj.TickValues.*nan];
                BTY=[sqrt(3)/2-obj.TickValues./200.*sqrt(3);sqrt(3)/2-obj.TickValues./200.*sqrt(3)+sin(2*pi/3).*obj.TickLenth(1);obj.TickValues.*nan];
                set(obj.B_Tick,'XData',BTX(:),'YData',BTY(:));
                %
                CTX=[obj.TickValues./100;obj.TickValues./100+cos(-2*pi/3).*obj.TickLenth(1);obj.TickValues.*nan];
                CTY=[obj.TickValues.*0;obj.TickValues.*0+sin(-2*pi/3).*obj.TickLenth(1);obj.TickValues.*nan];
                set(obj.C_Tick,'XData',CTX(:),'YData',CTY(:));
                % Renew Tick Label >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                for i=1:length(obj.TickValues)
                    set(obj.A_TickLabel{i},'Position',...
                        [1-obj.TickValues(i)./200+cos(0).*(obj.TickLenth(1)+.01),...
                        obj.TickValues(i)./200.*sqrt(3)+sin(0).*(obj.TickLenth(1)+.01)],...
                        'String',obj.A_TickLabelStr{mod(i-1,length(obj.TickValues))+1});
                    set(obj.B_TickLabel{i},'Position',...
                        [1/2-obj.TickValues(i)./200+cos(2*pi/3).*(obj.TickLenth(1)+.01),...
                        sqrt(3)/2-obj.TickValues(i)./200.*sqrt(3)+sin(2*pi/3).*(obj.TickLenth(1)+.01)],...
                        'String',obj.B_TickLabelStr{mod(i-1,length(obj.TickValues))+1});
                    set(obj.C_TickLabel{i},'Position',...
                        [obj.TickValues(i)./100+cos(-2*pi/3).*(obj.TickLenth(1)+.01),...
                        sin(-2*pi/3).*(obj.TickLenth(1)+.01)],...
                        'String',obj.C_TickLabelStr{mod(i-1,length(obj.TickValues))+1});
                end
            else
                if length(obj.(hdlName))>1
                    tHdl=obj.(hdlName);
                    for i=1:length(tHdl)
                        set(tHdl{i},varargin{:})
                    end
                else
                    set(obj.(hdlName),varargin{:})
                end
            end
        end
% -------------------------------------------------------------------------
        function label2Side(obj)
            set(obj.A_Label,'Position',[3/4+cos(pi/6).*obj.LabelSep.*90,sqrt(3)/4+sin(pi/6).*obj.LabelSep.*90],...
                'HorizontalAlignment','center','VerticalAlignment','bottom','Rotation',-60)
            set(obj.B_Label,'Position',[1/4+cos(5*pi/6).*obj.LabelSep.*90,sqrt(3)/4+sin(5*pi/6).*obj.LabelSep.*90],...
                'HorizontalAlignment','center','VerticalAlignment','bottom','Rotation',60)
            set(obj.C_Label,'Position',[1/2+cos(-pi/2).*obj.LabelSep.*90,0+sin(-pi/2).*obj.LabelSep.*90],...
                'HorizontalAlignment','center','VerticalAlignment','top','Rotation',0)
        end
% Copyright (c) 2023, Zhaoxu Liu / slandarer
% =========================================================================
% @author : slandarer
% gzh  : slandarer随笔
% -------------------------------------------------------------------------
% Zhaoxu Liu / slandarer (2023). ternary 
% (https://www.mathworks.com/matlabcentral/fileexchange/127958-ternary), 
% MATLAB Central File Exchange. 检索来源 2023/4/18.
% Define Functions ========================================================
        function scatterHdl=SScatter(obj,A,B,C,varargin)
            [X,Y]=obj.ternData(A,B,C);
            scatterHdl=scatter(obj.ax,X,Y,varargin{:});
        end
% -------------------------------------------------------------------------
        function plotHdl=SPlot(obj,A,B,C,varargin)
            [X,Y]=obj.ternData(A,B,C);
            plotHdl=plot(obj.ax,X,Y,varargin{:});
        end
% -------------------------------------------------------------------------
        function fillHdl=SFill(obj,A,B,C,varargin)
            [X,Y]=obj.ternData(A,B,C);
            fillHdl=fill(obj.ax,X,Y,varargin{:});
        end
% -------------------------------------------------------------------------
        function convhullHdl=SConvhull(obj,A,B,C,varargin)
            [X,Y]=obj.ternData(A,B,C);
            [ind,~]=convhull([X,Y]);
            convhullHdl=fill(obj.ax,X(ind),Y(ind),varargin{:});
        end
% -------------------------------------------------------------------------
        function textHdl=SText(obj,A,B,C,varargin)
            [X,Y]=obj.ternData(A,B,C);
            textHdl=text(obj.ax,X,Y,varargin{:});
        end
% -------------------------------------------------------------------------
        function bubblechartHdl=SBubblechart(obj,A,B,C,varargin)
            [X,Y]=obj.ternData(A,B,C);
            bubblechartHdl=bubblechart(obj.ax,X,Y,varargin{:});
        end
% -------------------------------------------------------------------------
        function [contourHdl,Z]=SContour(obj,A,B,C,N,varargin)
            if isempty(N),N=90;end
            [X,Y]=obj.ternData(A,B,C);
            [XX1,XX2]=meshgrid(linspace(0,1,N),linspace(0,1,N));
            F=ksdensity([X,Y],[XX1(:),XX2(:)]);
            Z=reshape(F,size(XX1));
            Z(XX2>XX1.*sqrt(3)+.03)=nan;
            Z(XX2>sqrt(3)-XX1.*sqrt(3)+.03)=nan;
            hdlSet=findobj(obj.ax,'Tag','TernaryContour');
            if isempty(hdlSet)
                T=1;
            else
                T=1;
                for i=1:length(hdlSet)
                    T=max(T,get(hdlSet(i),'UserData')+1);
                end
            end
            contour(obj.ax,XX1,XX2,Z,varargin{:},'Tag','TernaryContour','UserData',T);
            uistack(obj.TriLHdl,'top');uistack(obj.TriRHdl,'top')
            uistack(obj.A_MinorTick,'top');uistack(obj.B_MinorTick,'top');uistack(obj.C_MinorTick,'top');
            uistack(obj.A_Tick,'top');uistack(obj.B_Tick,'top');uistack(obj.C_Tick,'top');
            uistack(obj.A_Axis,'top');uistack(obj.B_Axis,'top');uistack(obj.C_Axis,'top');
            for i=1:length(obj.A_TickLabel)
                uistack(obj.A_TickLabel{i},'top');
                uistack(obj.B_TickLabel{i},'top');
                uistack(obj.C_TickLabel{i},'top');
            end
            uistack(obj.A_Label,'top');uistack(obj.B_Label,'top');uistack(obj.C_Label,'top');
            contourHdl=findobj(obj.ax,'Tag','TernaryContour','UserData',T);
        end
% -------------------------------------------------------------------------
        function [contourfHdl,Z]=SContourf(obj,A,B,C,N,varargin)
            if isempty(N),N=90;end
            [X,Y]=obj.ternData(A,B,C);
            [XX1,XX2]=meshgrid(linspace(0,1,N),linspace(0,1,N));
            F=ksdensity([X,Y],[XX1(:),XX2(:)]);
            Z=reshape(F,size(XX1));
            Z(XX2>XX1.*sqrt(3)+.03)=nan;
            Z(XX2>sqrt(3)-XX1.*sqrt(3)+.03)=nan;
            hdlSet=findobj(obj.ax,'Tag','TernaryContour');
            if isempty(hdlSet)
                T=1;
            else
                T=1;
                for i=1:length(hdlSet)
                    T=max(T,get(hdlSet(i),'UserData')+1);
                end
            end
            contourf(obj.ax,XX1,XX2,Z,varargin{:},'Tag','TernaryContour','UserData',T);
            uistack(obj.TriLHdl,'top');uistack(obj.TriRHdl,'top')
            uistack(obj.A_MinorTick,'top');uistack(obj.B_MinorTick,'top');uistack(obj.C_MinorTick,'top');
            uistack(obj.A_Tick,'top');uistack(obj.B_Tick,'top');uistack(obj.C_Tick,'top');
            uistack(obj.A_Axis,'top');uistack(obj.B_Axis,'top');uistack(obj.C_Axis,'top');
            for i=1:length(obj.A_TickLabel)
                uistack(obj.A_TickLabel{i},'top');
                uistack(obj.B_TickLabel{i},'top');
                uistack(obj.C_TickLabel{i},'top');
            end   
            uistack(obj.A_Label,'top');uistack(obj.B_Label,'top');uistack(obj.C_Label,'top');
            contourfHdl=findobj(obj.ax,'Tag','TernaryContour','UserData',T);
        end
% -------------------------------------------------------------------------
        function [X,Y]=ternData(~,A,B,C)
            ABC=[A(:),B(:),C(:)];
            ABC=ABC./sum(ABC,2);
            B=ABC(:,2);C=ABC(:,3);
            X=C+(1-C-B)./2;
            Y=0+sqrt(3).*(1-C-B)./2;
        end
% -------------------------------------------------------------------------
        function ABC=SNorm(~,ABC)
            ABC=ABC-min(ABC,[],1);
            ABC=ABC./max(ABC,[],1);
        end
% -------------------------------------------------------------------------
        function ABC=SNormByLim(~,ABC,Lim)
            ABC=ABC-Lim([1,3,5]);
            ABC=ABC./(Lim([2,4,6])-Lim([1,3,5]));
        end
    end
% Copyright (c) 2023, Zhaoxu Liu / slandarer
% =========================================================================
% @author : slandarer
% gzh  : slandarer随笔
% -------------------------------------------------------------------------
% Zhaoxu Liu / slandarer (2023). ternary 
% (https://www.mathworks.com/matlabcentral/fileexchange/127958-ternary), 
% MATLAB Central File Exchange. 检索来源 2023/4/18.
end

本代码编写真的不易,光看工具函数也能看出工作量(写推文时mdnice都卡住了),希望大家该点赞的点赞,该在看的在看!!

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

Zhaoxu Liu / slandarer (2023). ternary (https://www.mathworks.com/matlabcentral/fileexchange/127958-ternary), MATLAB Central File Exchange. 检索来源 2023/4/18.

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

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

https://gitee.com/slandarer/matlab-ternary-plot文章来源地址https://www.toymoban.com/news/detail-427810.html

到了这里,关于MATLAB | 如何用MATLAB如何绘制各式各样精致的三元相图(ternary plot)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MATLAB | 如何使用MATLAB绘制雷达图(蜘蛛图)

    数据为数值矩阵即可: 有 Patch 和 Line 两种样式,通过设置 Type 属性设置样式: 范围改为[2,10],并绘制2,8,9,10四条刻度线: 使用: setThetaTick setRTick 设置轴属性,举个例子,theta轴变为淡红色,R轴变为淡蓝色: 使用: setPropLabel setRLabel 修改属性标签和R刻度标签: 使用 setBkg 函数修饰

    2024年02月12日
    浏览(29)
  • MATLAB | 如何使用MATLAB绘制甘特图(gantt chart)

    好久不见哈,今天带来一个不咋炫酷但是比较实用的甘特图绘制,就画一堆矩形嘛非常简单。 之所以这期工具函数放在最前面是因为比较短哈: 基本使用 设置任务开始时间,结束时间及任务编号后,调用工具函数绘图即可: 不咋好看的圆角 设置 Curvature 为0-1之间的数值即可

    2024年02月09日
    浏览(26)
  • MATLAB | 如何使用MATLAB绘制高度自定义的桑基图(sankey)

    我之前也出过一个超简单的桑基图绘制函数,但是无法应对很多特殊情况,在这里我将其重构了一些写成了类,加了很多内置修饰函数,实现了流入流出数据不相等或者跨层数据流动的特殊情况绘制,首先展示一下使用我编写的函数能够实现怎样的效果吧: 以上的图片全是本

    2024年02月04日
    浏览(57)
  • MATLAB | 如何绘制这样的描边散点图?

    最近略忙可能更新的内容会比较简单,见谅哇,今日更新内容: 看到gzh BYtools科研笔记 (推荐大家可以去瞅瞅,有很多有意思的图形的R语言复现!!)做了这样一张图: 感觉很有意思,但是作者是使用 R语言+Adobe illustrator 进行完成的,于是俺就想试试能不能用 MATLAB来进行完成

    2024年02月14日
    浏览(27)
  • 一文讲解如何写出高效精致SQL

    尽量避免select * from,仅返回所需字段         在日常查询表数据时,经常不自觉的写select * from,查询全部字段信息;虽然记录少的单表没啥感觉,但当关联多个表且表体量大时,select * from将返回所有表的字段,会影响查询效率。较好的方式,就是需要什么查什么, 仅返回

    2024年02月09日
    浏览(26)
  • 详尽解读MATLAB中如何绘制和动态展示GPS NMEA数据的实现方式

    大家好,我在这篇文章中想与大家分享一些我个人的经验和见解。我会详细讨论如何在MATLAB中绘制和动态展示GPS NMEA数据。在我的学习和研究过程中,我遇到了很多挑战,但我仍然坚持并逐步掌握了这项技术。我希望这篇文章能够对你的学习和研究有所帮助。 在科学研究和工

    2024年02月09日
    浏览(30)
  • 如何用python绘制流星雨【附源码】

    一、方案一      最为简单的方法是:使用随机数来控制流星的生成频率。通过调整生成流星的概率,可以控制流星雨的密度,具体代码如下: import pygame import random import sys # 初始化 Pygame pygame.init() # 屏幕大小 SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 # 颜色 WHITE = (255, 255, 255) BLACK = (0,

    2024年04月14日
    浏览(37)
  • 如何用 Midjourney 绘制你自己的拟人头像?

    在元宇宙时代,许多人都使用各种AI应用程序来生成他们自己的头像,其中Midjourney是一个非常流行的选择。然而,成功的先行者可能不愿意透露具体的prompt(提示语),因为他们可能担心自己的创意被其他人抄袭。此外,prompt的选择也取决于每个人的具体需求和创意,不同的

    2024年02月09日
    浏览(63)
  • 前端-如何用echarts绘制含有多个分层的波形图

    先展示一下实际的效果图 用户选择完需要的波形参数字段之后,页面开始渲染图表,有几个参数就要渲染几个grid,也就是几行波形。 拿到所选的参数数据之后 1.首先是给横坐标轴的里程-数据注入 2.修改tooltip(跟着竖线走的卡片弹窗)里面的弹出窗的显示,需要返回html模板

    2024年02月01日
    浏览(27)
  • 如何用 Midjourney 绘制你自己的皮克斯风格头像?

    元宇宙时代,有个卡通形式的头像(Avatar)似乎是刚需了。我看到很多小伙伴都给自己弄了一个头像。大多保持了神似,很是羡慕。 我也想自己弄一个,不过雇人设计绘制太贵,自己画嘛,你知道的…… 我的武松打虎,画的是这样的: 所以,我还是得找帮手来绘制。好在咱

    2024年02月09日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包