避免MATLAB图形中的文本重叠问题

8
当使用 text(x,y,'label') 在 MATLAB 图形中以编程方式插入文本时,我经常发现文本块重叠,使它们难以阅读。我想知道是否有任何自动方式来偏移文本块,使它们不会重叠。例如,如果我在点(0,0),(0.01,0)和(0.02,0)处添加了三个顶部左对齐的标签,那么我希望它们重新定位为:
. . .
label1
  label2
    label3

而目前它们看起来像:

. . .
la~~~~~~l3

当波浪线重叠时,它们变得难以阅读。

如果还没有一种方法来解决这个问题,我可以为此编写自己的算法/启发式方法,但是否有一种方法可以查询一个图形(或句柄)上所有现有文本框的边界框?然后,每次我想放置标签时都可以调用它?

谢谢!


你不必亲自去做。这里讨论了一个处理文本定位的工具:http://blogs.mathworks.com/pick/2009/01/02/automatic-text-placement/ 文件交换的直接链接为: http://www.mathworks.com/matlabcentral/fileexchange/11466 即使你想要自己动手,这也是一个很好的起点。希望有所帮助。 Darren - Darren Rowland
这看起来很不错!我正在寻找一种将文本放置在给定点附近的方法,因此这不是一个开箱即用的解决方案,但确实是一个很好的起点。在接受之前,我会等待看看是否有其他人知道更多功能强大的解决方案,但还是谢谢! - btown
1个回答

6

我想到了一个解决方案……看起来工作得还不错。

function h = textfit(x,y,txt,varargin)
% textfit(x,y,txt,varargin)
%
% Mike Lawrence 2011

ythresh = 0.4;  % maximal allowable overlap (includes cell padding accounted for in "extent" property)
xthresh = 0.1;

n = length(x);
if ~iscell(txt), txt={txt}; end
if length(y)~=n || length(txt)~=n, error('length mismatch between x,y,txt'); end

h = text(x,y,txt,varargin{:});

yl=ylim; ytot=diff(yl);
xl=xlim; xtot=diff(xl);

maxtries = 100;
for t=1:maxtries
  ext = nan(n,4);
  for i=1:n, ext(i,:) = get(h(i),'extent'); end
  xstart=ext(:,1); xsz=ext(:,3); xend=xstart+xsz;
  ystart=ext(:,2); ysz=ext(:,4); yend=ystart+ysz;
  overlapx = zeros(n,n);
  overlapy = zeros(n,n);
  for i1=1:n-1, for i2=i1+1:n
    if xstart(i1)<=xend(i2)&xstart(i2)<=xend(i1)
      overlapx(i1,i2)=(min(xend(i2)-xstart(i1),xend(i1)-xstart(i2)))/(min(xsz(i1),xsz(i2)));
    end
    if ystart(i1)<=yend(i2)&ystart(i2)<=yend(i1)
      overlapy(i1,i2)=(min(yend(i2)-ystart(i1),yend(i1)-ystart(i2)))/(min(ysz(i1),ysz(i2)));
    end
  end,end
  overlapmax = max(overlapx,overlapy);
  ov = (overlapx>xthresh & overlapy>ythresh);
  [o1 o2] = find(ov);
  if isempty(o1), break; end
  [tmp ord] = sort(overlapmax(find(ov)));
  o1=o1(ord); o2=o2(ord);
  moved = false(n,1);
  for i=1:length(o1), i1=o1(i); i2=o2(i);
    if moved(i1) || moved(i2), continue; end
    pos1 = get(h(i1),'position');
    pos2 = get(h(i2),'position');
    oy = overlapy(i1,i2)*min(ysz(i1),ysz(i2));
    ox = overlapx(i1,i2)*min(xsz(i1),xsz(i2));
    if oy/ytot < ox/xtot   % overlapy is easier to fix
      shift = 0.5*(1-ythresh)*oy;
      if ystart(i1)<ystart(i2)  % i1 above i2
        pos1(2)=pos1(2)-shift; pos2(2)=pos2(2)+shift;
      else                      % i1 below i2
        pos1(2)=pos1(2)+shift; pos2(2)=pos2(2)-shift;
      end
    else                                 % overlapx is easier to fix
      shift = 0.5*(1-xthresh)*ox;
      if xstart(i1)<xstart(i2)  % i1 left of i2
        pos1(1)=pos1(1)-shift; pos2(1)=pos2(1)+shift;
      else                      % i1 right of i2
        pos1(1)=pos1(1)+shift; pos2(1)=pos2(1)-shift;
      end
    end
    set(h(i1),'position',pos1);
    set(h(i2),'position',pos2);
    moved([i1 i2]) = true;
  end
end

if nargout==0, clear h, end

这太棒了!而且在15b中仍然有效。唯一的烦恼是有些标签会出现在轴外面,但它运行良好。感谢分享。 - Matteo Ferla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接