How can i plot an ellipse and parabola together in Matlab? - matlab

I need to plot a parabola and ellipse. However the ellipse is giving me trouble. Can anyone help? The equations are: y = -5*x^2 + 2 and (x^2/16) + (y^2/2) = 4
I've tried this code but obviously I feel like like it isn't right.
x = linspace(-5, 5);
y1 = (x.^2/16) + (y.^2/2) - 1;
y2 = -5*x.^2 +2;
figure(1)
plot(x, y1)
hold on
plot(x, y2)
hold off

Firstly, you did not define a range variable x. Secondly, the ellipse won't pass the vertical line test and can't be plotted like a regular function f(x). Thirdly, your equation y1 = (x.^2/16) + (y.^2/2) - 1; is non-sensical because you have y on each side.
You could correct your method by defining a range variable x1 and x2 that each have appropriate ranges for the functions your plotting. What I mean by this is that you probably don't want the same range for each function, because the ellipse is undefined over most of the range that the parabola is defined. To plot the ellipse using f(x) you could observe that there are + and - values that are identical, using this fact you could plot your ellipse by two functions one to represent the top half and one to represent the bottom half, each of these would pass the vertical line test.
OR
You could utilize ezplot and have a nice time with it because it makes your life easier. Here is a solution.
ezplot('x^2/16+y^2/2-4'); axis equal; hold on
ezplot('-5*x^2+2-y')

There are multiple ways to plot an ellipse, e.g. you could also use a parametric representation of the equation.
In your approach though, when plotting functions using plot(x,y) command, you need to express your dependent variable (y) through independent variable (x). You defined the range for x, which is what you substitute into your equations in order to find y's. While for the parabola, the dependency of y from x is obvious, you forgot to derive such a relationship for the ellipse. In this case it will be +-sqrt((1 - x^2/16)*2). So in your approach, you'll have to take into account both negative and positive y's for the same value of x. Also there's discrepancy in your written equation for the ellipse (=4) and the one in Matlab code (=1).
x = linspace(-5, 5);
y1 = sqrt((1 - x.^2/16)*2);
y2 = -5*x.^2 +2;
figure(1)
plot(x, real(y1), 'r', x, -real(y1), 'r')
hold on
plot(x, y2)
hold off
Since the ellipse has real y's not on the whole x domain, if you want to plot only real parts, specify real(y1) or abs(y1) (even though Matlab does it for you, too). You can also dismiss complex numbers for certain x when computing y1, but you'll need a for-loop for that.
In order to make things simpler, you can check the function fimplicit, ezplot is not recommended according to Matlab's documentation. Or if you want to plot the ellipse in a parametric way, fplot will work, too.
Another (more classic) approach for parametric plotting is given here already, then you don't need any other functions than what you already use. I think it is the simplest and most elegant way to plot an ellipse.

You will not be able to generate points for the ellipse using a function f(x) from a Cartesian linspace range. Instead, you can still use linspace but for the angle in a polar notation, from 0 to 2*pi. You should also be able to easily adjust radius and offset on both axis on the cos and sin expressions.
x = linspace(-5, 5);
y2 = -5*x.^2 +2;
figure(1)
clf;
plot(x, y2)
hold on
a = linspace(0,2*pi);
x2 = 4*cos(a);
y2 = sqrt(2)*sin(a);
plot(x2, y2)
xlim([-5,5]);
ylim([-5,5]);
hold off

Related

Get matlab `surf` to plot a function that doesn't exist everywhere in the region

I'm trying to use matlab to create a surface plot of a function that has a limited domain [it's a square root, and the argument goes negative].
x = [-2:0.02:4]
y = [-6:0.1:6]
[X,Y] = meshgrid(x,y)
If I do
surf(X,Y,sqrt(9-(X-1).*(X-1)-Y.*Y/4))
I get an error message because the function is imaginary outside of an ellipse. So I could do
surf(X,Y,real(sqrt(9-(X-1).*(X-1)-Y.*Y/4)))
But then it's 0 outside of the domain. Really I'd like it to just not plot anything at all.
The only idea I have is to modify Y so that for each X, it's limited to the values where the function is defined. But I'd really like a way to say 'just don't plot those parts' so that I don't have to calculate the domain each time.
Exploiting the fact that NaNs are usually ignored by graphical routines, you could use:
x = [-2:0.02:4];
y = [-6:0.1:6];
[X,Y] = meshgrid(x,y);
clear x y;
W=sqrt(9-(X-1).*(X-1)-Y.*Y/4);
Z=nan(size(W));
W_isreal=abs(imag(W))<=eps();
Z(W_isreal)=real(W(W_isreal));
clear W W_isreal;
surf(X,Y,Z);
Notice that this approach introduces unsightly artifacts near z=0:
A more elegant approach that avoids such gaps near z=0 could be:
[X,Y,Z]=ellipsoid(1,0,0,3,6,3);
surf(X,Y,Z);
zlim([0 Inf]);
% Verify computations
W=9-(X-1).*(X-1)-Y.*Y/4;
W_istruenegative=(W<=-1e-6);
if any(W_istruenegative(:))
error('Our ellipsoid looks invalid.');
end
if any( abs(sqrt(abs(W(:))) - abs(Z(:))) > 1e-6 ) %verify ellipsoid
error('Our ellipsoid looks invalid.');
end
clear W W_istruenegative;

