I'm looking for a way to export anti-aliased graphics containing lines and "surf" at the same time.
With HG2, the "plot" lines are anti-aliased by default but the anti-aliasing is switched off once I insert a "surf". The closest I could get was by using "export_fig" but it's not exporting dashed lines properly.
r=100;
theta = linspace(0,2*pi,100);
[x,y] = pol2cart(theta,r*ones(1,100));
[x1,y1] = pol2cart(theta,0.9*r*ones(1,100));
rc = 0.1;
h = 0.3;
m = h/rc;
[R,A] = meshgrid(-linspace(0,rc,11),linspace(0,2*pi,50));
X3 = R .* cos(A)*r;
Y3 = R .* sin(A)*r;
Z3 = -(m*R+h)*r;
hold on
plot(x,y)
plot(x1,y1,'-.')
%plots are with anti-aliasing
s = surf(X3,Y3,Z3)
s.FaceLighting = 'gouraud';
s.AmbientStrength = 0.6;
s.DiffuseStrength = 0.8;
s.SpecularStrength = 0.9;
s.SpecularExponent = 25;
s.BackFaceLighting = 'reverselit';
s.FaceColor=[0.25 0.25 0.25];
set(s,'FaceAlpha',0.3);
set(s,'EdgeAlpha',0);
view(2)
%anti-aliasing is gone...
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)
In this movie the conformal mapping fz = -1/z is visualized as a continuous transformation of an image to the distorted result. How was this made? I am working with conformal mappings in Matlab and I would like to know a method to generate the intermediate steps of an arbitrary conformal transformation in analogy to this movie.
One old trick is to use surface with FaceColor = texturemap with Z=0. A texturemapped surface with Z=0 is basically an image, but it lets you mess with the X&Y coordinates of the underlying grid to do this sort of warping.
You'd want 2D arrays for your XData & YData. Those are the ones you'll manipulate with the mapping. Your ZData would be an array of the same size which was all zeros. Then the CData array would be an image. If you wanted to use a 20x20 grid, it might look something like this:
m = 20;
n = 20;
[x,y] = meshgrid(m,n);
img = imread('myimage.png');
h = surf(x,y,zeros(m,n),img,'FaceColor','texturemap');
Then you can manipulate h.XData and h.YData to animate changing the mapping.
for t = 0:.05:1
[newx, newy] = mymapping(x,y,t);
h.XData = newx;
h.YData = newy;
drawnow
end
With the following code I can generate a sequence of images that could be considered as a transformation or animation using the linear equation (1-t) * 1 + t * (1./(a.*(x+1i.*y))); But it is in no way that what is seen in CH56_Clip4.mov. Additionally t = 0.00 delivers a monochrome result.
[h_i, w_i, ~] = size(img);
% INITIALIZE IN-MESHGRID & NORMALIZE [0 1]
[xi,yi] = meshgrid(linspace(0,w_i+1,w_i),linspace(0,h_i+1,h_i));
xi = (xi/w_i); yi = (yi/h_i);
% INITIALIZE OUT-MESHGRID & NORMALIZE [-1 1]
[xo,yo] = meshgrid(1:w_i, 1:h_i);
xo = (xo/w_i)*2 - 1; yo = (yo/h_i)*2 - 1;
% GENERATE SURFACE
h = surf(xo, yo, zeros(w_i, h_i), img, 'FaceColor', 'texturemap');
% INITIALIZE OUT-IMAGE
img_out_t = zeros(h_i, w_i, 3);
for t = 0.00:0.1:1.0
% DISTORTION, SEPARATE & NORMALIZE [0 1]
fxiy = (1-t) * 1 + t * (1./(1.2.*(xo+1i.*yo)));
h.XData = real(fxiy); xo1 = h.XData;
h.YData = imag(fxiy); yo1 = h.YData;
xo1 = (xo1+1)/2; yo1 = (yo1+1)/2;
% INTERPOLATION
for k = 1:3; img_out_t(:,:,k) = uint8(interp2(xi, yi, img(:,:,k), xo1, yo1, interpol_meth)); end; imwrite(uint8(img_out_t), ['img_out_t_', num2str(t), '.jpg'], 'jpg', 'Quality', 98);
end
I have made this plot of streamlines around a cylinder with a radius of 1. Is there a way to remove whats inside the cylinder and maybe even high lite the cylinder with a different colour?
clear
% make axes
xymax = 2;
x = linspace(-xymax,xymax,100);
y = linspace(-xymax,xymax,100);
% note that x and y don't include 0
[X,Y] = meshgrid(x,y);
R = sqrt(X.^2 + Y.^2);
sin_th = Y./R;
cos_th = X./R;
U = 1;
a = 1;
psi = U*(R - a*a./R).*sin_th;
figure
contour(X,Y,psi,[-3:.25:3],'-b');
You can mask what you don't want to draw with nan:
psi((Y>0 & psi<0) | (Y<0 & psi>0)) = nan;
and than draw a circle on it:
rectangle('Position', [-1 -1 2 2],'Curvature',[1 1],'EdgeColor','r')
Here is the code and result:
% make axes
xymax = 2;
x = linspace(-xymax,xymax,100);
y = linspace(-xymax,xymax,100);
% note that x and y don't include 0
% [X,Y] = meshgrid(x(x<-1 | x>1),y(y<-1 | y>1));
[X,Y] = meshgrid(x,y);
R = sqrt(X.^2 + Y.^2);
sin_th = Y./R;
cos_th = X./R;
U = 1;
a = 1;
psi = U*(R - a*a./R).*sin_th;
% mask the inner part with nans:
psi((Y>0 & psi<0) | (Y<0 & psi>0)) = nan;
contour(X,Y,psi,[-3:0.25:3],'-b');
% draw a circle:
rectangle('Position', [-1 -1 2 2],'Curvature',[1 1],'EdgeColor','r')
axis equal
You can try also changing directly X and Y (instead of Y and psi):
psi(Y>-1 & X>-1 & Y<1 & X<1) = nan;
but the result is a bit different.
This is counter-intuitive, but the rectangle function can be used to draw a circle!
hold on
rectangle('Position',[-R,-R,2*R,2*R],'Curvature',[1,1],'FaceColor',[1 1 0])
Feel free to play around with the line properties too ('EdgeColor' and 'LineWidth')
https://www.mathworks.com/help/matlab/ref/rectangle.html
I need to slice a 3D volume (200x200x500 matrix) and plot the result. I tried following the example from Mathworks reported here, but the resulting slice is empty (it shouldn't be)... Do you have suggestions on how to fix this? Thanks!
Here is the code I am using and the resulting slice:
xmin = 1;
ymin = 1;
zmin = 1;
xmax = 200;
ymax = 200;
zmax = 499;
hslice = surf(linspace(xmin,xmax,100),...
linspace(ymin,ymax,100),...
zeros(100));
rotate(hslice,[100,100,250],-45)
xd = get(hslice,'XData');
yd = get(hslice,'YData');
zd = get(hslice,'ZData');
delete(hslice);
x = 1:200;
y = 1:200;
z = 1:499;
figure;
colormap(jet);
h = slice(x,y,z,V1,xd,yd,zd);
h.FaceColor = 'interp';
h.EdgeColor = 'none';
h.DiffuseStrength = 0.8;
This will draw a slice at x=100
v=randn(200,200,500);
[x,y,z] = meshgrid(1:200,1:200,1:500);
h=slice(x,y,z,v,100,[],[]);
set(h,'EdgeColor','none')
like wise you can place additional slices at y or z if you replace the [] with coordinates for e.h. y and z.
I would like to plot the surface of this function in Matlab:
w=(m*(1-p))/(h-1+m*(1-p))
Where
h=0.98;
P=[0.05:0.001:0.98];
M=[0:0.001:1];
The graph should look like this:
I tried to implement the graphing function as:
h=0.98;
P=[0.05:0.001:0.98];
M=[0:0.001:1];
W=[];
for i=1:size(P, 2)
for j=1:size(M, 2)
p=P(i);
m=M(j);
w=(m*(1-p))/(h-1+m*(1-p));
if w>1000
w=1000;
end
if w<0
w=0;
end
W(i, j) = w;
end
end
mesh(M, P, W);
But since the function changes rapidly around the boundary condition, my graph ended up looking like this:
How can I smooth out the curve and give it a nice, uniform grid like in the first picture?
Here's a way to do what you want. See comments in the code for more information.
%% //Definitions
w = #(h,m,p)(m.*(1-p))./(h-1+m.*(1-p)); %// w as a function handle
w_min = 0; w_max = 10; %// For plots
cMap = hot(200); cMap = cMap(floor(0.5*length(cMap)):ceil(0.7*length(cMap)),:);
h = 0.98;
m_start = 0; m_end = 1; m_step = [0.02 0.01 0.001];
p_start = 0.05; p_end = 0.98; p_step = [0.1 0.01 0.001];
%// Definitions of the mesh used in plotting (same for all charts)
mesh_m_step = 0.05; mesh_p_step = 0.05;
[meshM,meshP] = meshgrid(m_start:mesh_m_step:m_end,p_start:mesh_p_step:p_end);
meshW = w(h,meshM,meshP);
%% //Evaluation and plotting:
figure(); set(gcf,'Position',[240,500,1391,376]); subplot(1,3,1);
for ind1 = 1:3
%% // Evaluate equation
[MM,PP] = meshgrid(m_start:m_step(ind1):m_end,p_start:p_step(ind1):p_end);
WW = w(h,MM,PP);
%% // Plot
subplot(1,3,ind1);
surf(MM,PP,WW,'EdgeColor','none'); view([45,45]);
hold on; mesh(meshM,meshP,meshW,'EdgeColor','k','FaceColor','none');
colormap(cMap); %// Fix the colormap
zlim([w_min,w_max]); caxis(zlim) %// Modify zlim
end
Which results in: