How to wrap strings when plotting with `text`? - matlab

I have a long string that I would like to add to a subplot as descriptive text.
description = 'This kitchen has white cabinets and two blue chairs. The upper cabinet has a black microwave. The paper towels are above the trash can. There is a black garbage can just on the left of the blue chair. On its left there is a red fire distinguisher.';
I have tried to add new line characters after every sentence to make it fit better.
subplot(1,2,2);
with_new_lines = regexprep(description, '\.', '\.\n');
text( 0.5, 0.5, with_new_lines, 'FontSize', 14', 'FontWeight', 'Bold', ...
'HorizontalAlignment', 'Center', 'VerticalAlignment', 'middle' ) ;
But it still does not fit properly within the axis.
Is there a way to wrap the string dynamically to fit the subplot?

How about using an annotate box, with the FitBoxToText property off?
description = 'This kitchen has white cabinets and two blue chairs. The upper cabinet has a black microwave. The paper towels are above the trash can. There is a black garbage can just on the left of the blue chair. On its left there is a red fire distinguisher.';
figure;subH=subplot(1,2,2);
pos=get(subH,'Position');
annotation('textbox', pos,...
'String', description,...
'FitBoxToText','off');
You can change the location by changing the 1st two elements of pos ,which (I think) describe the left-bottom corner, but forget.

You could use the textwrap function in one of two ways:
Wrap the text to fit within a text uicontrol:
hText = uicontrol('Style', 'Text', 'Position', ...(some starting position)... );
[wrappedText, newPosition] = textwrap(hText, {description});
set(hText, 'String', wrappedText, 'Position', newPosition);
Wrap the text at a fixed number of columns before plotting with text:
wrappedText = textwrap({description}, 20);
text(0.5, 0.5, wrappedText, 'FontSize', 14', 'FontWeight', 'Bold', ...
'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle');

Related

Matlab - Add a specific tick on a colorbar

I'm representing a surface using "surf" function, with a colorbar. I would like to keep the default ticks of the colorbar, but add a custom tick on this colorbar, at a specific value (that I could make red to distinguish it from other ticks for example). Any idea on how to add a custom tick like that with keeping existing ticks on the colorbar ?
Thanks
As Luis mentioned in the comments, you can add an additional tick mark like so
h = colorbar;
newTick = 0.75;
h.Ticks = sort([h.Ticks newTick]);
If you want to add a line to the bar, the easiest thing (I think) is to use an annotation which is positioned relative to the figure (the same as the colorbar), so we can overlay it
pos = h.Position;
r = (newTick - min(h.Ticks))/(max(h.Ticks)-min(h.Ticks));
annotation( 'line', pos(1)+[0, pos(3)], [1, 1]*(pos(2)+pos(4)*r), ...
'color', [1,0,0], 'linewidth', 2 );
I'm setting the x position of the annotation to match the left and right sides of the colorbar, and the y position to match the bottom plus the relative % of the height according to the tick value.
Result:
Similarly, you could use annotatation exclusively to just get a red label, it's a little more convoluted to get everything lined up correctly, you have to make sure the text box is wide enough to be on a single line and vertically aligned to the middle to get the position right:
h = colorbar;
newTick = 0.75;
pos = h.Position;
r = (newTick - min(h.Ticks))/(max(h.Ticks)-min(h.Ticks));
h = 0.2;
annotation( 'textbox', [pos(1)+pos(3)/2, (pos(2)+pos(4)*r)-(h/2), pos(3)*2, h], ...
'color', [1,0,0], 'string', ['- ' num2str(newTick)], 'linestyle', 'none', ...
'VerticalAlignment', 'middle' );

Add complete 6 borders for 3D figure

I use surf to plot 3D surface, and I try to add borders using "box on", but it can only show 3 borders. see
However, What I really want is to add all 6 borders for the cube, like this
.
Could anyone tell me how to do that?
You need to change the axes BoxStyle to 'full', with the Box on. For example:
[x,y] = meshgrid( 0:0.1:6, 0:0.1:6 );
surf( x, y, cos(x)+sin(y), 'LineStyle', 'none' );
set( gca, 'Box', 'on', 'BoxStyle', 'full' );

Matlab textbox alpha does not adjust all background color

