Defining surfaces not just in terms of z - matlab

I have three different surfaces and I want to display all of them in one figure.
The problem is, that I have one surface defined in terms of z (means that I got x and y values and a grid which specifies the z-values for each combination) and two other ones which are defined in terms of x. This means that there exist various z-values for one x,y-pair.
My idea was:
figure
surf(x,y,zgrid)
hold on
surf(x,ygrid,z)
surf(x,ygrid2,z)
hold off
I hoped MATLAB would manage it by itself but it doesn't.
Do you have any ideas how to get the wanted results? I want to display all of them in one plot to show the cross-sections.
Here is an image of how it should more or less look like:
If there is a more beautiful method to display this, please let me know.

You didn't specify what exactly was going wrong, but I'll hazard an educated guess that you got an error like the following when you tried to plot your second surface:
Error using surf (line 82)
Z must be a matrix, not a scalar or vector.
I'm guessing your x, y, and z variables are vectors, instead of matrices. The surf function allows for the X and Y inputs to be vectors, which it then expands into matrices using meshgrid. It doesn't do this for the Z input, though.
It's best practice, in my opinion, to just use matrices for all your inputs anyway. Here's an example where I do this (using meshgrid) to plot three surfaces of a cube:
% Top surface (in z plane):
[x, y] = meshgrid(1:10, 1:10);
surf(x, y, 10.*ones(10), 'FaceColor', 'r');
hold on;
% Front surface (in y plane):
[x, z] = meshgrid(1:10, 1:10);
surf(x, ones(10), z, 'FaceColor', 'b');
% Side surface (in x plane):
[y, z] = meshgrid(1:10, 1:10);
surf(ones(10), y, z, 'FaceColor', 'g');
axis equal
And here's the plot:

Related

How can i plot an ellipse and parabola together in Matlab?

I need to plot a parabola and ellipse. However the ellipse is giving me trouble. Can anyone help? The equations are: y = -5*x^2 + 2 and (x^2/16) + (y^2/2) = 4
I've tried this code but obviously I feel like like it isn't right.
x = linspace(-5, 5);
y1 = (x.^2/16) + (y.^2/2) - 1;
y2 = -5*x.^2 +2;
figure(1)
plot(x, y1)
hold on
plot(x, y2)
hold off
Firstly, you did not define a range variable x. Secondly, the ellipse won't pass the vertical line test and can't be plotted like a regular function f(x). Thirdly, your equation y1 = (x.^2/16) + (y.^2/2) - 1; is non-sensical because you have y on each side.
You could correct your method by defining a range variable x1 and x2 that each have appropriate ranges for the functions your plotting. What I mean by this is that you probably don't want the same range for each function, because the ellipse is undefined over most of the range that the parabola is defined. To plot the ellipse using f(x) you could observe that there are + and - values that are identical, using this fact you could plot your ellipse by two functions one to represent the top half and one to represent the bottom half, each of these would pass the vertical line test.
OR
You could utilize ezplot and have a nice time with it because it makes your life easier. Here is a solution.
ezplot('x^2/16+y^2/2-4'); axis equal; hold on
ezplot('-5*x^2+2-y')
There are multiple ways to plot an ellipse, e.g. you could also use a parametric representation of the equation.
In your approach though, when plotting functions using plot(x,y) command, you need to express your dependent variable (y) through independent variable (x). You defined the range for x, which is what you substitute into your equations in order to find y's. While for the parabola, the dependency of y from x is obvious, you forgot to derive such a relationship for the ellipse. In this case it will be +-sqrt((1 - x^2/16)*2). So in your approach, you'll have to take into account both negative and positive y's for the same value of x. Also there's discrepancy in your written equation for the ellipse (=4) and the one in Matlab code (=1).
x = linspace(-5, 5);
y1 = sqrt((1 - x.^2/16)*2);
y2 = -5*x.^2 +2;
figure(1)
plot(x, real(y1), 'r', x, -real(y1), 'r')
hold on
plot(x, y2)
hold off
Since the ellipse has real y's not on the whole x domain, if you want to plot only real parts, specify real(y1) or abs(y1) (even though Matlab does it for you, too). You can also dismiss complex numbers for certain x when computing y1, but you'll need a for-loop for that.
In order to make things simpler, you can check the function fimplicit, ezplot is not recommended according to Matlab's documentation. Or if you want to plot the ellipse in a parametric way, fplot will work, too.
Another (more classic) approach for parametric plotting is given here already, then you don't need any other functions than what you already use. I think it is the simplest and most elegant way to plot an ellipse.
You will not be able to generate points for the ellipse using a function f(x) from a Cartesian linspace range. Instead, you can still use linspace but for the angle in a polar notation, from 0 to 2*pi. You should also be able to easily adjust radius and offset on both axis on the cos and sin expressions.
x = linspace(-5, 5);
y2 = -5*x.^2 +2;
figure(1)
clf;
plot(x, y2)
hold on
a = linspace(0,2*pi);
x2 = 4*cos(a);
y2 = sqrt(2)*sin(a);
plot(x2, y2)
xlim([-5,5]);
ylim([-5,5]);
hold off

