How to plot a parametric surface in Matlab - 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)

Related

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 my differential equation with quiver?

I want to solve my differential equation and plot velocity vectors but I am having some trouble with that. I tried this:
syms y(x);
ode = (1+exp(x))*y*diff(y,x)-2*exp(x) == 0;
ySol = dsolve(ode)
[X,Y] = meshgrid(-2:.2:2);
Z = 2*exp(X)/((1+exp(X)).*Y);
[DX,DY] = gradient(Z,.2,.2);
figure
contour(X,Y,Z)
hold on
quiver(X,Y,DX,DY)
hold off
and I get this error:
Warning: Matrix is singular to working precision.
Warning: Contour not rendered for non-finite ZData
It is probably something simple that I do not see but I am just starting using Matlab and I cold not find a right way to do my task. Please help me...
EDIT
As bconrad suggested, I changed my Z function like this:
Z = 2*exp(X)/((1+exp(X)).*Y);
and the previous errors are fixed. However, my prime goal, to plot velocity vectors is not accomplished yet because I get a graph like this:
Don’t have the ability to check at the moment, but I reckon you want an element by element division in that line. You’re missing a dot on the division, try
Z = 2*exp(X)./((1+exp(X)).*Y);
I took a closer look once at my station. The zero-division mentioned by Pablo forces inf's in Z, so quiver get's confused when scaling the vectors (understandably) and just doesn't show them. Try this (with the ode part removed):
[X,Y] = meshgrid(-2 : .2 : 2);
Z = 2 * exp(X) ./ ((1 + exp(X)) .* Y);
Z(isinf(Z)) = nan; % To avoid 0-division problems
[DX, DY] = gradient(Z, .2, .2);
figure
contour(X, Y, Z, 30, 'k')
hold on
quiver(X, Y, DX, DY, 6)
hold off
I've done 3 things here:
Added the line Z(isinf(Z)) = nan; forcing infinite values to be essentially ignored by quiver
Added the arguments 30, 'k' to the contour function to show 30 lines, and make them black (a bit more visible)
Added the argument 6 to the quiver function. This overrides the automatic length-scaling of the vectors.
You'll want to play with the arguments in the contour and quiver functions to make your figure appear as you'd like.
PS: There is a handy arrow function on the file exchange that I find gives better control when creating vector field plots. See https://www.mathworks.com/matlabcentral/fileexchange/278-arrow - the ratings do it justice.

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

plot Quadric Surfaces in General Form in matlab

I have Quadric Surface equation
I know A,B,C...
How can I plot my equation in matlab?
Your best bet is to produce a 3D contour plot of your function with a single contour at the function value 0. To do this with reasonable accuracy, compute your function F at a number of points x, y, z as follows:
gv = linspace(-30,30,50); % adjust for appropriate domain
[xx yy zz]=meshgrid(gv, gv, gv);
F = A*xx.*xx + B*yy.*yy + C*zz.*zz+ ... etc
figure
isosurface(xx, yy, zz, F, 0)
The reason to do it this way is that your function is typically multi-valued- that is, for a given value of X and Y there may be two possible answers for Z. By doing things this way you effectively bypass that problem - instructing matlab to put a surface anywhere that the function is zero.
Note that I gave an arbitrary vector gv for the grid - that is, the points on which the function is evaluated. To get an accurate and visually pleasing result you probably need around 50 points in each dimension within the range over which a solution is possible (this may be different in the three dimensions);
For example, with
F = xx.^2 + 2*yy.^2 + 0.5*zz.^2 + .4*xx.*yy + .5*xx.*zz + .6*yy.*zz + 7*xx + 8*yy + 9*zz - 100;
You get the following figure:

Plotting the result of a 2 parameter function in matlab (3D Graph)

Basically, I have a function f(X,Y) that would return one value for each X,Y that I give. Is there any function in matlab where I can pass the function f, the ranges for X,Y so that it plots a 3d graph showing the magnitude of f (along the z axis) for all values within the given range.
ezplot3, does this kind of, but it takes only one parameter 't'. I am very new to matlab and am trying my best to learn it fast, but I couldnt find much regarding this. Any help would be appreciated
Keep in mind, that with matlab, you're never really plotting "functions"; You're plotting arrays/vectors. So instead of trying to plot g = f(X,Y), you'll actually by plotting the vectors X, Y, and g, where X and Y are your original inputs and g is a vector containing your outputs.
I'm having a hard time visualizing what exactly you're trying to plot but basically, you can follow any standard matlab plotting example such as: http://web.cecs.pdx.edu/~gerry/MATLAB/plotting/plotting.html
It does not produce a 3D plot, but I have found the 2D scatter plot useful for this kind of task before:
scatter(x, y, 5, z)
Where z is the value of the function at the point (x, y) will produce something similar to what you want. Its perhaps not quite as pretty as a full 3D plot but can be used to good effect.
See:
http://www.mathworks.com/matlabcentral/fileexchange/35287-matlab-plot-gallery-scatter-plot-2d/content/html/Scatter_Plot_2D.html
Here is some (very ugly) code I put together to demonstrate the difference:
j=1;
y = -100:1:100;
for i = -100:1:100
y = [y -100:1:100];
count = 0;
while count < 202;
x(j) = i;
j = j+1;
count = count + 1;
end
end
z = (abs(x) + abs(y));
figure(1)
scatter(x, y, 10, z)
h=colorbar;
figure(2)
ezsurf('(abs(x) + abs(y))')
Well, this is what I was going for : http://www.mathworks.com/help/matlab/ref/ezsurf.html
if i do this
ezsurf('f(x,y)');
I get the 3d graph I wanted.
Thanks anyways!