how to plot graphs above each other in matlab [duplicate]

I wanted to generate a plot (X vs Y), and Z values depend on the Y. The example is shown in the figure below. The matrix size of X is same with Z but not Y. I can plot Z against X, but I wanted to combine all the plot into a single plot and become Y against X. I can plot multiple plots into a single plot but the plot is overlapping each other.
My question is there any method I can merge multiple plots into a single plot without overlapping each plot as the difference between each plot is very small (e.g Z1=1,2,3,4,5 and Z2=1.0001,2.0002,3.0001,4.0002,5.0001). So, I wanted to set each Z plot at different Y axis. (e.g Z1 at Y=0, Z2 at Y=2 ...)
Does anyone have any suggestions or idea?
Thank You
I'll clarify the ideas I wrote in a comment.
First, let's get some data:
x = 470:0.1:484;
z1 = cos(x)/2;
z2 = sin(x)/3;
z3 = cos(x+0.2)/2.3;
I'll plot just three data sets, all of this is trivial to extend to any number of data sets.
Idea 1: multiple axes
The idea here is simply to use subplot to create a small-multiple type plot:
ytick = [-0.5,0.0,0.5];
ylim = [-0.9,0.9]);
figure
h1 = subplot(3,1,1);
plot(x,z1);
set(h1,'ylim',ylim,'ytick',ytick);
title('z1')
h2 = subplot(3,1,2);
plot(x,z2);
set(h2,'ylim',ylim,'ytick',ytick);
title('z2')
h3 = subplot(3,1,3);
plot(x,z3);
set(h3,'ylim',ylim,'ytick',ytick);
title('z3')
Note that it is possible to, e.g., remove the tick labels from the top two plot, leaving only labels on the bottom one. You can then also move the axes so that they are closer together (which might be necessary if there are lots of these lines in the same plot):
set(h1,'xticklabel',[],'box','off')
set(h2,'xticklabel',[],'box','off')
set(h3,'box','off')
set(h1,'position',[0.13,0.71,0.8,0.24])
set(h2,'position',[0.13,0.41,0.8,0.24])
set(h3,'position',[0.13,0.11,0.8,0.24])
axes(h1)
title('')
ylabel('z1')
axes(h2)
title('')
ylabel('z2')
axes(h3)
title('')
ylabel('z3')
Idea 2: same axes, plot with offset
This is the simpler approach, as you're dealing only with a single axis. #Zizy Archer already showed how easy it is to shift data if they're all in a single 2D matrix Z. Here I'll just plot z1, z2+2, and z3+4. Adjust the offsets to your liking. Next, I set the 'ytick' property to create the illusion of separate graphs, and set the 'yticklabel' property so that the numbers along the y-axis match the actual data plotted. The end result is similar to the multiple axes plots above, but they're all in a single axes:
figure
plot(x,z1);
hold on
plot(x,z2+2);
plot(x,z3+4);
ytick = [-0.5,0.0,0.5];
set(gca,'ytick',[ytick,ytick+2,ytick+4]);
set(gca,'yticklabel',[ytick,ytick,ytick]);
text(484.5,0,'z1')
text(484.5,2,'z2')
text(484.5,4,'z3')
The simplest would be to shift Z data. But note that Z2 would look like to be oscillating around 1 - so this is a neat visual representation, but might mislead.
% Simple version - shift Z curves by 0, 1, ... (as recommended by #Cris Luengo)
shiftMat = repmat(0 : size(Z, 2)-1, size(Z,1), 1);
Z = Z + shiftMat;
%Min shift up to have non-overlapping - curves touching
for i = 2 : size(Z, 2)
Zdif = (Z(:, i-1) - Z(:, i));
Z(:, i) = Z(:, i) + max(Zdif); % + 0.01 to separate them a little bit.
end
%Bigger shift up, to have all points of Z(2) equal or above all points of z1.
for i = 2 : numZ
Zdif = max(Z(:, i-1))-min(Z(:, i));
Z(:, i) = Z(:, i) + Zdif;
end
Another possibility is to have multiple Y axis and each Z curve plotted against its own Y axis. This is likely fancier and shouldn't mislead, but it is way more work, even after you grab the function, as you still need to position all those axes. MATLAB by default lets you use only 2 axes, so grab a function from fileexchange to add more: https://www.mathworks.com/matlabcentral/fileexchange/9016-addaxis

Draw a line with non-Cartesian coordinates in MATLAB

MATLAB's surf command allows you to pass it optional X and Y data that specify non-cartesian x-y components. (they essentially change the basis vectors). I desire to pass similar arguments to a function that will draw a line.
How do I plot a line using a non-cartesian coordinate system?
My apologies if my terminology is a little off. This still might technically be a cartesian space but it wouldn't be square in the sense that one unit in the x-direction is orthogonal to one unit in the y-direction. If you can correct my terminology, I would really appreciate it!
EDIT:
Below better demonstrates what I mean:
The commands:
datA=1:10;
datB=1:10;
X=cosd(8*datA)'*datB;
Y=datA'*log10(datB*3);
Z=ones(size(datA'))*cosd(datB);
XX=X./(1+Z);
YY=Y./(1+Z);
surf(XX,YY,eye(10)); view([0 0 1])
produces the following graph:
Here, the X and Y dimensions are not orthogonal nor equi-spaced. One unit in x could correspond to 5 cm in the x direction but the next one unit in x could correspond to 2 cm in the x direction + 1 cm in the y direction. I desire to replicate this functionality but drawing a line instead of a surf For instance, I'm looking for a function where:
straightLine=[(1:10)' (1:10)'];
my_line(XX,YY,straightLine(:,1),straightLine(:,2))
would produce a line that traced the red squares on the surf graph.
I'm still not certain of what your input data are about, and what you want to plot. However, from how you want to plot it, I can help.
When you call
surf(XX,YY,eye(10)); view([0 0 1]);
and want to get only the "red parts", i.e. the maxima of the function, you are essentially selecting a subset of the XX, YY matrices using the diagonal matrix as indicator. So you could select those points manually, and use plot to plot them as a line:
Xplot = diag(XX);
Yplot = diag(YY);
plot(Xplot,Yplot,'r.-');
The call to diag(XX) will take the diagonal elements of the matrix XX, which is exactly where you'll get the red patches when you use surf with the z data according to eye().
Result:
Also, if you're just trying to do what your example states, then there's no need to use matrices just to take out the diagonal eventually. Here's the same result, using elementwise operations on your input vectors:
datA = 1:10;
datB = 1:10;
X2 = cosd(8*datA).*datB;
Y2 = datA.*log10(datB*3);
Z2 = cosd(datB);
XX2 = X2./(1+Z2);
YY2 = Y2./(1+Z2);
plot(Xplot,Yplot,'rs-',XX2,YY2,'bo--','linewidth',2,'markersize',10);
legend('original','vector')
Result:
Matlab has many built-in function to assist you.
In 2D the easiest way to do this is polar that allows you to make a graph using theta and rho vectors:
theta = linspace(0,2*pi,100);
r = sin(2*theta);
figure(1)
polar(theta, r), grid on
So, you would get this.
There also is pol2cart function that would convert your data into x and y format:
[x,y] = pol2cart(theta,r);
figure(2)
plot(x, y), grid on
This would look slightly different
Then, if we extend this to 3D, you are only left with plot3. So, If you have data like:
theta = linspace(0,10*pi,500);
r = ones(size(theta));
z = linspace(-10,10,500);
you need to use pol2cart with 3 arguments to produce this:
[x,y,z] = pol2cart(theta,r,z);
figure(3)
plot3(x,y,z),grid on
Finally, if you have spherical data, you have sph2cart:
theta = linspace(0,2*pi,100);
phi = linspace(-pi/2,pi/2,100);
rho = sin(2*theta - phi);
[x,y,z] = sph2cart(theta, phi, rho);
figure(4)
plot3(x,y,z),grid on
view([-150 70])
That would look this way

How to plot graph with customized axis

I apologize for asking this, I believe this is a simple task, but I don't know how to do it.
Suppose I have a formula y = (exp(-x) + x^2)/sqrt(pi(x) and I want to plot it as y versus x^2.
How does one do this?
Like this:
X = 0:0.1:5; %// Get the x values
x = X.^2; %// Square them
%// Your formula had errors, I fixed them but I could have misinterpreted here, please check
y = (exp(-x) + x.^2)./sqrt(pi*x); %// Calculate y at intervals based on the squared x. This is still y = f(x), I'm just calculating it at the points at which I want to plot it.
plot(x,y) %//Plot against the square X.
At this point this is no different to having just plotted it normally. What you want is to make the tickmarks go up in values of X.^2. This does not change the y-values nor distort the function, it just changes what it looks like visually. Similar to plotting against a log scale:
set(gca, 'XTick', X.^2) %//Set the tickmarks to be squared
The second method gives you a plot like
edit:
Actually I think you were asking for this:
x = 0:0.1:5;
y = x.^2; %// Put your function in here, I'm using a simple quadratic for illustrative purposes.
plot(x.^2,y) %//Plot against the square X. Now your y values a f(x^2) which is wrong, but we'll fix that later
set(gca, 'XTick', (0:0.5:5).^2) %//Set the tickmarks to be a nonlinear intervals
set(gca, 'XTickLabel', 0:0.5:5) %//Cahnge the labels to be the original x values, now accroding to the plot y = f(x) again but has the shape of f(x^2)
So here I'm plotting a simple quadratic, but if I plot it against a squared x it should become linear. However I still want to read off the graph that y=x^2, not y=x, I just want it to look like y=x. So if I read the y value for the x value of 4 on that graph i will get 16 which is still the same correct original y value.
Here's my answer: it is similar to Dan's one, but fundamentally different. You can calculate the values of y as a function of x, but plot them as a function of x^2, which is what the OP was asking, if my understanding is correct:
x = 0:0.1:5; %// Get the x values
x_squared = x.^2; %// Square them
%// Your formula had errors, I fixed them but I could have misinterpreted here, please check
y = (exp(-x) + x.^2)./sqrt(pi*x); %// Calculate y based on x, not the square of x
plot(x_squared,y) %//Plot against the square of x
As Dan mentioned, you can always change the tickmarks:
x_ticks = (0:0.5:5).^2; % coarser vector to avoid excessive number of ticks
set(gca, 'XTick', x_ticks) %//Set the tickmarks to be squared

How to plot a specific function in matlab

I have this function:
and I want plot it, I think the result is a periodic function...
I tried this but got only one point :(
x1=-50:0.1:50;
x2=-50:0.1:50;
plot(cos(sqrt(power(x1,2)+power(x2,2)))/(power(x1,2)+power(x2,2)));
where is my problem and what is the correct way?
appreciate any help.
You need to plot it as a 3-D surface. For example, use surf:
[X1, X2] = meshgrid(-5:0.25:5, -5:0.25:5);
F = cos(sqrt(X1 .^ 2 + X2 .^ 2)) ./ (X1 .^ 2 + X2 .^ 2 + 1);
surf(X1, X2, F)
Note two things:
You forgot the "+1" in the denominator.
I've reduced the range of x1 and x2 coordinates, for better visualization.
If the black edges look annoying and seem to clutter the plot, you can remove the edge lines by disabling the EdgeColor property (as user Shai pointed out):
surf(X1, X2, F, 'EdgeColor', 'None')
The final result should look something like this:
That's a 3d plot, since there are two inputs x1 and x2. So you've got to use plot3 (or surf as #EitanT points out, or any 3d plotting function).
You're now only plotting the pairs (-50;-50), (-49.9;-49.9),...,(50;50), because you start from two vectors, you probably want to cover all the combinations. Therefore, use meshgrid (for higher dimensions, there is also ndgrid):
x1=-50:0.1:50;
x2=-50:0.1:50;
[X1, X2] = meshgrid(x1,x2);
You now use matrix operations, read through this link and you'll see that you need elementwise operations: a.*b instead of a*b, etc. power(a,b) is already the element-wise operation (the same as a.^b), matrix equivalent is mpower(a,b) or a^b.
f = cos(sqrt(power(X1,2)+power(X2,2)))./(power(X1,2)+power(X2,2)+1);
plot3(X1,X2,f);