annotation with both "doublearrow" and "textblock", with same data units

65 visualizaciones (últimos 30 días)
Sim
Sim el 28 de Dic. de 2023
Editada: Richard el 13 de Nov. de 2024 a las 15:53
I am employing the solution proposed by @Jorg Woehl in "Specify annotation position with respect to x- and y-axes values?" to use data units inside
annotation('doublearrow',...)
Now, I would like to add the "annotation('textbox',..)" in the same position of the "annotation('doublearrow',...)", by using the same data units. Something like this:
my_position = [x_begin y_begin dx dy];
annotation('doublearrow','dim',my_position);
annotation('textbox','dim',my_position);
However, my attempt does not work:
% From: Jorg Woehl in "Specify annotation position with respect to x- and y-axes values?"
hf = figure;
x = 0:180; f = @(x) 0.09*exp(-x/18);
plot(x, f(x));
ha = annotation('doublearrow');
ha.Parent = hf.CurrentAxes; % associate annotation with current axes
% now you can use data units
ha.X = [50 20];
ha.Y = [f(20) f(20)];
% From: https://ch.mathworks.com/help/matlab/ref/annotation.html
dim = [ha.X ha.Y];
str = {'Straight Line Plot','from 1 to 10'};
annotation('textbox',dim,'String',str,'FitBoxToText','on');
Error using annotation
Position values must be between 0 and 1.
Any suggestion?

Respuesta aceptada

Hassaan
Hassaan el 28 de Dic. de 2023
Editada: Hassaan el 28 de Dic. de 2023
Same solution as pointed by @Voss [credit and special thanks goes to him] , I Just created some functions for easier access and modification.
x = 0:200;
f = @(x) 0.09*exp(-x/18);
y = f(x);
figure;
ax = gca;
plot(ax, x, y);
xStart = 20;
xEnd = 50;
txtHorizontaloffset = 1;
txtBoxXstart = (xEnd + txtHorizontaloffset);
% Add a double-arrow annotation
createDoubleArrow(ax, [xStart xEnd], [f(xStart) f(xStart)]);
% Add a text box annotation
createTextBox(ax, txtBoxXstart, f(xStart), 'Straight Line Plot from 1 to 10');
function createDoubleArrow(ax, xData, yData)
% Creates a double-arrow annotation on the given axes
% ax: Axes handle where the plot is drawn
% xData: The x-coordinates for the annotation (start and end point)
% yData: The y-coordinates for the annotation (start and end point)
% Ensure that xData and yData have two points for the double-arrow
if length(xData) ~= 2 || length(yData) ~= 2
error('xData and yData must contain exactly 2 elements each.');
end
% Draw a double-arrow annotation
doubleArrow = annotation(ax.Parent, 'doublearrow');
doubleArrow.Parent = ax; % Associate with the correct axes
doubleArrow.X = xData;
doubleArrow.Y = yData;
end
function createTextBox(ax, xPos, yPos, annotationText)
% Creates a text box annotation on the given axes
% ax: Axes handle where the plot is drawn
% xPos, yPos: The position for the annotation text box
% annotationText: The text to be displayed in the text box
% Add text at the specified location
textAnnotation = text(ax, xPos, yPos, annotationText, ...
'HorizontalAlignment', 'left', 'EdgeColor', 'k', ...
'BackgroundColor', 'white', 'Margin', 5);
end
  3 comentarios
Hassaan
Hassaan el 28 de Dic. de 2023
I am Ok with both. I personally liked the @Voss answers as well. Thanks.
Richard
Richard el 13 de Nov. de 2024 a las 15:48
Editada: Richard el 13 de Nov. de 2024 a las 15:53
Thanks for this. It helped me a lot.
Is there a way to turn the text sideways, so it would be readable from the right?
I'm using R2024a right now.
Update: Just added a this to the createTextBox-Function, just after the 'Margin',5 setting: 'Rotation',90

Iniciar sesión para comentar.

Más respuestas (3)

Voss
Voss el 28 de Dic. de 2023
% From: Jorg Woehl in "Specify annotation position with respect to x- and y-axes values?"
hf = figure;
x = 0:180; f = @(x) 0.09*exp(-x/18);
plot(x, f(x));
ha = annotation('doublearrow');
ha.Parent = hf.CurrentAxes; % associate annotation with current axes
% now you can use data units
ha.X = [50 20];
ha.Y = [f(20) f(20)];
One way is to use the text() function:
str = {'Straight Line Plot','from 1 to 10'};
text(ha.X(1),ha.Y(1),join(str,newline()), ...
'Parent',ha.Parent,'EdgeColor','k','HorizontalAlignment','left');

