I am trying to plot a cake piece like surface in matlab but I have no idea how to define z to make it look like a cake pie. The shape I need is this:
This is the code I wrote so far:
th = linspace(0, pi/3);
r = linspace(0, pi/3);
% z = linspace(0, 10);
[R, TH] = meshgrid(r, th);
x = R.*cos(TH);
y = R.*sin(TH);
z = R;
% z = 10 * ones(size(x));
ss = surf(x, y, z, 'FaceAlpha',0.3);
ss.EdgeAlpha = 0.6;
ss.FaceAlpha = 0.1;
it will look similar to that shape, but not exactly, I mean the shape will be rough:
z = rand(size(x));
another option with smoother surface:
z = zeros(size(x));
[m,n]=size(x);
for i=1 : n
for j=1 : m
if(mod(i+j,2)==0)
z(i,j) = 1;
end
end
end
Related
I am trying to use the spherical harmonics to represent a perturbation of a spherical object in an acoustic and fluid flow in 3D.
So far, I have been able to use a 2D perturbation on a 3D spherical object, however, I would like to extend that.
The current code represents a 3D sphere with a 2D perturbation, so the perturbation is only in x and y:
clearvars; clc; close all;
Nx = 128;
Ny = 128;
Nz = 128;
Lx =128;
Ly = 128;
Lz = 128;
xi = (0:Nx-1)/Nx*2*pi;
xi_x = 2*pi/Lx;
x = xi/xi_x;
yi = (0:Ny-1)/Ny*2*pi;
yi_y = 2*pi/Ly;
y = yi/yi_y;
zi = (0:Nz-1)/Nz*2*pi;
zi_z = 2*pi/Lz;
z = zi/zi_z;
[X,Y,Z] = meshgrid(x,y,z);
A = 2*pi / Lx;
B = 2*pi / Ly;
C = 2*pi / Lz;
x0 = 64;
y0 = 64;
z0 = 64;
rx0 = 20;
ry0 = 20;
rz0 = 20;
p = 3;
b = 0.1; % pert amplitude
c = 12;
d = 1;
a = 4;
theta = atan2(Y -y0, X-x0) - (pi/c);
p0 = ((X-x0) .* (X-x0)) /(rx0 * rx0) + ((Y-y0) .* (Y-y0))/(ry0 * ry0) + ((Z-z0) .* (Z-z0))/(rz0 * rz0);
Test =d + a * exp((-1. * p0 .* (1 - b .* cos(c * theta))).^p) ;
figure
isosurface(X,Y,Z,Test);
shading flat;
grid on;
Which returns the isosurface:
However, I would like to achieve something similar to this plot (perturbation in z as well):
This is my attempt using spherical harmonics to reproduce the above picture:
clearvars; clc; close all;
%in spherical coord
%calculate r
Nx = 128;
Ny = 128;
Nz = 128;
Lx =128;
Ly = 128;
Lz = 128;
xi = (0:Nx-1)/Nx*2*pi;
xi_x = 2*pi/Lx;
x = xi/xi_x;
yi = (0:Ny-1)/Ny*2*pi;
yi_y = 2*pi/Ly;
y = yi/yi_y;
zi = (0:Nz-1)/Nz*2*pi;
zi_z = 2*pi/Lz;
z = zi/zi_z;
r = sqrt(x.^2 + y.^2 + z.^2);
% Create the grid
delta = pi/127;
%Taking for instance l=1, m=-1 you can generate this harmonic on a (azimuth, elevation) grid like this:
azimuths = 0 : delta : pi;
elevations = 0 : 2*delta : 2*pi;
[R, A, E] = ndgrid(r, azimuths, elevations); %A is phi and E is theta
H = 0.25 * sqrt(3/(2*pi)) .* exp(-1j*A) .* sin(E) .* cos(E);
%transform the grid back to cartesian grid like this:
%can also add some radial distortion to make things look nicer:
%the radial part depends on your domain
X = r .* cos(A) .* sin(E);
Y = r .* sin(A) .* sin(E);
Z = r .* cos(E);
%parameters
x0 = 64;
y0 = 64;
z0 = 64;
rx0 = 20;
ry0 = 20;
rz0 = 20;
p = 3;
b = 0.1; % pert amplitude
%c = 12;
d = 1;
a = 4;
p0 = ((X-x0) .* (X-x0)) /(rx0 * rx0) + ((Y-y0) .* (Y-y0))/(ry0 * ry0) + ((Z-z0) .* (Z-z0))/(rz0 * rz0);
Test1 =d + a * exp((-1. * p0 .*H).^p) ;
figure
isosurface(X,Y,Z,real(Test1)); %ERROR
This gives me the following error:
Error using griddedInterpolant
Grid arrays must have NDGRID structure.
Is the issue in the way I am setting up the spherical harmonics? or the functional form of Test1?? Thanks
I think the problem is that you've created a NDGrid in the second code. In the first code that worked you created a meshgrid.
isosurface expects a grid in meshgrid format and transforms it later into an NDGrid format with permute just for the usage of the griddedInterpolant function. By the input of an NDGrid this operation will fail.
Why did you switch to creating a NDGrid? Did you get the same error when using meshgrid?
EDIT
OK, new theory: I think the problem is the grid itsself. Read the documentation on ndgrid for more information but for short: A NDGrid format is a completely rectangular grid where all nodes are exclusivly surrounded by 90° angles. By spanning up a grid with ndgrid(r, azimuths, elevations) or meshgrid(r, azimuths, elevations) you are getting this rectangular grid but of course this grid is meaningless because r, azimuths and elevations represent spherical coordinates. By later converting R, A and E into the carthesian coordinates X, Y and Z you get a propper spherical grid but the grid isn't a NDGrid structure anymore since it's not rectangular anymore.
So you have to find a workaround to calculate with your spherical grid.
Maybe you can use another function to visualize your data that dosn't take any grid format as input
Or maybe you can try working with a rectangular cartesian grid by setting all values outside the sphere to 0. (You have to refine your grid accordingly to achieve a good estimation of the sphere)
I have the function:
f(z) = conj(z) + 0.4*z^2,
Going from a polar grid where 0 < theta < 2pi and between 0.5 < |z| < 2.5 for its two radii. I have no idea where to start as I'm new to MATLAB but I'm trying to make 2 subplots each with two parametric equations for each curve but I've had no success.
Try this code. Swap the definition of f to switch between the polar grid and the transformed grid. I also answered a similar question here.
clear
clc
N = 41;
t = linspace(0, 2*pi, N);
r = linspace(0.5, 2.5, N);
[R,T] = meshgrid(r,t);
Z = R.*exp(T*1i);
% f = Z; %Original mesh
f = conj(Z) + 0.4*Z.^2; %Transformed mesh
U = real(f);
V = imag(f);
%Plot mesh
hold off
plot(U,V,'b-');
hold on
plot(U',V','r-');
xlim([-5,5]);
ylim([-5,5]);
axis equal
I want to use function where x and y are coordinates forming circle, z(x, y) grows from 0 at the edge to max at the R/2 and back to 0 at the center without sharp changes. I stucked with
t = -pi:pi/180:pi;
R = 5;
x = R*cos(t);
y = R*sin(t);
for i = 1:361
for j = 1:361
z(i,j) = exp( sqrt((x(i)).^2 + (y(j)).^2));
end
end
[u, v] = meshgrid(x, y);
mesh(u, v, z), grid on;
How should I realize z to add this drop to the middle? Any suggestions appreciated!
Maybe subtract two 2D gaussians with a different standard deviation?
% the area
x = linspace(-5,5,1E2);
y = linspace(-5,5,1E2);
sig1=1;
sig2=2;
%2D gaussian
efac = 1/(2*sig1);
X = exp(-efac*x.^2);
Y = exp(-efac*y.^2)';
z1 = Y*X;
z1=z1./max(z1(:));
%2D gaussian
efac = 1/(2*sig2);
X = exp(-efac*x.^2);
Y = exp(-efac*y.^2)';
z2 = Y*X;
z2=z2./max(z2(:));
[u, v] = meshgrid(x, y);
mesh(u, v, z2-z1), grid on;
An alternative that has zero outside of R and is more along the lines of your own code:
x = linspace(-2*pi,2*pi,1E2);
y = linspace(-2*pi,2*pi,1E2);
[u, v] = meshgrid(x, y);
r = sqrt(u.^2+v.^2);
z = sin(r);
z(r>pi)=0;
mesh(u, v, z), grid on;
Or to make it a little less sharp at the base:
z = sin(r).^2;
I could use this method to draw a ellipsoid in Matlab:
Xc is x-coordinate of the center, Xr is half the length of ellipsoid in x direction
Xc = 0; Xr = 1;
Yc = 0; Yr = 2;
Zc = 0; Zr = 3;
[X Y Z] = ellipsoid(Xc, Yc, Zc, Xr, Yr, Zr);
surf(X,Y,Z);
This can give me a 3-D image of the ellipsoid but if I do not know things like Xc or Xr ..., all I know is a function:
A = 5; B = 0; C =2;
D = 2; E = 1;
P = [A B;
B C];
q = [D E];
syms x y;
f = [x y] * P * [x y]' + q * [x y] + 1;
But it seems that surf won't allow to use syms variables.
ezplot(f) give only a 2-D ellipse.
How can I draw a 3-D ellipsoid with this function in Matlab using surf, mesh or anything else?
The reason I write this function f is that I want to see how the positive definiteness and negative definiteness of matrix P influence the image of function f.
Thanks!
You can draw an ellipsoid (or any other implicit surface) using isosurface. For example, the ellipsoid
2*x^2+2xy+3y^2+2yz+4z^2+4z-1=0 can be drawn using the following code:
[x,y,z]= meshgrid(-2:0.05:2); % the surface should fit in the meshgrid area
v= 2*x.^2+2*x.*y+3*y.^2+2*y.*z+4*z.^2+4*z-1; % the left side of the equation
isosurface(x,y,z,v,0); % the value 0 is the right hand side of the equation
axis tight
I'm trying to graph a simple 2D Gaussian in MATLAB using the surf function, but I'm getting an error saying that the last value in surf must be a matrix and not a vector. I don't understand how to graph the function then as every other example I've found while searching has had the third value as a vector. I feel as if I'm completely off base here with the surf function. Any ideas?
amp = 10;
x0 = 0;
y0 = 0;
sigmaX = 10
sigmaY = 10
X = 1:1:100;
Y = 1:1:100;
Z = amp*exp(-(X-x0).^2/(2*sigmaX^2)+(Y-y0).^2/(2*sigmaY^2));
disp(size(Z))
surf(X, Y, Z);
Edit
When I plot this using #Suever's answer, I get something that doesn't look like a Gaussian at all.
Here's the plot
amp = 1;
x0 = 0;
y0 = 0;
sigmaX = 1;
sigmaY = 1;
%X = 1:1:100;
%Y = 1:1:100;
[X,Y] = meshgrid(-3:.1:3);
%Z = X .* exp(-X.^2 - Y.^2);
Z = amp*exp(-(X-x0).^2/(2*sigmaX^2)+(Y-y0).^2/(2*sigmaY^2));
surf(X, Y, Z);
You have used X and Y to define a 2D domain over which you would like to compute your gaussian. If you want Z to be a function of X and Y, you need to define Z for all permutations of X and Y. If you don't provide a matrix of Z values, MATLAB has no idea how to create a surface over the X Y ranges you've provided.
You can create all permutations of X and Y using meshgrid and then compute Z over this entire domain. Then you will be able to display the result with surf.
amp = 10; x0 = 50; y0 = 50; sigmaX = 10; sigmaY = 10;
[X, Y] = meshgrid(1:100, 1:100);
% Z as you had it written (see correct version below)
Z = amp*exp(-(X-x0).^2./(2*sigmaX^2)+(Y-y0).^2./(2*sigmaY^2));
surf(X, Y, Z);
Update
Your equation for the 2D Gaussian is wrong. The - sign should be outside of the addition of the two components. The way that you had it written, you negated the X-component and then added to the Y component.
Z = amp*exp(-((X-x0).^2./(2*sigmaX^2)+(Y-y0).^2./(2*sigmaY^2)));