How I can draw the graph of three equations (x=x(u,v,w), y=y(u,v,w), z=z(u,v,w)) involving three parameters using Matlab? - matlab-figure

I have got three equations involving three parameters
x=u*cos(2*pi*v), y=u*sin(2*pi*v), z=sqrt(1-u^2)*(2*w-1),
where u, v, w belong to [0,1].
How can I draw the graph of above equations using matlab?
I have tried three nested for loops, but it's really time taking. The graph obtained in this way consists of dots and its quality is not so good.
Is there any other way to draw the graph of these equations in Matlab?

You don't need a loop to create the matrix for the calculations. Below is an example for creating the matrices and also plotting. It might not be exactly what you are looking for, but it should get you close.
% set up values to calc for for u,v,w in [0,1]
stepsize = 0.1;
u = 0:stepsize:1; % min, step, max
v = 0:stepsize:1;
w = 0:stepsize:1;
% now set up combined tables
u = u';
v = v';
w = w';
uv = [repmat(u, length(v),1), repmat(v, length(u),1)];
uw = [repmat(u, length(w),1), repmat(w, length(u),1)];
% now do calcs
% note u-vector is uv(:,1) or uw(:,1), depending upon the combo, etc.
x = uv(:,1) .* cos(2 * pi * uv(:,2));
y = uv(:,1) .* sin(2 * pi * uv(:,2));
z = sqrt(1 - uw(:,1) .^2) .* (2 * uw(:,2) -1);
% it's not clear what you want to plot, but here are some examples
figure
hold on
subplot(4,1,1)
plot(x, y, 'Color', 'green', 'DisplayName', 'XY');
box on
title('Your Title Here', 'FontSize', 10)
xlabel('X', 'FontSize', 8)
ylabel('Y', 'FontSize', 8)
set(legend, 'Location', 'best')
subplot(4,1,2)
plot(x, z, 'Color', 'blue', 'DisplayName', 'XZ');
box on
title('Your Title Here', 'FontSize', 10)
xlabel('X', 'FontSize', 8)
ylabel('Z', 'FontSize', 8)
set(legend, 'Location', 'best')
subplot(4,1,3)
plot(y, z, 'Color', 'red', 'DisplayName', 'YZ');
box on
title('Your Title Here', 'FontSize', 10)
xlabel('Y', 'FontSize', 8)
ylabel('Z', 'FontSize', 8)
set(legend, 'Location', 'best')
subplot(4,1,4)
plot3(x, y, z, 'Color', 'magenta', 'DisplayName', 'XYZ');
box on
grid on
ax = gca;
ax.GridAlpha = 0.5;
title('Your Title Here', 'FontSize', 10)
xlabel('X', 'FontSize', 8)
ylabel('Y', 'FontSize', 8)
zlabel('Y', 'FontSize', 8)
set(legend, 'Location', 'best')
The above produces this figure:

Related

Get an image of a text with optimized font size and centering in Matlab?

