I'm trying to create 3D plots in Matlab, and I have practically no experience. I'd really like to plot the figure described by these equations:
x = cos(u)*(2 + cos(v))
y = sin(u)*(2 + cos(v))
z = x^2 - y^2 + 2*x*y*tan^2(v)
-pi <= u <= pi, -pi <= v <= pi
Which plot originally should be like this
(source: paulbourke.net)
I've tried my best and came up with:
% volume data
u = linspace(-pi,pi,40);
v = linspace(-pi,pi,40);
[u, v] = meshgrid(u, v);
X =cos(u).*(2 + cos(v));
Y =sin(u).*(2 + cos(v));
Z =(X.^2)-(Y.^2)+(X.*Y.*2.*((tan(v)).^2));
surf(X,Y,Z,'FaceColor','none','EdgeColor','interp')
%shaded surface
colormap(jet)
camlight right
I get the following:
What's wrong?
There's actually nothing wrong with your graph. The reason why you see the graph like that is because the z
axis is too large. The z
values that actually define most of its shape are orders of magnitude smaller than the highest values seen in that graph... in the order of thousands. The reason why is because when the values of u
and v
are +/- pi/2
, tan
is undefined, which is why the heights are so high as you gravitate towards these angles.
One suggestion I have is to clip the z
values if they get too large. Set some sort of threshold on the z
values and clip them. Something like 100 for high positive values and -100 for large negative values. Also, adjust the viewing angle for a better view, and I would also recommend increasing the number of points so that the shading is better interpolated... something like 1000. For an even glossier effect, try changing the FaceColor
attribute to interp
rather than none
.
As such:
u = linspace(-pi,pi,1000); %// Define 1000 points per dimension
v = linspace(-pi,pi,1000);
[u, v] = meshgrid(u, v);
X =cos(u).*(2 + cos(v));
Y =sin(u).*(2 + cos(v));
Z =(X.^2)-(Y.^2)+(2*X.*Y.*(tan(v).^2));
Z(Z <= -100) = -100; %// Enforce threshold
Z(Z >= 100) = 100;
surf(X,Y,Z,'FaceColor','interp','EdgeColor','interp')
%shaded surface
colormap(jet)
view(30,50); %// Change viewing angle
camlight right
I get this: