matlab: putting a circled number onto a graph

2020-06-18 09:49发布

I want to put a circled number on a graph as a marker near (but not on) a point. Sounds easy, but I also want to be invariant of zoom/aspect ratio changes.

Because of this invariant, I can't draw a circle as a line object (without redrawing it upon rescale); if I use a circle marker, I'd have to adjust its offset upon rescale.

The simplest approach I can think of is to use the Unicode or Wingdings characters ① ② ③ etc. in a string for the text() function. But unicode doesn't seem to work right, and the following sample only works with ① and not for the other numbers (which yield rectangle boxes):

works:

clf; text(0.5,0.5,char(129),'FontName','WingDings')

doesn't work (should be a circled 2):

clf; text(0.5,0.5,char(130),'FontName','WingDings')

What gives, and can anyone suggest a workaround?

2条回答
迷人小祖宗
2楼-- · 2020-06-18 10:07

This seems to work for me, uses Matlab's latex interpreter, and \textcircled:

clf; text(0.5, 0.5, '$\textcircled{2}$', 'Interpreter', 'latex')

The \textcircled command seems have some offset problems, maybe you can try to improve the used latex command and let us know :)

Following the above link, for example, I get better results with:

clf; text(0.5, 0.5, '$\raisebox{.5pt}{\textcircled{\raisebox{-.9pt} {2}}}$', 'Interpreter', 'latex')

Still, two digit numbers look awful.

查看更多
SAY GOODBYE
3楼-- · 2020-06-18 10:15

Here is an example where the markers (text+circles) are invariant to zoom/resize:

%# some graph in 2D
[adj,XY] = bucky;
N = 30;
adj = adj(1:N,1:N);
XY = XY(1:N,1:2);

%# plot edges
[xx yy] = gplot(adj, XY);
hFig = figure(); axis equal
line(xx, yy, 'LineStyle','-', 'Color','b', 'Marker','s', 'MarkerFaceColor','g')

%# draw text near vertices
xoff = 0; yoff = 0;     %# optional offsets
str = strtrim(cellstr(num2str((1:N)')));
hTxt = text(XY(:,1)+xoff, XY(:,2)+yoff, str, ...
    'FontSize',12, 'FontWeight','bold', ...
    'HorizontalAlign','right', 'VerticalAlign','bottom');

%# draw circles around text
e = cell2mat(get(hTxt, {'Extent'}));
p = e(:,1:2) + e(:,3:4)./2;
hLine = line('XData',p(:,1), 'YData',p(:,2), ...
    'LineStyle','none', 'Marker','o', 'MarkerSize',18, ...
    'MarkerFaceColor','none', 'MarkerEdgeColor','k');

%# link circles position to text (on zoom and figure resize)
callbackFcn = @(o,e) set(hLine, ...
    'XData',cellfun(@(x)x(1)+x(3)/2,get(hTxt,{'Extent'})), ...
    'YData',cellfun(@(x)x(2)+x(4)/2,get(hTxt,{'Extent'})) );
set(zoom(hFig), 'ActionPostCallback',callbackFcn)
set(hFig, 'ResizeFcn',callbackFcn)

screenshot

Compare against the LaTeX-based solution that @catchmeifyoutry proposed (pay attention to the two-digits numbers):

%# use LaTeX to draw circled text at vertices
%#str = num2str((1:N)', '$\\textcircled{%d}$');
str = num2str((1:N)', '$\\raisebox{.5pt}{\\textcircled{\\raisebox{-.9pt} {%d}}}$');
text(XY(:,1), XY(:,2), str, ...
    'HorizontalAlign','right', 'VerticalAlign','bottom', ...
    'Interpreter','latex', 'FontSize',18)

screenshot_latex

查看更多
登录 后发表回答