How do I create a colormap from an existing data set in Matlab?

I currently have a 2-D contour plot in Matlab from an existing data set. I made an [x,y] mesh grid and used this mesh grid and z-data to produce a 2-d contour plot using contourf(x, y, z). My goal is to reproduce this same data as a colormap, with smooth color gradients, rather than as a 2-d contour plot, with distinct color bands.
I have tried using imagesc(x, y, z) with [x,y] as a mesh grid and without. I ended up with an error function "Attempt to execute SCRIPT imagesc as a function:"
x = 0.1:0.1:1
y = 0.1:0.1:1
[X, Y] = meshgrid( x , y )
Z = #data#
contourf( X , Y , Z )
title
xlabel
ylabel
I'm not quite sure what's going wrong with your attempt to use imagesc... When I used your x and y and defined Z=sin(X*20)+sin(Y*20); and ran imagesc(x,y,Z) I got
Looking at the error message you're getting I suspect that you have a script somewhere saved as imagesc which is somehow overwriting the imagesc function. Try running edit imagesc and see what comes up, is it a function?
Now as far as making this smooth looking you have two options. Firstly you could just use a higher density of points as opposed to a 10x10 grid. For example
x = linspace(0,1,1000);
y = linspace(0,1,1000);
[X, Y] = meshgrid( x , y );
Z=sin(X*20)+sin(Y*20);
imagesc(x,y,Z)
gives
Alternatively, if you want/need to stick with the low density of points you can use pcolor(X,Y,Z) and then set shading interp which gives

Slice contour graphic at given level