I have a string chain of characters that I would like to display as big as possible within a rectangle frame, in a centered way. I know :
how many characters maximum can have my input
the dimensions of the rectangle
It has to :
find the best font size and displays the result.
Here is the MATLAB code
color = 'k';
txt = '1';
howManyCharMaximum = 7;
boxWidth = 250;
boxHeight = 100;
%% comput: Now I assume one char is as wide as tall
howManyChar = strlength(txt);
marginHoriz = mod(boxWidth,howManyCharMaximum); %in points
subRectangle.width = (boxWidth-marginHoriz)/howManyCharMaximum;
subRectangle.height = boxHeight;
[fontSize,idx] = min([subRectangle.width, subRectangle.height]); %the largest square that fits in a rectangle
%%
hFigure = figure('MenuBar', 'none', ...
'ToolBar', 'none', ...
'Units', 'points', ...
'Position', [0 0 boxWidth boxHeight], ... % x y from bottom left of screen to botleft of the fig
'Color', 'w');
hAxes = axes; hAxes.Visible = 'off';
%pos:=botleft vertex of the string
switch(idx)
case 1
x = floor((boxWidth-howManyChar*fontSize)/2);
y = floor((boxHeight-fontSize)/2);
case 2
addMarginHoriz = (subRectangle.width-subRectangle.height)*howManyCharMaximum;
x = floor((boxWidth-howManyChar*fontSize)/2);
y = 0;
end
hText = text(x, y, ...
txt, ...
'Units', 'points', ...
'FontSize', fontSize, ...
'HorizontalAlignment', 'left', ...
'VerticalAlignment', 'middle', ...
'Color', color);
But for some reasons I can't figure out, this is what it returns unfortunately -- a decentered character:
Would anyone know where I did a mistake pleaase ? By thanking you in advance.
I used normalized units for text as its lot easier to find the center and then it worked with the proper alignment. Note that a slight offset will still exist because actual figure grid has more space on left then right and at bottom then top. You can experimentally adjust it if you wish
color = 'k';
txt = '18998';
%howManyCharMaximum = 7; I didnt use this one
boxWidth = 250;
boxHeight = 100;
%% comput: Now I assume one char is as wide as tall
howManyChar = strlength(txt);
%marginHoriz = mod(boxWidth,howManyCharMaximum); %in points
subRectangle.width = (boxWidth)/howManyChar;
subRectangle.height = boxHeight;
[fontSize,idx] = min([subRectangle.width, subRectangle.height]); %the largest square that fits in a rectangle
%%
hFigure = figure('MenuBar', 'none', ...
'ToolBar', 'none', ...
'Units', 'points', ...
'Position', [0 0 boxWidth boxHeight], ... % x y from bottom left of screen to botleft of the fig
'Color', 'w');
hAxes = axes; hAxes.Visible = 'off';
%plot(0,0)
%pos:=botleft vertex of the string
x = floor(boxWidth/2);
y = floor(boxHeight/2)
hText = text(0.5, 0.5, ...
txt, ...
'Units', 'normalized', ...
'FontSize', fontSize, ...
'HorizontalAlignment', 'center', ...
'VerticalAlignment', 'middle', ...
'Color', color);

How to code a slider in Octave to have interactive plot?