Hassaan
Hassaan el 28 de Dic. de 2023
Editada: Hassaan el 28 de Dic. de 2023
Each function will take care of positioning based on the given x values and will place the textbox above the double arrow. You can tinker with the values and functionality as per your needs.
% Example usage
hf = figure;
x = 0:0.1:200;
f = @(x) 0.09*exp(-x/18);
plot(x, f(x));
ax = gca;
% Call the functions to create annotations
createDoubleArrowAnnotation(ax, f, [50, 100]);
createTextboxAnnotation(ax, f, [50, 100], 'Straight Line Plot, from 50 to 100');
% Function to create a double arrow annotation
function createDoubleArrowAnnotation(ax, f, x_range)
y_start = f(x_range(1));
y_end = f(x_range(2));
% Normalize the coordinates
norm_x = normalizeCoordinate(ax, x_range);
norm_y = normalizeCoordinate(ax, [y_start, y_end], 'y');
% Create the double arrow annotation
annotation('doublearrow', norm_x, norm_y);
end
% Function to create a textbox annotation
function createTextboxAnnotation(ax, f, x_range, str)
% Calculate the midpoint of the double arrow in data units for the textbox
mid_x = mean(x_range);
mid_y = f(mid_x) + 0.1 * range(ax.YLim); % Adjust y to place the textbox above the arrow
% Normalize the coordinates
norm_mid_x = normalizeCoordinate(ax, mid_x);
norm_mid_y = normalizeCoordinate(ax, mid_y, 'y');
% Create the textbox annotation
ht = annotation('textbox', [norm_mid_x, norm_mid_y, 0.1, 0.05], 'String', str, 'FitBoxToText', 'on', 'BackgroundColor', 'white');
% Adjust the position of the textbox to center it above the arrow
ht.Position(1) = ht.Position(1) - ht.Position(3) / 2;
end
% Helper function to normalize x or y coordinates
function norm_coord = normalizeCoordinate(ax, data_coord, coord_type)
if nargin < 3
coord_type = 'x';
end
ax_lim = get(ax, [upper(coord_type) 'Lim']);
ax_pos = get(ax, 'Position');
norm_coord = (data_coord - ax_lim(1)) / diff(ax_lim);
if strcmpi(coord_type, 'x')
norm_coord = norm_coord * ax_pos(3) + ax_pos(1);
else
norm_coord = norm_coord * ax_pos(4) + ax_pos(2);
end
end
Make sure to place the createDoubleArrowAnnotation and createTextboxAnnotation functions, along with the normalizeCoordinate helper function, in the same file or in your MATLAB path. Then, you can call these functions as shown in the example usage to create your annotations. The normalizeCoordinate function is a utility to convert data coordinates to normalized figure coordinates, which is used by both annotation-creating functions.
------------------------------------------------------------------------------------------------------------------------------------------------
If you find the solution helpful and it resolves your issue, it would be greatly appreciated if you could accept the answer. Also, leaving an upvote and a comment are also wonderful ways to provide feedback.

Hassaan
Hassaan el 28 de Dic. de 2023
% Example usage
hf = figure;
x = 0:0.1:200;
f = @(x) 0.09*exp(-x/18);
plot(x, f(x));
ax = gca;
% Define the y values for the annotations
y_values = [f(20), f(20)];
% Call the functions to create annotations
createDoubleArrowAnnotation(ax, [50, 20], y_values);
createTextboxAnnotation(ax, [50, 20], y_values, 'Straight Line Plot, from 50 to 100');
% Function to create a double arrow annotation with specified x and y values
function createDoubleArrowAnnotation(ax, x_range, y_range)
% Normalize the coordinates
norm_x = normalizeCoordinate(ax, x_range, 'x');
norm_y = normalizeCoordinate(ax, y_range, 'y');
% Create the double arrow annotation
annotation('doublearrow', norm_x, norm_y);
end
% Function to create a textbox annotation with specified x and y values
function createTextboxAnnotation(ax, x_range, y_range, str)
% Calculate the midpoint of the double arrow in data units for the textbox
mid_x = mean(x_range);
mid_y = mean(y_range) + 0.1 * range(ax.YLim); % Adjust y to place the textbox above the arrow
% Normalize the coordinates
norm_mid_x = normalizeCoordinate(ax, mid_x, 'x');
norm_mid_y = normalizeCoordinate(ax, mid_y, 'y') + 0.002; % Adjust this value as needed to offset above the arrow
% Create the textbox annotation
ht = annotation('textbox', [norm_mid_x - 0.002, norm_mid_y, 0.1, 0.002], 'String', str, 'FitBoxToText', 'on', 'BackgroundColor', 'white');
% Adjust the position of the textbox to center it above the arrow
ht.Position(1) = ht.Position(1) - ht.Position(3) / 2;
ht.Position(2) = norm_mid_y; % Align top of textbox with midpoint y
end
% Helper function to normalize x or y coordinates
function norm_coord = normalizeCoordinate(ax, data_coord, coord_type)
ax_lim = get(ax, [upper(coord_type) 'Lim']);
ax_pos = get(ax, 'Position');
if strcmpi(coord_type, 'x')
norm_coord = (data_coord - ax_lim(1)) / diff(ax_lim) * ax_pos(3) + ax_pos(1);
else
norm_coord = (data_coord - ax_lim(1)) / diff(ax_lim) * ax_pos(4) + ax_pos(2);
end
end
------------------------------------------------------------------------------------------------------------------------------------------------
If you find the solution helpful and it resolves your issue, it would be greatly appreciated if you could accept the answer. Also, leaving an upvote and a comment are also wonderful ways to provide feedback.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by