I have the following function (z) that should output a graphic which if sliced at f(x,y) = 0.001 the result image should be a message.
I wrote this code but I`m unable to slice it right
[x,y] = meshgrid(-1.5:0.3:1.5,-2.5:0.5:2.5) ;
z=exp(-4*x.^2-2*y.^2)*cos(8*x)+exp(-3*((2*x+1)/2).^2-6*y.^2);
% meshc (x,y,z, [0.001 0.001]);
meshc (x,y,z);
What did i miss?
You are likely looking for the countour function instead of meshc. meshc plots a contour plot under a mesh plot, but you don't need a mesh plot to view the message. In fact, the countour docs show an example of how to only plot a specific level:
contour(x, y, z, [0.001 0.001])
I also suspect that your function is not defined correctly. exp(...) * cos(...) should probably read exp(...) .* cos(...):
The poor granularity leads me to believe that the sample spacing should be decreased (i.e., the grid should be made finer):
[x,y] = meshgrid(-1.5:0.003:1.5,-2.5:0.005:2.5);
Contouring the original function with the finer spacing also shows why I think * should probably be .* in the expression:
[x,y] = meshgrid(-1.5:0.003:1.5,-2.5:0.005:2.5);
z=exp(-4*x.^2-2*y.^2)*cos(8*x)+exp(-3*((2*x+1)/2).^2-6*y.^2);
contour(x, y, z, [0.001 0.001])
Unless the message is a count of sausage shapes, I think that the .* version is more likely to contain useful information (looks like HI).
You'll want to use contour rather than meshc to plot the intersection of your mesh with 0.001 so that you can specify exactly at what value you'd like to compute the contour.
contour(x, y, z, [0.001 0.001]);
If you do want to use meshc, you can use the output which contains a handle to the contour plot to set the LevelList property to your desired value
h = meshc(x, y, z);
set(findobj(h, 'type', 'contour'), 'LevelList', [0.001 0.001])
As far as getting an intelligible message out, I guess intelligent is in the eye of the beholder

Multiple 1D plots in a 3D plot

I have a 2D equation, for example y = sin(x + t). For each unique value of t, I would like to plot a 1D realization of y. For example, if x = 0:0.1:2*pi and t = 1:10, for each value of t I would like to plot y = sin(x + t) for x = 0:0.1:2*pi. Basically, I would like to have lines along one direction for each value of t.
Is there a way I can do this in MATLAB?
Would something like a waterfall plot be beneficial for your case? Given a vector of x coordinates, for each unique value of y (in your case t), it would plot a one-dimensional realization of that curve. First, you would generate a 2D grid of coordinates X, Y where each row of X and Y together would be a vector of x coordinates for one realization of y and you'd plot all of these together in one plot.
Something like this:
[t,x] = meshgrid(0:0.1:2*pi, 1:10);
waterfall(t, x, sin(x + t));
view(-50, 50); % Adjust for a better view
xlabel('x'); ylabel('t'); zlabel('y'); % Add axis labels
We get this plot:
If you don't desire the "vertical" baselines that you see in the plot, then you can get away with using surf by specifying some additional properties to it:
[t,x] = meshgrid(0:0.1:2*pi, 1:10);
surf(t, x, sin(x + t), 'FaceColor', 'white', 'EdgeColor', 'interp', 'MeshStyle', 'row');
view(-50, 50);
xlabel('x'); ylabel('t'); zlabel('y');
The FaceColor and EdgeColor attributes are there to mimic what you see in the waterfall plot. Each visualization has a white face and the amplitude colours are interpolated. What is important is the MeshStyle attribute where you want to display the edges of the plot row wise. The default way for mesh is to show both rows and columns, so you'll visualize your plot in a grid like pattern, which is not what you want. Setting MeshStyle to row will simulate the waterfall plot but without the vertical baselines that you see in that plot.
You'll get:

How to interpolate and plot a 4-Dimensional hamburger?

I have solved the heat equation in octave via finite difference and produced the following 3-D plot whose point colors correspond to the temperatures in each element of my three dimensional hamburger.
My computational resources limit the resolution at which I may solve my burger. Thus the only way to get the plot I want is to make my scatter3 points huge blobs of color and it looks kind of bad.
[x,y,z] = meshgrid(1:nx,1:ny,1:nz) % Defines a grid to plot on
scatter3(x(:), y(:), z(:), 40, burgermatrix(:), 's', 'filled')% Point color=value
What I want is a nice gorgeous smooth rectangular prism like this:
So I figure I need to somehow interpolate between the 3D points that I have. Can anyone help me figure out how to do this?
I might be missing something obvious, but here's the example from octave's help slice:
[x, y, z] = meshgrid (linspace (-8, 8, 32));
v = sin (sqrt (x.^2 + y.^2 + z.^2)) ./ (sqrt (x.^2 + y.^2 + z.^2));
slice (x, y, z, v, [], 0, []);
[xi, yi] = meshgrid (linspace (-7, 7));
zi = xi + yi;
slice (x, y, z, v, xi, yi, zi);
shading interp; %addition by me
Isn't this exactly what you need? You have your grid (x,y,z), your solutions (T), so you just need to plot it slicing along [0 0 1] etc. Something like
[xi yi]=meshgrid(unique(x),unique(y));
slice (x, y, z, T, xi, yi, max(z(:))*ones(size(xi)));
and the same for cuts along the two other axes. (Obviously the unique calls should be substituted with the vectors you already have from which you constructed the 3d mesh in the first place.)
NOTE: By the way, you should really consider changing the default (jet) colormap. I was yesterday enlightened by a colleague about the viridis colormap made by the SciPy people, see for instance this post and video link therein. Their reasoning is overwhelming, and their colormap is beautiful. This should define it: viridis, although I haven't tried it myself yet.
(If it wasn't for jet, I'd tell you that your temperature profile seems strongly 1d. Do you happen to have periodic boundary conditions along the vertical walls and homogeneous (i.e. constant) boundary conditions along the horizontal ones?)