Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MATLAB textbox in a constant position on top of spinning 3D plot?

I'm trying to have a textbox in MATLAB on a spinning plot, but I don't want the textbox to change its position relative to the figure. I thought that 'units','normalized' in the text function would do it, but it's not quite working, as the example below illustrates. I suppose I could use uicontrol but I'd like to use Greek letters and I can't get uicontrol looking quite as good as text. The following example recreates my problem. You'll notice the text box moves as the plot spins, but I'd like it to just stay in the top left region where it starts. Thank you!

part_x = rand(1000,3)-.5;                         %generate random 3D coordinates to scatter
fig1 = figure;
scatter3(part_x(:,1), part_x(:,2), part_x(:,3))
axis equal vis3d
axis([-1 1 -1 1 -1 1])
set(fig1,'color','w')

for tau = 1:150
    view(tau+20,30);                              %spin the plot
    pause(.01)
    if tau~=1; delete(tau_text); end;             %delete the previous text if it exists
    tau_text = text(.1,.7,...
                    ['\tau = ',num2str(tau)],...
                    'units','normalized',...      %text coordinates relative to figure?
                    'Margin',3,...                %these last 3 lines make it look nice
                    'edgecolor','k',...
                    'backgroundcolor','w');
end
like image 944
MountainDrew Avatar asked Sep 22 '14 18:09

MountainDrew


2 Answers

Several things:

1) As you found out - using an annotation object instead of text object is the way to go. The difference is explained very nicely here.

2) You should only create the annotation once and then modify its string instead of deleting and recreating it on every iteration.

Finally:

part_x = rand(1000,3)-.5;
fig1 = figure;
scatter3(part_x(:,1), part_x(:,2), part_x(:,3))
axis equal vis3d
axis([-1 1 -1 1 -1 1])
set(fig1,'color','w')

%// Create the text outside the loop:
tau_text = annotation('textbox',[0.2 0.8 0.1 0.05],...
                  'string','\tau = NaN',...
                  'Margin',4,... 
                  'edgecolor','k',...
                  'backgroundcolor','w',...
                  'LineWidth',1);

for tau = 1:150
    view(tau+20,30); 
    pause(.01)
    set(tau_text,'String',['\tau = ',num2str(tau)]); %// Modify the string
end

Notes:

1) It is interesting to note that @Otto's suggestion of using legend results in the creation of an axes (because this is what a legend object is - an axes with annotation children). You could then position the legend manually, and get its location using either get(gco,'position') (assuming it was the last thing you clicked) or more generally get(findobj('tag','legend'),'position'). Afterwards, whenever you create the legend, you can just set its position to the one you previously got. You could also get rid of the line\marker inside the legend by deleting the appropriate child of type line from the legend, e.g.:

ezplot('sin(x)');
hLeg = legend('\tauex\tau');
delete(findobj(findobj('Tag','legend'),'Type','line'));
hA1 = findobj(findobj('Tag','legend'),'Type','text');
set(hA1,'Position',[0.5,0.5,0],'HorizontalAlignment','center');

It is of course also possible to manipulate the legend's String using its handle (hA1) directly.

2) This post on UndocumentedMatlab discusses the behavior of annotation objects and some undocumented ways to manipulate them.

like image 191
Dev-iL Avatar answered Nov 17 '22 01:11

Dev-iL


You could use

legend(['\tau = ',num2str(tau)],'Location','NorthWestOutside')
like image 34
Otto Nahmee Avatar answered Nov 17 '22 00:11

Otto Nahmee