annotation with both "doublearrow" and "textblock", with same data units
63 次查看(过去 30 天)
显示 更早的评论
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');
Any suggestion?
0 个评论
采纳的回答
Hassaan
2023-12-28
编辑:Hassaan
2023-12-28
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 个评论
Richard
2024-11-13,15:48
编辑:Richard
2024-11-13,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
更多回答(3 个)
Voss
2023-12-28
% 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');
0 个评论
Hassaan
2023-12-28
编辑:Hassaan
2023-12-28
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.
0 个评论
Hassaan
2023-12-28
% 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.
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Annotations 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!