├── CoorFromAxis2Fig.m
├── DrawAxisWithArrow.m
├── DrawLine.m
├── FigPointLabel.m
├── README.md
├── SaveFig2Img.m
├── demo01.m
├── demo02.m
├── demo03.m
├── demo04.m
└── figures
├── demo01.png
├── demo02.png
├── demo03.png
└── demo04.png
/CoorFromAxis2Fig.m:
--------------------------------------------------------------------------------
1 | function [fp] = CoorFromAxis2Fig(h_axi, ap)
2 | %CoorFromAxis2Fig - 将点在 axis 的坐标转换为该点在 figure 上的坐标
3 | %
4 | % Syntax: [fp] = CoorFromAxis2Fig(h_axi, ap)
5 | %
6 | % Input: h_axi 坐标轴句柄
7 | % ap 点在h_axi上的坐标
8 | %
9 | % Output:
10 | % fp 该点在figure上的坐标
11 |
12 | x_range = get(h_axi, 'XLim'); % axis的x轴范围
13 | y_range = get(h_axi, 'YLim'); % axis的y轴范围
14 | rec = get(h_axi, 'Position'); % axis在fig的坐标(x,y,w,h)
15 | fp(1) = (ap(1)-x_range(1))*rec(3) / (x_range(2)-x_range(1)) + rec(1);
16 | fp(2) = (ap(2)-y_range(1))*rec(4) / (y_range(2)-y_range(1)) + rec(2);
17 |
18 | end
19 |
20 |
--------------------------------------------------------------------------------
/DrawAxisWithArrow.m:
--------------------------------------------------------------------------------
1 | function [xarrow, yarrow] = DrawAxisWithArrow(h_axi, varargin)
2 | %DrawAxisWithArrow - 绘制带箭头的坐标轴
3 | %
4 | % Syntax: [xarrow, yarrow] = DrawAxisWithArrow(h_axi[, param])
5 | %
6 | % Input: h_axi 坐标轴句柄
7 | % param 可选参数,要求输入参数为一个结构体,成员如下:
8 | % Color 坐标轴的颜色
9 | % HeadWidth 箭头大小
10 | % XLabel x轴的标签(在箭头上方)
11 | % YLabel y轴的标签(在箭头右方)
12 | % Olabel 原点的标签(两坐标轴交点的左下角)
13 | % XyVisible 可选值为x,y,xy(默认), 表示可视化的轴
14 | % 若结构体未包含某项成员,则使用默认值
15 | %
16 | % Output: xarrow x坐标轴对象
17 | % yarrow y坐标轴对象
18 |
19 | %% 输入参数处理
20 | n = length(varargin);
21 | if n == 0
22 | arrow_color = [0.7, 0.62, 1]; % arrow 的默认颜色
23 | head_width = 6; % 箭头的默认大小
24 | xy_visible = 'xy'; % 显示x轴和y轴
25 | xlabel_str = ''; % x 轴的标签
26 | ylabel_str = ''; % y 轴的标签
27 | olabel_str = ''; % x 轴与y轴交点的标签
28 | elseif n == 1
29 | % 坐标轴颜色
30 | if isfield(varargin{1}, 'Color')
31 | arrow_color = varargin{1}.Color;
32 | else
33 | arrow_color = [0.7, 0.62, 1];
34 | end
35 | % 箭头大小
36 | if isfield(varargin{1}, 'HeadWidth')
37 | head_width = varargin{1}.HeadWidth;
38 | else
39 | head_width = 6;
40 | end
41 | % x轴标签
42 | if isfield(varargin{1}, 'XLabel')
43 | xlabel_str = varargin{1}.XLabel;
44 | else
45 | xlabel_str = '';
46 | end
47 | % y轴标签
48 | if isfield(varargin{1}, 'YLabel')
49 | ylabel_str = varargin{1}.YLabel;
50 | else
51 | ylabel_str = '';
52 | end
53 | % 原点标签
54 | if isfield(varargin{1}, 'OLabel')
55 | olabel_str = varargin{1}.OLabel;
56 | else
57 | olabel_str = '';
58 | end
59 | % 显示的坐标轴
60 | if isfield(varargin{1}, 'XyVisible')
61 | xy_visible = varargin{1}.XyVisible;
62 | else
63 | xy_visible = 'xy';
64 | end
65 | else
66 | error('DrawAxisWithArrow: 输入参数太多');
67 | end
68 |
69 | %% 获得坐标原点的位置,
70 | % 若坐标轴的范围不包含坐标原点,则选择最靠近原点的一角作为坐标轴的交点,
71 | % 坐标轴的箭头指向正向
72 | x_range = get(h_axi, 'XLim');
73 | y_range = get(h_axi, 'YLim');
74 | op = [0, 0]; % 默认交点为坐标原点
75 | if x_range(1) > 0
76 | op(1) = x_range(1);
77 | elseif x_range(2) < 0
78 | op(1) = x_range(2);
79 | else
80 | op(1) = 0;
81 | end
82 | if y_range(1) > 0
83 | op(2) = y_range(1);
84 | elseif y_range(2) < 0
85 | op(2) = y_range(2);
86 | else
87 | op(2) = 0;
88 | end
89 | op = CoorFromAxis2Fig(h_axi, op); % 转换为在fig上的坐标
90 |
91 | % 获得axis的坐标
92 | axis_rec = get(h_axi, 'Position'); % axis在fig的坐标(x,y,w,h)
93 | % 获得fig句柄
94 | h_fig = get(h_axi, 'Parent');
95 | % 绘制 x 坐标轴
96 | if find('x'==xy_visible)
97 | xarrow_x = [axis_rec(1)-0.05*axis_rec(3), axis_rec(1)+1.05*axis_rec(3)];
98 | xarrow_y = [op(2), op(2)];
99 | xarrow = annotation(h_fig, 'arrow', xarrow_x, xarrow_y);
100 | set(xarrow, 'HeadStyle', 'plain', 'HeadWidth', head_width, 'Color', arrow_color);
101 | end
102 | % 绘制 y 坐标轴
103 | if find('y'==xy_visible)
104 | yarrow_x = [op(1), op(1)];
105 | yarrow_y = [axis_rec(2)-0.05*axis_rec(4), axis_rec(2)+1.05*axis_rec(4)];
106 | yarrow = annotation(h_fig, 'arrow', yarrow_x, yarrow_y);
107 | set(yarrow, 'HeadStyle', 'plain', 'HeadWidth', head_width, 'Color', arrow_color);
108 | end
109 | % 关闭默认的坐标轴
110 | set(h_axi, 'Visible', 'off');
111 |
112 | %% 是否显示坐标标签
113 | if xlabel_str
114 | XArrowLabel(xarrow, xlabel_str);
115 | end
116 | if ylabel_str
117 | YArrowLabel(yarrow, ylabel_str);
118 | end
119 | if olabel_str
120 | OriginLabel(op, olabel_str);
121 | end
122 |
123 | end
124 |
125 | function YArrowLabel(arrow, str)
126 | % 给 y 坐标轴添加标签
127 | p = [0, 0];
128 | arrow_x = get(arrow, 'X');
129 | arrow_y = get(arrow, 'Y');
130 | p(1) = arrow_x(2);
131 | p(2) = arrow_y(2);
132 |
133 | param.Color = [0.8, 0.52, 0.98];
134 | param.FontSize = 14;
135 |
136 | FigPointLabel(p, str, 'east', param);
137 | end
138 |
139 | function XArrowLabel(arrow, str)
140 | % 给 x 坐标轴添加标签
141 | p = [0, 0];
142 | arrow_x = get(arrow, 'X');
143 | arrow_y = get(arrow, 'Y');
144 | p(1) = arrow_x(2);
145 | p(2) = arrow_y(2);
146 |
147 | param.Color = [0.8, 0.52, 0.98];
148 | param.FontSize = 14;
149 |
150 | FigPointLabel(p, str, 'north', param);
151 | end
152 |
153 | function OriginLabel(p, str)
154 | % 给 x 坐标轴添加标签
155 | param.Color = [0.8, 0.52, 0.98];
156 | param.FontSize = 14;
157 |
158 | FigPointLabel(p, str, 'southwest', param);
159 | end
160 |
--------------------------------------------------------------------------------
/DrawLine.m:
--------------------------------------------------------------------------------
1 | function line_obj = DrawLine(h_axi, pnt1, pnt2, varargin)
2 | %DrawLine 在图窗上绘制直线,可设置端口类型和直线类型
3 | %
4 | % Syntax: line_obj = DrawLine(h_axi, pnt1, pnt2[, param])
5 | %
6 | % Input: h_axi 坐标轴句柄
7 | % pnt1 端点1在坐标轴上的坐标
8 | % pnt2 端点2在坐标轴上的坐标
9 | % param 可选参数,要求输入参数为一个结构体,成员如下:
10 | % Type 参考值 'line', 'arrow', 'doublearrow'
11 | % Color 颜色
12 | % LineStyle 线型
13 | % LineWitdh 线宽
14 | % HeadStyle 箭头的类型
15 | %
16 | % Output: line_obj 图形对象
17 | %
18 | % Note: 自动根据直线长度调整箭头大小
19 |
20 | %% 输入参数处理
21 | n = length(varargin);
22 | if n == 0
23 | type = 'line';
24 | % type = 'arrow';
25 | % type = 'doublearrow';
26 |
27 | color = [0.8, 0.52, 0.98];
28 | line_style = '-';
29 | line_width = 0.5;
30 | head_style = 'vback2';
31 |
32 | elseif n == 1
33 | % 绘制类型
34 | if isfield(varargin{1}, 'Type')
35 | type = varargin{1}.Type;
36 | else
37 | type = 'line';
38 | end
39 |
40 | % 颜色
41 | if isfield(varargin{1}, 'Color')
42 | color = varargin{1}.Color;
43 | else
44 | color = [0.8, 0.52, 0.98];
45 | end
46 |
47 | % 线型
48 | if isfield(varargin{1}, 'LineStyle')
49 | line_style = varargin{1}.LineStyle;
50 | else
51 | line_style = '-';
52 | end
53 |
54 | % 线宽
55 | if isfield(varargin{1}, 'LineWitdh')
56 | line_width = varargin{1}.LineWitdh;
57 | else
58 | line_width = 0.5;
59 | end
60 |
61 | % 箭头类型
62 | if isfield(varargin{1}, 'HeadStyle')
63 | head_style = varargin{1}.HeadStyle;
64 | else
65 | head_style = 'vback2';
66 | end
67 |
68 | else
69 |
70 | error('Function DrawLine: 输入参数过多!')
71 |
72 | end
73 |
74 | %%
75 | fpnt1 = CoorFromAxis2Fig(h_axi, pnt1);
76 | fpnt2 = CoorFromAxis2Fig(h_axi, pnt2);
77 | line_obj = annotation(type, [fpnt1(1), fpnt2(1)], [fpnt1(2), fpnt2(2)]);
78 | line_obj.LineStyle = line_style;
79 | line_obj.LineWidth = line_width;
80 | line_obj.Color = color;
81 |
82 | line_length = sqrt(sum((fpnt1-fpnt2).^2));
83 | if line_length < 0.1
84 | head_size = line_length*0.4*(h_axi.Parent.Position(3))*72/96;
85 | elseif line_length < 0.15
86 | head_size = line_length*0.2*(h_axi.Parent.Position(3))*72/96;
87 | else
88 | head_size = 10;
89 | end
90 |
91 | head_size = min(10, head_size);
92 |
93 | if strcmp(type, 'arrow')
94 | line_obj.HeadWidth = head_size;
95 | line_obj.HeadLength = head_size;
96 | line_obj.HeadStyle = head_style;
97 | end
98 |
99 | if strcmp(type, 'doublearrow')
100 | line_obj.Head1Width = head_size;
101 | line_obj.Head2Width = head_size;
102 | line_obj.Head1Length = head_size;
103 | line_obj.Head2Length = head_size;
104 | line_obj.Head1Style = head_style;
105 | line_obj.Head2Style = head_style;
106 | end
107 |
108 | end
109 |
--------------------------------------------------------------------------------
/FigPointLabel.m:
--------------------------------------------------------------------------------
1 | function FigPointLabel(p, str, loc, varargin)
2 | %FigPointLabel - 向figure上的点添加文本说明
3 | %
4 | % Syntex: FigPointLabel(p, str, loc[, param])
5 | %
6 | % Input: p 点在figure上的坐标
7 | % str 待标注的文本
8 | % loc 文本相对点的位置, 可选值包括:
9 | % east, west, south, north, northwest, northeast, southwest, southeast
10 | % param 可选参数,要求输入参数为一个结构体,成员如下:
11 | % Color 字体的颜色
12 | % FontSize 字体大小
13 | % 若结构体未包含某项成员,则使用默认值
14 | %
15 | % Output: None
16 |
17 | %% 输入参数处理
18 | n = length(varargin);
19 | if n == 0
20 | color = [0.8, 0.52, 0.98]; % label 的默认颜色
21 | fontsize = 14; % 字体的默认大小
22 | elseif n == 1
23 | if isfield(varargin{1}, 'Color')
24 | color = varargin{1}.Color;
25 | else
26 | waring("FigPointLabel: Color设置为默认值\n");
27 | color = [0.8, 0.52, 0.98];
28 | end
29 | if isfield(varargin{1}, 'FontSize')
30 | fontsize = varargin{1}.FontSize;
31 | else
32 | fontsize = 14;
33 | waring("FigPointLabel: FontSize设置为默认值\n");
34 | end
35 | else
36 | error('FigPointLabel: 输入参数太多');
37 | end
38 |
39 | %% 在坐标轴上的指定某点添加标注
40 | ptx = p(1); pty = p(2);
41 | switch loc
42 | case 'north'
43 | label_pos = [ptx-0.05, pty-0.01, 0.1, 0.1];
44 | hAlign = 'center';
45 | vAlign = 'bottom';
46 | case 'south'
47 | label_pos = [ptx-0.05, pty-0.1, 0.1, 0.1];
48 | hAlign = 'center';
49 | vAlign = 'top';
50 | case 'east'
51 | label_pos = [ptx, pty-0.05-0.008, 0.1, 0.1];
52 | hAlign = 'left';
53 | vAlign = 'middle';
54 | case 'west'
55 | label_pos = [ptx-0.1, pty-0.05-0.008, 0.1, 0.1];
56 | hAlign = 'right';
57 | vAlign = 'middle';
58 | case 'northwest'
59 | label_pos = [ptx-0.1, pty-0.01, 0.1, 0.1];
60 | hAlign = 'right';
61 | vAlign = 'bottom';
62 | case 'northeast'
63 | label_pos = [ptx, pty-0.01, 0.1, 0.1];
64 | hAlign = 'left';
65 | vAlign = 'bottom';
66 | case 'southwest'
67 | label_pos = [ptx-0.1, pty-0.1, 0.1, 0.1];
68 | hAlign = 'right';
69 | vAlign = 'top';
70 | case 'southeast'
71 | label_pos = [ptx, pty-0.1, 0.1, 0.1];
72 | hAlign = 'left';
73 | vAlign = 'top';
74 | otherwise
75 | label_pos = [ptx-0.05, pty-0.01, 0.1, 0.1];
76 | hAlign = 'center';
77 | vAlign = 'bottom';
78 | end
79 | annotation(gcf, 'textbox', ...
80 | label_pos, ...
81 | 'Color', color, ...
82 | 'String', str, ...
83 | 'Interpreter', 'latex', ...
84 | 'FontSize', fontsize, ...
85 | 'EdgeColor', 'None', ...
86 | 'FitBoxToText', 'On', ...
87 | 'VerticalAlignment', vAlign, ...
88 | 'HorizontalAlignment', hAlign);
89 | end
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MatlabDrawNiceGraph
2 | > Hi! I am 002! Let's draw more beautiful graphics by using Matlab.
3 |
4 | 你好,我是002!创建此仓库的主要目的是使用Matlab绘制各种好看的图形。你可以根据自己的需求和喜好,复制、修改此仓库的代码。目前实现的功能有:
5 |
6 | - [MatlabDrawNiceGraph](#matlabdrawnicegraph)
7 | - [创建带箭头的坐标系](#创建带箭头的坐标系)
8 | - [在坐标轴上绘制线段、单箭头和双箭头](#在坐标轴上绘制线段单箭头和双箭头)
9 |
10 | ---
11 |
12 | ## 创建带箭头的坐标系
13 |
14 | **实现如下效果:**
15 |
16 | | |
|
|
17 | | -------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- |
18 |
19 |
22 |
23 | 以上结果分别是运行 `demo01.m`,`demo02.m`,`demo03.m` 得到的结果,其中使用到的API功能描述如下,函数实现和用法详见源码和实例。
24 |
25 | - `DrawAxisWithArrow` **自动确定**坐标原点在图窗的位置,并以此来绘制带箭头的坐标轴;
26 |
27 | - `CoorFromAxis2Fig` 进行坐标转换,将点在坐标轴(axis)上的坐标转换为在图窗(figure)的归一化坐标;
28 |
29 | - `FigPointLabel` 在图窗上的某点附近添加文字。结合函数 `CoorFromAxis2Fig`,可以很方便在 axis 上添加文字(只需知道该点在 axis 的坐标),如 `demo03` 中坐标轴上的标注均是使用此函数添加的;
30 |
31 | - `SaveFig2Img` 保存图窗;
32 |
33 | **代码实例(demo01.m)**
34 |
35 | ```matlab
36 | figure('color', [0.15, 0.15, 0.15]);
37 | x = linspace(-3, 4, 100);
38 | y = x.^2;
39 | plot(x, y, 'Color', [0,1,1], 'LineWidth', 1.5);
40 | % 调用 DrawAxisWithArrow 即可在当前坐标轴绘制带箭头坐标轴
41 | param = struct('XLabel', '$x$', 'YLabel', '$y$', 'OLabel', '$O$');
42 | DrawAxisWithArrow(gca, param);
43 | ```
44 |
45 | `demo02.py` 是测试在多坐标轴下的运行结果;`demo03.m` 相对前面两个demo实现起来代码稍微冗长繁琐一些(这是一个理想低通滤波器的单位阶跃响应)。
46 |
47 | ---
48 |
49 | ## 在坐标轴上绘制线段、单箭头和双箭头
50 |
51 | **实现如下效果**
52 |
53 | 同样是调用 `annotation` + `CoorFromAxis2Fig`(图窗和坐标轴的坐标转换)来实现,比较简单。为方便调用封装成一个 API:`DrawLine`。
54 |
55 | 运行 `demo04.m` 输出结果如下图所示。有关[直线](https://ww2.mathworks.cn/help/matlab/ref/matlab.graphics.shape.arrow-properties.html)和[箭头](https://ww2.mathworks.cn/help/matlab/ref/matlab.graphics.shape.arrow-properties.html)的属性可上官网查看。
56 |
57 |