How to draw a circular 3D plot in matlab - matlab

I want to plot this function in matlab : sin(4*x)*cos(4*y) on a disk
This is how i proceeded :
syms x y;
f=#(x,y) sin(4*x)*cos(4*y);
ezmesh(f,'circ')
This method works with f=#(x,y) sin(2*x)*cos(2*y);
but with a more quickly varying function like f=#(x,y) sin(4*x)*cos(4*y); ezmesh mistakes these variations for discontinuities.
the problem is i can't use the 'circ' parameter and increase the number of points that ezmesh uses at the same time (ezmesh didn't accept it)
Is there any other way ?

I'm not sure if it can be done by adding another parameter. However, if you want a quick-and-dirty way, here you go:
x = -2*pi:0.1:2*pi;
y = -2*pi:0.1:2*pi;
[xx, yy] = meshgrid(x,y);
zz = sin(4*xx).*cos(4*yy);
zz(xx.^2 +yy.^2 >(2*pi)^2) = 0;
surf(xx,yy,zz);
Which produces:

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

Take fitted data from fit object

I use the following example taken from the site that describes fit. Returns an
object. Is it possible to take the data that refer to the fitted surface?
load franke
sf = fit([x, y],z,'poly23')
plot(sf,[x,y],z)
Thanks!
Here is a way to do it; but there is probably a cleaner one:
After getting your sf object, you can access its methods like so:
MethodName(sf)
See here for the list of available methods
So let's say you wish to plot the surface using a handle for the plot:
hPlot = plot(sf)
Then you can fetch the XData, YData and ZData using the handles like so:
X = get(hPlot,'XData')
Y = get(hPlot,'YData')
Z = get(hPlot,'ZData')
Might be a it cumbersome but it works. Note that you can also fetch the coefficients of the fitted surface like so:
coeffvalues(sf)
and the formula used to generate it:
formula(sf)
Therefore you could generate X, Y data and create Z values using meshgrid for example and you could then modify the surface as you wish.
EDIT Here is how you could create your own surface using the coefficients and the formula. Here I create an anonymous function with two input arguments (x and y) and use it to generate z values to plot. From the data obtained using plot(sf) I used x = 1:0.01:0.01:1 and y = 500:500:3000 but you could obviously change them.
I entered the formula manually in the function handle but there has to be a better way; I'm a bit in a hurry so I did not looked further into that but you could extract every element of the formula and multiply it by the right coefficient to automatically generate the formula.
Here is the whole code:
clear
clc
close all
load franke
sf = fit([x, y],z,'poly23')
c = coeffvalues(sf)
F = formula(sf)
%// Generate x and y values.
[x,y] = meshgrid(500:100:3000,0.01:.01:1);
%// There should be a better approach than manually entering the data haha.
%// Maybe use eval or feval.
MyFun = #(x,y) (c(1) + c(2)*x + c(3)*y +c(4)*x.^2 + c(5)*x.*y + c(6)*y.^2 + c(7)*(x.^2).*y + c(8)*x.*y.^2 + c(9)*y.^3);
%// Generate z data to create a surface
z = (MyFun(x,y));
figure
subplot(1,2,1)
plot(sf)
title('Plot using sf','FontSize',18)
subplot(1,2,2)
surf(x,y,z)
title('Plot using MyFun','FontSize',18)
Output:
[I know this is many years later, but I thought I'd add this for future visitors looking for answers]
There is a much simpler way to do this - use feval, or the implicit shortcuts to it by calling the fittype object itself. It did take me a little digging to find this when I needed it, it isn't particularly obvious.
From the feval MATLAB documentation:
Standard feval syntax:
y = feval(cfun,x)
z = feval(sfun,[x,y])
z = feval(sfun,x,y)
y = feval(ffun,coeff1,coeff2,...,x)
z = feval(ffun,coeff1,coeff2,...,x,y)
You can use feval to evaluate fits, but the following simpler syntax is recommended to evaluate these objects, instead of calling feval directly. You can treat fit objects as functions and call feval indirectly using the following syntax:
y = cfun(x) % cfit objects;
z = sfun(x,y) % sfit objects
z = sfun([x, y]) % sfit objects
y = ffun(coef1,coef2,...,x) % curve fittype objects;
z = ffun(coef1,coef2,...,x,y) % surface fittype objects;

What interpolation technique does Matlab plot function use to show the data?

It seems to be very basic question, but I wonder when I plot x values against y values, what interpolation technique is used behind the scene to show me the discrete data as continuous? Consider the following example:
x = 0:pi/100:2*pi;
y = sin(x);
plot(x,y)
My guess is it is a Lagrangian interpolation?
No, it's just a linear interpolation. Your example uses a quite long dataset, so you can't tell the difference. Try plotting a short dataset and you'll see it.
MATLAB's plot performs simple linear interpolation. For finer resolution you'd have to supply more sample points or interpolate between the given x values.
For example taking the sinus from the answer of FamousBlueRaincoat, one can just create an x vector with more equidistant values. Note, that the linear interpolated values coincide with the original plot lines, as the original does use linear interpolation as well. Note also, that the x_ip vector does not include (all) of the original points. This is why the do not coincide at point (~0.8, ~0.7).
Code
x = 0:pi/4:2*pi;
y = sin(x);
x_ip = linspace(x(1),x(end),5*numel(x));
y_lin = interp1(x,y,x_ip,'linear');
y_pch = interp1(x,y,x_ip,'pchip');
y_v5c = interp1(x,y,x_ip,'v5cubic');
y_spl = interp1(x,y,x_ip,'spline');
plot(x,y,x_ip,y_lin,x_ip,y_pch,x_ip,y_v5c,x_ip,y_spl,'LineWidth',1.2)
set(gca,'xlim',[pi/5 pi/2],'ylim',[0.5 1],'FontSize',16)
hLeg = legend(...
'No Interpolation','Linear Interpolation',...
'PChip Interpolation','v5cubic Interpolation',...
'Spline Interpolation');
set(hLeg,'Location','south','Fontsize',16);
By the way..this does also apply to mesh and others
[X,Y] = meshgrid(-8:2:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
figure
mesh(Z)
No, Lagrangian interpolation with 200 equally spaced points would be an incredibly bad idea. (See: Runge's phenomenon).
The plot command simply connects the given (x,y) points by straight lines, in the order given. To see this for yourself, use fewer points:
x = 0:pi/4:2*pi;
y = sin(x);
plot(x,y)

How do I plot relations in matlab?

I want to plot relations like y^2=x^2(x+3) in MATLAB without using ezplot or doing algebra to find each branch of the function.
Does anyone know how I can do this? I usually create a linspace and then create a function over the linspace. For example
x=linspace(-pi,pi,1001);
f=sin(x);
plot(x,f)
Can I do something similar for the relation I have provided?
What you could do is use solve and allow MATLAB's symbolic solver to symbolically solve for an expression of y in terms of x. Once you do this, you can use subs to substitute values of x into the expression found from solve and plot all of these together. Bear in mind that you will need to cast the result of subs with double because you want the numerical result of the substitution. Not doing this will still leave the answer in MATLAB's symbolic format, and it is incompatible for use when you want to plot the final points on your graph.
Also, what you'll need to do is that given equations like what you have posted above, you may have to loop over each solution, substitute your values of x into each, then add them to the plot.
Something like the following. Here, you also have control over the domain as you have desired:
syms x y;
eqn = solve('y^2 == x^2*(x+3)', 'y'); %// Solve for y, as an expression of x
xval = linspace(-1, 1, 1000);
%// Spawn a blank figure and remember stuff as we throw it in
figure;
hold on;
%// For as many solutions as we have...
for idx = 1 : numel(eqn)
%// Substitute our values of x into each solution
yval = double(subs(eqn(idx), xval));
%// Plot the points
plot(xval, yval);
end
%// Add a grid
grid;
Take special care of how I used solve. I specified y because I want to solve for y, which will give me an expression in terms of x. x is our independent variable, and so this is important. I then specify a grid of x points from -1 to 1 - exactly 1000 points actually. I spawn a blank figure, then for as many solutions to the equation that we have, we determine the output y values for each solution we have given the x values that I made earlier. I then plot these on a graph of these points. Note that I used hold on to add more points with each invocation to plot. If I didn't do this, the figure would refresh itself and only remember the most recent call to plot. You want to put all of the points on here generated from all of the solution. For some neatness, I threw a grid in.
This is what I get:
Ok I was about to write my answer and I just saw that #rayryeng proposed a similar idea (Good job Ray!) but here it goes. The idea is also to use solve to get an expression for y, then convert the symbolic function to an anonymous function and then plot it. The code is general for any number of solutions you get from solve:
clear
clc
close all
syms x y
FunXY = y^2 == x^2*(x+3);
%//Use solve to solve for y.
Y = solve(FunXY,y);
%// Create anonymous functions, stored in a cell array.
NumSol = numel(Y); %// Number of solutions.
G = cell(1,NumSol);
for k = 1:NumSol
G{k} = matlabFunction(Y(k))
end
%// Plot the functions...
figure
hold on
for PlotCounter = 1:NumSol
fplot(G{PlotCounter},[-pi,pi])
end
hold off
The result is the following:
n = 1000;
[x y] = meshgrid(linspace(-3,3,n),linspace(-3,3,n));
z = nan(n,n);
z = (y .^ 2 <= x .^2 .* (x + 3) + .1);
z = z & (y .^ 2 >= x .^2 .* (x + 3) - .1);
contour(x,y,z)
It's probably not what you want, but I it's pretty cool!

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!