I have a very simple script that plots some random stuff and puts a textbox with background color. I am attempting to change the transparency of the background so that the plot shows through.
I have the following code:
x = rand(10);
plot(sin(x))
a = annotation('textbox', [0.5 0.5 0.1 0.1], 'String', 'Some Random Text');
set(a, 'BackgroundColor', [.7 .9 .7]);
set(a, 'FaceAlpha', 0.5);
And it results in an image like this:
So obviously the transparency has worked because part of the background colour is transparent.
Why is all of it not transparent? Have I done something wrong here?
Update: Mathworks confirmed that it probably is a bug which might be fixed in 2014b (to be released in July 2014). A temporary workaround is:
plot(sin(rand(10)))
a = annotation('textbox', [0.5 0.5 0.1 0.1], 'String', 'Some Random Text');
b = annotation('textbox', get(a,'Position'));
set(b, 'BackgroundColor', [0 0.5 0]);
set(b, 'FaceAlpha', 1);
uistack(a,'top')
One annotation for the text and below another for the background color.
It might be a Matlab bug actually. The documentation about annotations says:
FaceAlpha
Scalar alpha value in range [0 1] Transparency of object background.
Defines the degree to which the object's background color is
transparent. A value of 1 (the default) makes the background opaque, a
value of 0 makes the background completely transparent (that is,
invisible). The default value is 1.
I would conclude that the whole background should be affected but I can confirm that this is not the case also here (Matlab 2012b). I might file a bug report with them.
For a temporary fix, set the backgroundcolor as bright as possible ([0.9, 0.9, 0.9] for example) then one doesn't see the effect immediately.

Make background of annotation box in image semi-transparent

I am currently working on adding annotations to satellite images in MATLAB. Since the color underneath each text field can vary quite a lot, I want to use a background color under the text to make it easier to see and read.
However, when I do this, a lot of the terrain gets obscured. I though of trying to make the background color for each text box semi transparent, but hit a dead end trying to come up with a solution.
Any ideas? I was hoping for some UI-element where I could just set the 'facealpha' to maybe 0.5. I also need the text to support being rotated (as can be seen in the examples below).
Below is some example code and the resulting image. The workspace with the satellite data can also be found in the link:
Example workspace
figure(1);clf
imagesc(xx,yy,Map);
hold on
plot(xInspection,yInspection,'g.-')
% # Two ways of making a rotated text annotation.
% # Cant make background semi-transparent
testAnno= annotation('textarrow',[0.5 0.5],[0.5 0.5], ...
'string','textarrow annotation', ...
'HeadStyle','none','LineStyle', 'none',...
'TextRotation',asin(directionVec(1))*180/pi,...
'TextBackgroundColor',[0.7 0.7 0.7]);
testText = text(mean(xInspection),mean(yInspection),'text annotation', ...
'rotation',asin(directionVec(1))*180/pi, ...
'HorizontalAlignment','right', ...
'color',[0 0 0], ...
'backgroundcolor',[0.7 0.7 0.7], ...
'fontsize',8);
It doesn't look like either annotation or text return HgObjects that have BackgroundAlpha properties (they might exist but I wasn't able to find them using getundoc or by trying various different hacks).
I was able to get something working by drawing the background myself. Here is a simple proof of concept:
f = figure;
tObj = text(.5, .5, 'text object', 'FontSize', 20);
set(gca,'XLimMode', 'manual', 'YLimMode', 'manual'); % prevent the axes from resizing automatically
p = get(tObj, 'Extent'); %Get the outer position of the text
% now create a patch around the text object
pObj = patch([p(1) p(1) p(1)+p(3) p(1)+p(3)], [p(2) p(2)+p(4) p(2)+p(4) p(2)], 'r');
uistack(tObj, 'top'); % put the text object on top of the patch object
set(pObj , 'FaceAlpha', .2); % set the alpha of the patch face to .2
%Rotate the objects
set(tObj, 'Rotation', 20);
rotate(pObj, [0 0 1], 20);
I am afraid the only way you can do this is by not setting any color to your annotations, and then placing a patch in the background of each annotation. So something like this:
% Use completely transparent annotations
hA = annotation('textarrow', ..., 'TextBackgroundColor', 'none')
% Place a transparent patch exactly in the background of your annotation
hP = patch(X, Y, 'white', 'EdgeColor', 'none', 'FaceColor', 'white', ...
'alpha', 0.3)
% Ensure that your annotation is on top
uistack(hA, 'top')
But of course the big problem is to determine the correct coordinates of the patch (X and Y). Rotating is easy by simply multiplying your coordinates by a rotation matrix. However, finding the length and height of the patch and its central location is not that easy. You might be able to find some useful functions for this at Matlab central...

RTL msgbox in Matlab

I'm trying to present a msgbox in MATLAB which uses horizontal text alignment 'right'.
Problem is when I'm changing the text alignment, the message text appears out of the box.
h = msgbox('Sample Text');
th = findall(0, 'Tag','MessageBox' );
set(th, 'HorizontalAlignment', 'right');
Does anyone know to present the user with right-to-left message from Matlab?
The message string in the message box is actually created using the text function, i.e., it is positioned by two coordinates (neglecting the z-coordinate). To position it with the alignment right, you'll need to get the position of the message box and use its width argument to define the x position of the message text:
h = msgbox('Sample Text');
th = findall(0, 'Tag','MessageBox' );
boxPosition = get(h,'position');
textPosition = get(th, 'position');
set(th, 'position', [boxPosition(3) textPosition(2) textPosition(3)]);
set(th, 'HorizontalAlignment', 'right');
Since this puts your text exactly to the right border of the box, you'll need to adjust the text slightly to the left:
set(th, 'position', [boxPosition(3).*0.95 textPosition(2) textPosition(3)]);