Plot a surface in MATLAB - matlab

I want to plot a surface in MATLAB using surf. I have this equation: x = y^2 +4z^2.
What I am doing is the following:
[x,y] = meshgrid(-4:.1:4, -4:.1:4);
z = sqrt((x - y.^2)./4); % Basically I'm just clearing for z
surf(x,y,z)
But with this I am getting the error: Error using surf X,Y,Z and C cannot be complex. I know there is a complex number because of the values that x and y have, plus the square root. Is there another way to plot a surface in MATLAB? because I really don't know what to do, and my skills are very basics.

Why do you feel that you need to grid x and y, and not use the form of the original equation itself?
This seems to work perfectly fine
[y,z] = meshgrid(-4:.1:4, -4:.1:4);
x = y.^2 + 4*z.^2;
surf(x,y,z)
to produce

Related

Matlab Surface Plot of Z^2 = Z type equation

i'm currently trying to plot this function:
Z^2 = (X.^2+Y.^2+2*w.*Z.*Y.*a)./(1-w^2*a^2)
Geogebra gives a lightcone https://en.wikipedia.org/wiki/Light_cone but crushes if i change the parameters a bit. I tried then matlab:
[X,Y] = meshgrid(-10:.5:10);
a=2;
w=1;
Z = (X.^2+Y.^2+2*w.*sqrt(abs(Z)).*Y.*a)./(1-w^2*a^2);
surf(X,Y,Z)
zlim([-5,5])
And it has too few points. I wish i could add some changing meshgrid, like (-5:.1:5), but it gives:
Arrays have incompatible sizes for this operation.
Probably due to sqrt(abs(Z)) in the equation. I don't know how to fix it.
Thanks
It's easier to directly generate the cone data with command cylinder
t = 0:pi/10:2*pi;
r =linspace(2,0,numel(t))
[X,Y,Z] = cylinder(r);
figure
hs1=surf(X,Y,Z)
Note that I have added the handle hs1 which is output of surf.
This way you can change any property of the generated cone surface explained in detail here :
https://uk.mathworks.com/help/matlab/ref/matlab.graphics.chart.primitive.surface-properties.html

How can i plot an ellipse and parabola together in 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

How to plot a parametric surface in Matlab

I have a parametric B-Spline surface, S
S=[x(:);y(:);z(:)];
Right now, I am plotting the surface by just plotting each column of S as a single point:
plot3(S(1,:),S(2,:),S(3,:),'.')
The result is this:
Unfortunately, by plotting individual points, we lose the sense of depth and curvy-ness when we look at this picture.
Any ideas on how to implement SURF or MESH command for a parametric surface? These functions seem to require a matrix representing a meshgrid which I dont think I can use since the X x Y domain of S is not a quadrilateral. However, I like the lighting and color interpolation that can be conveniently included when using these functions, as this would fix the visualization problem shown in figure above.
I am open to any other suggestions as well.
Thanks.
Without seeing your equations it's hard to offer an exact solution, but you can accomplish this by using fsurf (ezsurf if you have an older version of MATLAB).
There are specific sections regarding plotting parametric surfaces using ezsurf and fsurf
syms s t
r = 2 + sin(7*s + 5*t);
x = r*cos(s)*sin(t);
y = r*sin(s)*sin(t);
z = r*cos(t);
fsurf(x, y, z, [0 2*pi 0 pi]) % or ezsurf(x, y, z, [0 2*pi 0 pi])
If you want to have a piece-wise function, you can either write a custom function
function result = xval(s)
if s < 0.5
result = 1 - 2*s;
else
result = 2 * x - 1;
end
end
And pass a function handle to fsurf
fsurf(#xval, ...)
Or you can define x to be piece-wise using a little bit of manipulation of the function
x = (-1)^(s > 0.5) * (1 - 2*s)

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

Matlab - how to plot the intersection between an implicitly defined surface and a plane

I'm not very familiar with matlab, but I'm trying to plot the intersection of a plane (x + y + z = 1) with a surface. the surface is defined implicitly (x, y, and z as functions of alpha, beta). this is my code:
alpha = linspace(0,pi);
beta = linspace(0,pi);
[alpha,beta]=meshgrid(alpha,beta);
L= 4*exp(-.6*beta).*sin(alpha);
%converting to x,y,z coordinates:
x = L.*sin(alpha).*cos(beta);
y = L.*cos(alpha);
z= L.*sin(alpha).*sin(beta);
to plot this i generally would use surf(x,y,z). but in this case i want to plot its intersection with a plane, for example the one defined by z2 = 1-x+y. (im not sure whether it would be better to define separate matrices for new x, y values, or whether it is better to use the existing ones.) i hope this question isn't too confusing. if you have any advice, please help.
What if you try the following: (I based my code on this answer to a previous question Plotting Implicit Algebraic equations in MATLAB) and it is not perfect but maybe it can help you:
clear
clc
alpha = linspace(0,pi);
beta = linspace(0,pi);
[alpha,beta]=meshgrid(alpha,beta);
L= 4*exp(-.6*beta).*sin(alpha);
x = L.*sin(alpha).*cos(beta);
y = L.*cos(alpha);
z= L.*sin(alpha).*sin(beta);
% Use an anonymous function to define the plane you want to plot
[X,Y] = meshgrid(min(x(:)):.5:max(x(:)),min(y(:)):0.5:max(y(:))); % x and y limits
f = #(X,Y) -X+Y+1; % sorry for the choice of capital letters; it was the most intuitive I thought.
hold on
surf(x,y,z);
contour3(X,Y,f(X,Y),200); % the 200 is arbitrary; play with it to change the # of lines making up the plane
hold off
rotate3d on
The result looks like this:
As I said I'm not 100% confident this is the most robust way but it looks fine to me :)