matlab subplot 的边距(with tight margins)

matlab subplot的边距问题

在matlab中使用subplot画出的图像的边距比较,因此,不管是在存为位图图像还是矢量图像的时候,这样的边距对后期结果的影响都比较麻烦。因此在网上找到了如下的解决方案:

  1. 使用subplot_tight函数。
  2. 使用set(gca, 'LooseInset', get(gca,'TightInset')), from here.

一些来源及参考:

  1. Figure margins, subplot spacings, and more… » File Exchange Pick of the Week - MATLAB & Simulink
  2. matlab控制图像的边界(margin),subplot的间距(gap)_再干杨超越的博客-CSDN博客
  3. How to reduce the borders around subplots in matlab?

新的解决方案

但是这些都不是很方便,使用subplot_tight时,需要对Axes的句柄进行管理,而我在画图的时候,很多是时候并不需要其够本。而使用LooseInset则每次都需要在自己的代码里重复这一句,很麻烦。

因此,写了如下的代码:文件名:tsubplot

%=============================================================================
%     FileName: tsubplot.m
%         Desc: like subplot, but with the margin and gap being very small
%       Author: Troy Daniel
%        Email: Troy_Daniel@163.com
%     HomePage: https://www.cnblogs.com/troy-daniel
%      Version: 0.0.2
%   LastChange: 2021-06-14 19:18:53
%      History:
% Ver 0.0.1     2021-06-14
%				Initial delivery
% Ver 0.0.2     2021-06-14
% 				Return the Axes, if the bounding box are very close to the desired one
%=============================================================================
function h = tsubplot(varargin)
	% Ver 0.0.1
	%  +---------+---------+---------+
	%  |    1    |     2   |    3    |
	%  +---------+---------+---------+
	%  |    4    |     5   |    6    |
	%  +---------+---------+---------+
	%  |    7    |     8   |    9    |
	%  +---------+---------+---------+
    if nargin >= 3, nRow = varargin{1}, nCol = varargin{2}, nIndex = varargin{3}; end
	if nargin == 2, error("Calling with two input args is not supported"), end
	if nargin == 1
		if varargin{1} < 100 || varargin{1} > 999
			error("Invaild calling with one parameters");
		end
		nRow = floor(varargin{1} / 100);
		nCol = floor(mod(varargin{1}, 100) / 10);
		nIndex = mod(varargin{1}, 10);
		if nIndex > (nRow * nCol)
			error("Invaild calling with one parameters");
		end
	end

	margin = 0.01;
	gap = 0.01;
	%     +------------------------------------------------------------------+
	%     |          margin                           margin                 |
	%     | m +------------------------+        +------------------------+ m |     +
	%     | a |         1              |   gap  |          2             | a |     | h
	%     | r +------------------------+        +------------------------+ r |     +
	%     | g      gap                                 gap                 g |
	%     | i +------------------------+        +------------------------+ i |
	%     | n |         3              |        |          4             | n |
	%     |   +------------------------+        +------------------------+   |
	%     |          margin                           margin                 |
	%     +------------------------------------------------------------------+
	%         +------------------------+
	%              w
	w = (1-margin * 2 - gap * (nCol - 1)) / nCol;
	h = (1-margin * 2 - gap * (nRow - 1)) / nRow;

	cols = mod(nIndex-1, nCol) + 1;
	colMin = min(cols);
	colSpan = max(cols) - colMin + 1;
	% colMax = max(cols);
	rows = floor((nIndex-1)/nCol) + 1;
	rowMin = min(rows);
	rowSpan = max(rows) - rowMin + 1;
	rowMax = max(rows);

	outPosition =  [margin + (colMin-1) * (w + gap), ...
			margin + (nRow - rowMax) * (h + gap), ...
			w * colSpan + gap * (colSpan - 1), ...
			h * rowSpan + gap * (rowSpan - 1)];
	% h = axes('Units','normalized', ...
	% 	'OuterPosition', [margin + (colMin-1) * (w + gap), ...
	% 		margin + (nRow - rowMax) * (h + gap), ...
	% 		w * colSpan + gap * (colSpan - 1), ...
	% 		h * rowSpan + gap * (rowSpan - 1)]);

	% remove axes that was covered by this axis
	tolerance = 0.01;
	outRect = [outPosition(1:2) - tolerance, outPosition(1:2) + outPosition(3:4) + tolerance];
	fig = gcf;
	nLength = length(fig.Children);
	for idx = nLength:-1:1
		hAxes = fig.Children(idx);
		if class(hAxes) == "matlab.graphics.axis.Axes"
			%  if the bounding box differ no more than tolerance, treat it as the desired axes
			if all(abs(hAxes.OuterPosition(1:2)- outPosition(1:2)) < tolerance) && all(abs(hAxes.OuterPosition(3:4) + hAxes.OuterPosition(1:2) - (outPosition(3:4) + outPosition(1:2)))< tolerance) 
                axes(hAxes); % make this the current active one
				h = hAxes;
				return;
			end
			if all(hAxes.Position(1:2)> outRect(1:2)) && all(hAxes.Position(3:4) + hAxes.Position(1:2) < outRect(3:4))
				delete(hAxes);
			end
		end
	end
	h = axes('Units','normalized', 'OuterPosition', outPosition);
    set(h,'LooseInset',get(h,'TightInset'));   % Please refer to: https://undocumentedmatlab.com/articles/axes-looseinset-property
end

这个函数在使用的时候与matlab自带的subplot基本类似:

t = 0:0.1:10;
tsubplot(211);
plot(t, sin(t), '-r');
tsubplot(2,2,3);
plot(t, cos(t), '--b');
tsubplot(2,2,4);
plot(sin(2*t), cos(3*t), '-b');

% add again, draw on the first Axes
tsubplot(2,1,1);
hold on;
t = 0: 1 : 10; 
stem(t, sin(t), 'm');

结果如下:

当然,要修改margin与gap,直接在函数文件里修改即可。由于自用,就没有进一步封装了。

posted @ 2021-06-16 17:44  Troy_Daniel  阅读(832)  评论(0编辑  收藏  举报