Contour plot of a function of 3 variables - matlab

As we can make contour plot of f=(x.^2) + (y.^2); in 2-D as follows:
[x,y]= meshgrid(-10:10, -10:10);
contour(x,y, (x.^2)+(y.^2));
and we can make contour plot of f=(x.^2) + (y.^2); in 3-D using contour3
Can we make contour plot of f=(x.^2) + (y.^2) + (z.^2); in 3-D

The matlab function isosurface can do what you are asking. However you can also achieve the results you want using other alternatives, like using surf. I will cover both methods.
Method 1: Using isosurface
We need to create the domain for x, y and z and then generate a 3D mesh with those values so that we can evaluate the function f(x,y,z) = x^2 + y^2 + z^2. Then, we shall give a value to the constant k and feed all this information to isosurface, so that we can obtain the family of (x,y,z) values that satisfy the condition: f(x,y,z) = k. Note that this contours are in fact spheres! Finally we can use patch to generate a surface with those values.
It is very interesting to give different values for k iterativelly and see the contours associated with those values.
% Value for x, y and z domain.
a = 10;
% Domain for x ,y and z.
x = linspace(-a,a);
y = linspace(-a,a);
z = linspace(-a,a);
% Generate a 3D mesh with x, y and z.
[x,y,z] = meshgrid(x,y,z);
% Evaluate function (3D volume of data).
f = x.^2 + y.^2 + z.^2;
% Do contours from k = 0 to k = 100 in steps of 1 unit.
for k = 0:100
% Draw the contour that matches k.
p = patch(isosurface(x,y,z,f,k));
isonormals(x,y,z,f,p)
p.FaceColor = 'red';
p.EdgeColor = 'none';
% Adjust figure properties.
title(sprintf('Contours of f(x,y,z) = x^2 + y^2 + z^2\nwith f(x,y,z) = k = %d',k));
xlabel('x-axis');
ylabel('y-axis');
zlabel('z-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10 -10 10]);
camlight left;
lighting phong;
% Update figure.
drawnow;
% Clear axes.
cla;
end
This is the output:
Method 2: Using surf
As in the previous method, to contour the function f(x,y,z) = x^2 + y^2 + z^2, we need to match the function to a constant value, this is f(x,y,z) = k, where k is any constant value you choose.
If we isolate z in terms of k, x and y we have: z = ± sqrt(k-x.^2-y.^2), so we have the explicit values for x, y and z. Now, let's give different values for k iterativelly and see the results that we get with the surf function!
% Do contours from k = 0 to k = 100 in steps of 1 unit.
for k = 0:100
% Find the value where: k - x^2 - y^2 = 0
a = sqrt(k);
% Domain for x and y.
x = linspace(-a,a);
y = linspace(-a,a);
[x,y] = meshgrid(x, y);
% Isolate z in terms of k, x and y.
z = sqrt(k-x.^2-y.^2);
% Find complex entries in z.
i = find(real(z)~=z);
% Replace complex entries with NaN.
z(i) = NaN;
% Draw upper hemisphere of surface.
surf(x,y,z,'FaceColor','red','EdgeColor','none');
hold on;
% Draw lower hemisphere of surface.
surf(x,y,-z,'FaceColor','red','EdgeColor','none');
% Adjust figure properties.
title(sprintf('Contours of f(x,y,z) = x^2 + y^2 + z^2\nwith f(x,y,z) = k = %d',k));
xlabel('x-axis');
ylabel('y-axis');
zlabel('z-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10 -10 10]);
camlight left;
lighting phong;
% Update figure.
drawnow;
hold off;
end
This is the output:
References
I took some of the ideas from David Arnold's article "Complex Numbers and Plotting in Matlab", which is well worth a read and will help you understand how to plot functions that generate complex numbers.

Related

Extracting Z values after 3D plot is generated by 2D curve revolution with repmat

I am stuck with an apparently simple problem. I have to revolve of 360° a 2D curve around an axis, to obtain a 3D plot. Say, I want to do it with this sine function:
z = sin(r);
theta = 0:pi/20:2*pi;
xx = bsxfun(#times,r',cos(theta));
yy = bsxfun(#times,r',sin(theta));
zz = repmat(z',1,length(theta));
surf(xx,yy,zz)
axis equal
I now want to visualize the numerical values of the Z plane, stored in a matrix. I would normally do it this way:
ch=get(gca,'children')
X=get(ch,'Xdata')
Y=get(ch,'Ydata')
Z=get(ch,'Zdata')
If I visualize Z with
imagesc(Z)
I don't obtain the actual values of Z of the plot, but the "un-revolved" projection. I suspect that this is related to the way I generate the curve, and from the fact I don't have a function of the type
zz = f(xx,yy)
Is there any way I can obtain the grid values of xx and yy, as well as the values of zz at each gridpoint?
Thank you for your help.
Instead of bsxfun you can use meshgrid:
% The two parameters needed for the parametric equation
h = linspace(0,2) ;
th = 0:pi/20:2*pi ;
[R,T] = meshgrid(h,th) ;
% The parametric equation
% f(x) Rotation along Z
% ↓ ↓
X = sin(R) .* cos(T) ;
Y = sin(R) .* sin(T) ;
% Z = h
Z = R ;
surf(X,Y,Z,'EdgeColor',"none")
xlabel('X')
ylabel('Y')
zlabel('Z')
Which produce:
And if you want to extract the contour on the X plane (X = 0) you can use contour:
contour(Y,Z,X,[0,0])
Which produce:

Edit the x limits of least squares line

I created two scatter plots and then used lsline to add regression lines for each plot. I used this code:
for i=1:2
x = ..;
y = ..;
scatter(x, y, 50, 'MarkerFaceColor',myColours(i, :));
end
h_lines = lsline;
However, the darker line extends far beyond the last data point in that scatter plot (which is at around x=0.3):
lsline doesn't seem to have properties that allow its horizontal range to be set. Is there a workaround to set this separately for the two lines, in Matlab 2016a?
For a single data set
This is a workaround rather than a solution. lsline internally calls refline, which plots a line filling the axis as given by their current limits (xlim and ylim). So you can change those limits to the extent you want for the line, call lsline, and then restore the limits.
Example:
x = randn(1,100);
y = 2*x + randn(1,100); % random, correlated data
plot(x, y, '.') % scatter plot
xlim([-1.5 1.5]) % desired limit for line
lsline % plot line
xlim auto % restore axis limit
For several data sets
In this case you can apply the same procedure for each data set sequentially, but you need to keep only one data set visible when you call lsline; otherwise when you call it to create the second line it will also create a new version of the first (with the wrong range).
Example:
x = randn(1,100); y = 2*x + randn(1,100); % random, correlated data
h = plot(x, y, 'b.'); % scatter plot
axis([min(x) max(x) min(y) max(y)]) % desired limit for line
lsline % plot line
xlim auto % restore axis limit
hold on
x = 2*randn(1,100) - 5; y = 1.2*x + randn(1,100) + 6; % random, correlated data
plot(x, y, 'r.') % scatter plot
axis([min(x) max(x) min(y) max(y)]) % desired limit for line
set(h, 'HandleVisibility', 'off'); % hide previous plot
lsline % plot line
set(h, 'HandleVisibility', 'on'); % restore visibility
xlim auto % restore axis limit
Yet another solution: implement your own hsline. It's easy!
In MATLAB, doing a least squares fit of a straight line is trivial. Given column vectors x and y with N elements, b = [ones(N,1),x] \ y; are the parameters to the best fit line. [1,x1;1,x2]*b are the y locations of two points along the line with x-coordinates x1 and x2. Thus you can write (following Luis' example, and getting the exact same output):
N = 100;
x = randn(N,1); y = 2*x + randn(N,1); % random, correlated data
h = plot(x, y, 'b.'); % scatter plot
hold on
b = [ones(N,1),x] \ y;
x = [min(x);max(x)];
plot(x,[ones(2,1),x] * b, 'b-')
x = 2*randn(N,1) - 5; y = 1.2*x + randn(N,1) + 6; % random, correlated data
plot(x, y, 'r.') % scatter plot
b = [ones(N,1),x] \ y;
x = [min(x);max(x)];
plot(x,[ones(2,1),x] * b, 'r-')
You can get the points that define the line using
h_lines =lsline;
h_lines(ii).XData and h_lines(ii).YData will contain 2 points that define the lines for each ii=1,2 line. Use those to create en equation of a line, and plot the line in the range you want.

Applying 3D rotation matrix to x, y, z values obtained from surface function

Applying 3D rotation matrix to the x,y,z values obtained from surface function object. The error I get is due to the matrix not being nonconforment but how can I adjust the matrix correctly?
I know hgtransform / makehgtform can do rotations but I need to use rotation matrices since I plan on testing it using matrices created from quaternions.
I've created a little plane out of cylinders and the surface functions.
See code below:
clear all,clf
ax=axes('XLim',[-2 2],'YLim', [-2 10],'ZLim',[-1.5 1.5]);
grid on;
%axis equal;
xlabel('x');
ylabel('y');
zlabel('z');
ax
% rotate around
rot_mat = [.707 -.707 0;.707 .707 0; 0 0 1] %rotation matrix
[xc yc zc] = cylinder([0.1 0.0]); %cone
[x y z]= cylinder([0.2 0.2]);
h(1) = surface(xc,zc,-yc,'FaceColor', 'red'); %noise cone
h(2) = surface(z,y,0.5*x,'FaceColor', 'blue'); %right wing
h(3) = surface(-z,y,0.5*x,'FaceColor', 'yellow');%left wing
h(4) = surface(x,-1.5*z,0.5*y,'FaceColor', 'green'); %main body
h(5) = surface(xc,(1.5*yc)-1.3,z*.5,'FaceColor', 'red'); %tail
view(3);
x_temp = get(h(1),'xdata'); % get x values
y_temp = get(h(1),'ydata');
z_temp =get(h(1),'zdata');
xc_new=x_temp.*rot_mat;
%zc_new=
%yc_new=
I can get the x,y, and z value by using the commands
x_temp = get(h(1),'xdata');
y_temp = get(h(1),'ydata');
z_temp = get(h(1),'zdata');
The error I get is due to the matrix being nonconforment but how can I adjust the matrix correctly?
error: test_object_matrix_rot: product: nonconformant arguments (op1 is 2x21, op2 is 3x3).
The error is with the line xc_new=x_temp.*rot_mat;
PS: I'm using Octave 5.0.91 which is like Matlab
YOu are messing up a lot of things......in fact I would say, you have made your work complex. YOu should straight away work on matrices to rotate to new positons instead of arrays and picking them from the figure.
This line:
x_temp = get(h(1),'xdata'); % get x values
giving you a 2*21 array and your rot_mat is 3X3.....you cannot multiply them. YOu need to pick (x,y,z) and multiply this point with rotation matrix to get the point shifted. Check the below pseudo code.....yo can develop your logic with the below example code.
t = 0:0.1:1;
[X,Y,Z] = cylinder((t));
%% Rotation
th = pi/2 ;
Rx = [1 0 0 ; 0 cos(th) -sin(th) ; 0 sin(th) cos(th)] ;
P0 = [X(:) Y(:) Z(:)] ;
P1 = P0*Rx ;
X1 = reshape(P1(:,1),size(X)) ;
Y1 = reshape(P1(:,2),size(X)) ;
Z1 = reshape(P1(:,3),size(X)) ;
figure
hold on
surf(X,Y,Z)
surf(X1,Y1,Z1)
view(3)

Visualize conic with Matlab or Octave

I like to visualize conics with Matlab or Octave. The (general) conic is given by the equation 0 = ax² + bxy + cy² +dxz +eyz+f*z² for a point p=(x,y,z). How can I plot this with Matlab or octave if I know the parameters a,b,c,d,e and f? Or respectively, how can I find the points that satisfy this equation?
Since you are asking for the conics, I understand that you are probably referring to the 2D contours of the general conic equation. I will also cover how to visualize this equation in other different ways.
For all the following examples, I have set the conic constants so that I obtain a hiperboloid.
My code is written in MATLAB syntax. If you are using Octave, it might differ slightly.
Visualizing 2D Conics with CONTOUR
I have isolated z in terms of x and y, from the general conic equation:
z = (1/2)*(-d*x-e*y±sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
Since z is a piecewise function due to (± sqrt), I need to make sure that I plot both hemispheres. I designate z1 for +sqrt, and z2 for -sqrt.
Finally, I plot the contours for z1 and z2 that will yield the set of conics in 2D. This conics will be circles of different radius.
Code:
clear all;
clc;
% Conic constants.
a = 1;
b = 0;
c = 1;
d = 0;
e = 0;
f = -1;
% Value for x and y domain.
v = 10;
% Domain for x and y.
x = linspace(-v,v);
y = linspace(-v,v);
% Generate a 2D mesh with x and y.
[x,y] = meshgrid(x,y);
% Isolate z in terms of x and y.
z1 = (1/2)*(-d*x-e*y+sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
z2 = (1/2)*(-d*x-e*y-sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
% Find complex entries in z.
i = find(real(z1)~=z1);
j = find(real(z2)~=z2);
% Replace complex entries with NaN.
z1(i) = NaN;
z2(j) = NaN;
figure;
subplot(1,2,1);
% Draw lower hemisphere.
contour(x,y,z1,'ShowText','on');
% Adjust figure properties.
title('2D Conics: Lower hemishphere');
xlabel('x-axis');
ylabel('y-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10]);
subplot(1,2,2);
% Draw upper hemisphere.
contour(x,y,z2,'ShowText','on');
hold off;
% Adjust figure properties.
title('2D Conics: Upper hemishphere');
xlabel('x-axis');
ylabel('y-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10]);
Output:
Visualizing 3D Conics with CONTOUR3
Same as on the previous example, but now we plot the set of conics in 3D.
Code:
clear all;
clc;
% Conic constants.
a = 1;
b = 0;
c = 1;
d = 0;
e = 0;
f = -1;
% Value for x and y domain.
v = 10;
% Domain for x and y.
x = linspace(-v,v);
y = linspace(-v,v);
% Generate a 2D mesh with x and y.
[x,y] = meshgrid(x,y);
% Isolate z in terms of x and y.
z1 = (1/2)*(-d*x-e*y+sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
z2 = (1/2)*(-d*x-e*y-sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
% Find complex entries in z.
i = find(real(z1)~=z1);
j = find(real(z2)~=z2);
% Replace complex entries with NaN.
z1(i) = NaN;
z2(j) = NaN;
% Lower hemisphere. Draw 20 conics.
contour3(x,y,z1,20);
hold on;
% Upper hemisphere. Draw 20 conics.
contour3(x,y,z2,20);
hold off;
% Adjust figure properties.
title('3D Conics');
xlabel('x-axis');
ylabel('y-axis');
zlabel('z-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10 -10 10]);
Output:
Visualizing Quadrics with ISOSURFACE
I have isolated f in terms of x, y and z, from the general conic equation, and renamed it to f_eq:
f_eq = -(a*x.^2+b*x.*y+c*y.^2+d*x.*z+e*y.*z)./z.^2;
Finally, I obtain the set of points that satisfy the equation f_eq = f, which is in fact an isosurface that yields a quadric; in this example a hiperboloid.
Code:
clear all;
clc;
% Conic constants.
a = 1;
b = 0;
c = 1;
d = 0;
e = 0;
f = -1;
% Value for x, y and z domain.
v = 10;
% Domain for x ,y and z.
x = linspace(-v,v);
y = linspace(-v,v);
z = linspace(-v,v);
% Generate a 3D mesh with x, y and z.
[x,y,z] = meshgrid(x,y,z);
% Evaluate function (3D volume of data).
f_eq = -(a*x.^2+b*x.*y+c*y.^2+d*x.*z+e*y.*z)./z.^2;
% Draw the surface that matches f_eq = f.
p = patch(isosurface(x,y,z,f_eq,f));
isonormals(x,y,z,f_eq,p)
p.FaceColor = 'red';
p.EdgeColor = 'none';
% Adjust figure properties.
title('Quadric');
xlabel('x-axis');
ylabel('y-axis');
zlabel('z-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10 -10 10]);
camlight left;
lighting phong;
Output:

plotting a bullet-nose curves

I would like to plot this function of Two Variables you can find it here
$$z^2=t(t-i) \Longleftrightarrow x^2+y^2=4x^2y^2 \Longleftrightarrow y=\dfrac{\pm x}{\sqrt{4x^2-1}} \mbox{ with } |x|>\frac{1}{2}$$
would someone show me step by step how to plot this in matlab
is there any script or toolbox in http://www.mathworks.com/matlabcentral/fileexchange
which make plot of that kind of curves quickly
this is by geogebra
This is by wolframe
You can use symbolic variables with ezplot.
syms x y % makes symbolic variables
h1 = ezplot('-4*x^2*y^2+x^2+y^2'); % plots the equation
axis equal
set(h1, 'Color', 'k');
Or you can define a function,
f = #(x,y) -4.*x.^2.*y.^2+x.^2+y.^2;
h1 = ezplot(f);
set(h1, 'Color', 'k');
It won't be easy to have the axis in the middle, I hope it's not necessary to have that.
Edit
You can download oaxes here
syms x y
h1 = ezplot('-4*x^2*y^2+x^2+y^2');
axis equal
set(h1, 'Color', 'm');
oaxes('TickLength',[3 3],'Arrow','off','AxisLabelLocation','side',...
'LineWidth',1)
Edit
For 3D plot try this,
% First line provides a grid of X and Y varying over -5 to 5 with .5 as step-size
[X,Y] = meshgrid(-5:.5:5);
% instead of "=0", Z takes the values of the equation
Z = -4 .* X.^2 .* Y.^2 + X.^2 + Y.^2;
surf(X,Y,Z) % makes a 3D plot of X,Y,Z
You can also try contourf(X,Y,Z) for 2D plot.