my target is to have a plot that shows Stochastic oscillator on forex market, and in order to validate which parameter is the best one to setup it, I would use a slider to modify it and show updated result on plot.
I have my historical data, for a defined pair (let say AUDUSD) and after loading it, I calculate Stocastic oscillator:
function [stoch, fk, dk] = stochastic(n, k, d)
X=csvread("AUDUSD_2017.csv");
C=X(2:length(X),5);
L=X(2:length(X),4);
H=X(2:length(X),3);
O=X(2:length(X),2);
for m=n:length(C)-n
stoch(m)=((C(m)-min(L(m-n+1:m)))/(max(H(m-n+1:m))-min(L(m-n+1:m))))*100;
endfor
for m=n:length(C)-n
fk(m)=mean(stoch(m-d:m));
endfor
for m=n:length(C)-n
dk(m)=mean(fk(m-d:m));
endfor
endfunction
This is a picture of what I have when I plot stoch, fk and dk:
I would add 3 sliders to the figure in order to change, in a range, parameters as input, so i.e. to have a slider that changes first parameter "n" between 3 and 50, "k" between 2 and 20, and "d" between 2 and 20.
I would use UI package in octave, can someone address me to have a plot updated when I use sliders?
Francesco
Have a look at this demo which will give you an window like that which should answer all your questions:
The relevant parts for your specific questions are:
h.noise_slider = uicontrol ("style", "slider",
"units", "normalized",
"string", "slider",
"callback", #update_plot,
"value", 0.4,
"position", [0.05 0.25 0.35 0.06]);
....
noise = get (h.noise_slider, "value");
Be sure to use the Qt toolkit!
Andy pointed out in the comments that the example I linked to doesn't work on octave out of the box; this is because Octave doesn't like nested functions for certain things for the time being, so I've reproduced an 'octave version' below.
%%%%%% In file myplot.m %%%%%
function myplot
%% Create initial figure and spiral plot
figure; axes ('position', [0.1, 0.3, 0.8, 0.6]);
global t; t = linspace (0, 8*pi, 100);
x = t .* cos(t); y = t .* sin(t);
plot (x, y); axis ([-100, 100, -100, 100]);
%% Add ui 'slider' element
hslider = uicontrol ( ...
'style', 'slider', ...
'Units', 'normalized', ...
'position', [0.1, 0.1, 0.8, 0.1], ...
'min', 1, ...
'max', 50, ...
'value', 10, ...
'callback', {#plotstuff} ...
);
end
%% Callback function called by slider event
%% Also in file myplot.m (i.e. a subfunction)
function plotstuff (h, event)
global t;
n = get (h, 'value');
x = n * t .* cos(t); y = n * t .* sin(t);
plot (x, y); axis ([-100, 100, -100, 100]);
end

matlab plot graph of data over an image

What I would like to do is plot an image of a graph (from say a pdf file or a scanned image). Next, I would like to overlay an axis on the graph in the image, and then plot data on that axis (over the image).
Using imtool, I know the coordinates of the graph in the image (x range = ~52-355 pixels, and y range = 23(top) - 262(bottom) pixels in this case).
This is what I have tried:
I = imread('C:\MATLAB\R2014a\help\images\ref\ftrans2_fig.png');
I = squeeze(uint8(mean(I,3)));
figure, imshow(I)
[rows, cols] = size(I);
x_data = (-1 : .01 : +1)';
y_data = 1 - x_data.^2;
h1 = axes('Position',([52, 23, 355-52, 262-23] ./ [cols, rows, cols, rows] ));
set(h1, 'Color', 'none')
hold on
plot(x_data, y_data, '-rx')
Question: Knowing the pixel coordinates of the graph in the image, how do I determine the proper position of the axis in the figure, (my code fails to account for the actual size of the figure box, the gray border around the image). I have to do this for several images and sets of data, so I would like an automated method, assuming I find the coordinates of the graphs in the image ahead of time.
Thanks for your reply! (1st time posting, please be kind)
You may be able to solve your problem by forcing the image onto the same axis as the plot. Try this:
I = imread('C:\MATLAB\R2014a\help\images\ref\ftrans2_fig.png');
I = squeeze(uint8(mean(I,3)));
[rows, cols] = size(I);
x_data = (-1 : .01 : +1)';
y_data = 1 - x_data.^2;
h1 = axes('Position',([52, 23, 355-52, 262-23] ./ [cols, rows, cols, rows] ));
set(h1, 'Color', 'none')
hold on
image(I, 'Parent', h1);
plot(h1, x_data, y_data, '-rx')
That should at ensure that the plot axis and the image axis have the same origin, as they will be one and the same. You may need to adjust your sizing code. Let me know if that doesn't do it for you.
Good Luck!
I think I have it figured out.
It would have been easier if I could use:
figure, h1=imshow(I)
get(h1,'Position')
but that results in "The name 'Position' is not an accessible property for an instance of class 'image'."
Instead, this appears to work:
I = imread('C:\MATLAB\R2014a\help\images\ref\ftrans2_fig.png');
I = squeeze(uint8(mean(I,3)));
in_mag = 300;
figure, imshow(I, 'Border', 'tight', 'InitialMagnification', in_mag)
[rows, cols] = size(I);
x_data = (-1 : .01 : +1)';
y_data = 1 - x_data.^2;
% Coord of graph in image pixels
x_0 = 50; x_max = 354; y_0 = 262; y_max = 23;
h1 = axes('Position',([x_0, rows-y_0, x_max-x_0, y_0-y_max] ...
./ [cols, rows, cols, rows] ));
set(h1,'Color','none')
hold on
plot(x_data, y_data, '-rx')
ylim([0,1.4])
set(gca,'YColor', [0 0 1], 'XColor', [0 0 1])
However, if anybody has a better idea, I would be very happy to explore it!
Thanks

Detect angle of text in image with horizontal and rotate in matlab [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
See the image below :
As you can seen in the image the written text in rotated by 90 deg angle and I want to rotate only the text to be horizontal. By what ever angle it is rotated I want to make it horizontal as in below :
I don't want the complete image to the rotated. I want that the text only is bounded and the angle by which the text is rotated is measured and then rotated by that angle to make it horizontal.
Can you suggest me a way to do so and then fit an ellipse onto the text ?
Thank you.
First, let's find x-y coordinates of all the dark pixels
bw = imread('http://i.imgur.com/0LxC6bd.png');
bw = min( bw, [], 3 ) < 50 ; % dark pixels - intensity lower than 50
[y x] = find( bw ); % note that find returns row-col coordinates.
Compute the covariance matrix of the text coordinates
mx = mean(x);
my = mean(y);
C = [ mean( (x-mx).^2 ), mean( (x-mx).*(y-my) );...
mean( (x-mx).*(y-my) ) mean( (y-my).^2 ) ];
You can get the orientation of the ellipse from the eigen vectors and eigen values of C:
[V D] = eig( C );
figure; imshow( bw ); hold on;
quiver( mx([1 1]), my([1 1]), (V(1,:)*D), (V(2,:)*D), .05 );
Looking at the eigenvectors and eigen values:
V =
-0.9979 -0.0643
-0.0643 0.9979
D =
1.0e+003 *
0.1001 0
0 1.3652
You can see that the eigen-vectors (columns of V) are approximately the pointing to the -X direction (first column) and the Y direction (second column). Examining the eigen values (diagonal of D) you can see that the second eigen value is much larger than the first - this is the major axis of your ellipse. Now you can recover the orientation of the ellipse:
[~, mxi] = max(diag(D)); % find major axis index: largest eigen-value
Recover the angle from the corresponding eigen-vector
or = atan2( V(2,mxi), V(1,mxi) ) * 180/pi ; % convert to degrees for readability
or =
93.6869
As you can see the major axis of the ellipse is almost 90deg off the horizon.
You can rotate the image back
imrotate( bw, -or );
Drawing an ellipse given the covariance matrix:
th = linspace(0, 2*pi, 500 );
xy = [cos(th);sin(th)];
RR = chol( C ); % cholesky decomposition
exy = xy'*RR; %//'
figure;imshow( bw ); hold on;
plot( 2*exy(:,1)+mx, 2*exy(:,2)+my, 'r', 'LineWidth', 2 );
I used this solution:
bw = im2;
bw = sum((1-im2).^2, 3) > .5;
%bw = min( bw, [], 3 ) < 50 ; % dark pixels - intensity lower than 50
[y x] = find( bw ); % note that find returns row-col coordinates.
mx = mean(x);
my = mean(y);
C = [ mean( (x-mx).^2 ), mean( (x-mx).*(y-my) );...
mean( (x-mx).*(y-my) ) mean( (y-my).^2 ) ];
[V D] = eig( C );
quiver( mx([1 1]), my([1 1]), (V(1,:)*D), (V(2,:)*D), .05 );
[~,mxi] = max(diag(D)); % find major axis index: largest eigen-value
or = atan2( V(2,mxi), V(1,mxi) ) * 180/pi ; % convert to degrees for readability
rotate = imrotate( im2, or-180 );
axes(handles.axes2);
imshow( rotate );
set(handles.text3, 'String',or-180);

Matlab: Something like "relative" position with uicontrol/axis; keep fixed margins when resizing

I currently have a big headache to get a small GUI working nicely which isn't being created with GUI editor but programmatically! What I have so far is something like the following:
hFig = figure();
set(hFig, 'Position', [300 200 500 400]);
plot((1:10).^2, '*-r');
% Größe des Plots so anpassen, dass links Platz für Buttons
ap = get(gca, 'TightInset');
fp = get(gcf, 'Position');
set(gca, 'Position', [160/fp(3), 30/fp(4), (fp(3)-180)/fp(3), (fp(4)-60)/fp(4)]);
uicontrol('Style', 'pushbutton', 'String', 'foo', 'Position', [15 fp(4)-60 110 30]);
uicontrol('Style', 'pushbutton', 'String', 'bar', 'Position', [15 fp(4)-100 110 30]);
Try to resize it: It doesn't 'look' the same, which means that the uicontrol boxes don't stay at the same relative position and the margins from the axis to the figure window get bigger. What I want to achieve is:
Have a figure window with a given position (x/y, width and height) with a plot inside. The plot will have a title and labels for x and y. Make the plot as height and width to have the TightInset plus a margin in each direction of a certain px-size (e.g. TightInset + 10px) as big as the figure window; except leave 150px of free space on the left to place some uicontrol buttons, and have them stay in the same position: This would be the same as being able to give the position from top/left (top = 20, left = 10) instead of bottom/left.
Thanks a lot!
Okay finally found a working solution I wanted it to be :-) Hopefully it is helpfull for somebody interested in it:
Main script file:
p = [300 300 1000 600];
fixedMargins = [250 0 0 0]; % [left, top, right, bottom]
f = figure('Position', p, 'Color', [0.9 0.9 0.9]);
plot(-10:10, (-10:10).^3, '*-r');
set(f, 'ResizeFcn', {#resizeCallback, gca, fixedMargins, {#myuiFunc, f, 40, 50}});
title('bla')
xlabel('foooooooooo')
ylabel('barrrrrrr')
Resize Callback Function:
% Need to pass the handle of the axis to modify (hAx) AND to pass the
% desired margins as second extra callback argument:
% [left, top, right, bottom]!
function resizeCallback(hFig, ~, hAx, fixedMargins, func)
% Disable automatic rezising
set(hAx, 'Units', 'pixels');
% Figure-Size
fp = get(hFig, 'Position');
% Calculate Position of the axis
margin = get(hAx, 'TightInset') * [-1 0 1 0; 0 -1 0 1; 0 0 1 0; 0 0 0 1];
% Position to fill the figure minus the TightInset-Margin
newPos = [0 0 fp(3:4)] - margin;
% Change position based on margins
newPos(1) = newPos(1) + fixedMargins(1);
newPos(3) = newPos(3) - fixedMargins(1) - fixedMargins(3);
newPos(2) = newPos(2) + fixedMargins(4);
newPos(4) = newPos(4) - fixedMargins(2) - fixedMargins(4);
% Set new position
set(hAx, 'Position', newPos);
% Call UI-Func
if(nargin == 5)
f = func{1};
args = func(2:end);
f(args{:});
end
end
You can pass whatever function you want to be called when resizing the figure window, e.g. to update something in the figure. In my example it's the myuiFunc(), which is the following:
function myuiFunc(hFig, left, top)
persistent handles;
if(~isempty(handles))
delete(handles);
handles = [];
end
fp = get(hFig, 'Position');
h1 = uicontrol('Style', 'pushbutton', 'String', 'Foo','Position', [left fp(4)-top 100 35]);
h2 = uicontrol('Style', 'pushbutton', 'String', 'Bar','Position', [left fp(4)-top-50 100 35]);
handles = [h1 h2];
end
I like it :) Hopefully you too!
Edit: No need to edit the resizeCallback Function! Should work if you just pass your desired margins to it and if you like, additionally a function handle with arguments which will be called for each resize!
You can also use "Normalized" units.
uicontrol('Style', 'pushbutton', 'String', 'foo', 'Units','normalized','Position', [0.90 0.05 0.08 0.08] );

Resources