3d-plotting surface 2x^2 + 3y^2 + z^2 = 6 - matlab

I was trying to plot the above surface in octave/matlab and ran into the this problem.
My code is as follows:
x = linspace(-sqrt(3),sqrt(3),1000);
y = linspace(-sqrt(2),sqrt(2),1000);
z = sqrt(6-2*x.^2-3*y.^2);
surf(x,y,z)
I got the error:
error: mesh: X, Y, Z arguments must be real.
I understand this was because some (x,y)s would result in negative 6-2*x.^2-3*y.*2, but I don't know how to tackle this because I can't trim either part of x or y. Any one can help? Thanks

It depends what you want to do with the non-real values of z.
One thing you could do is to set all these values to zero or NaN (as per #hbaderts' comment):
z = sqrt(6-2*x.^2-3*y.^2);
z( imag(z)~=0 ) = NaN;
One more thing though: your code might have a problem because z is a length-1000 vector, and you want it to be a 1000x1000 matrix. You should use meshgrid() on x and y to get two-dimensional matrices everywhere:
x = linspace(-sqrt(3),sqrt(3),1000);
y = linspace(-sqrt(2),sqrt(2),1000);
[xx,yy] = meshgrid(x,y);
z = sqrt(6-2*xx.^2-3*yy.^2);
z( imag(z)~=0 ) = NaN;
surf(xx,yy,z,'edgecolor','none')
(thanks #LuisMendo for the 'edgecolor','none' suggestion for better visualization.)
Running the above piece of code on octave gives this plot:

Related

Why can't I use 'scatter3' here?

[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
scatter3(X,Y,Z)
Error using scatter3 (line 64)
X, Y and Z must be vectors of the same length.
Matlab R2018b windows x64
As shown in the documentation, X, Y, Z must be vectors. (When you enter an article on mathworks from Googling, say, "matlab scatter3", you will first see the syntax for the function. Blue text means hyperlink. All the inputs are linked to the bottom of the page where their exact typing is defined.)
The reason is (probably) as follows.
As stated in the documentation, scatter3 puts circles (or other symbols of your choice if you modify the graphic object) on 3D coordinates of your choice. The coordinates are the ith element of X, Y, Z respectively. For example, the x-coordinate of the 10th point you wish to plot in 3D is X(10).
Thus it is not natural to input matrices into scatter3. If you know X(i), Y(i), Z(i) are indeed the coordinates you want to plot for all i, even though your X, Y, Z are not vectors for some reason, you need to reshape X, Y, Z.
In order to reshape, you can simply do scatter3(X(:), Y(:), Z(:)) which tells Matlab to read your arrays as a vectors. (You should look up in what order this is done. But it is in the intuitive way.) Or you can use reshape. Chances are: reshape is faster for large data set. But ofc (:) is more convenient.
The following should work:
[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
X = X(:);
Y = Y(:);
Z = Z(:);
scatter3(X,Y,Z)
scatter3 needs vectors, not matrices as far as I can see here
this is my result:
If you want to use meshgrid without reshaping the matrices you have to use plot3 and the 'o' symbol. So you can get a similar result with:
plot3(X,Y,Z,'o')
EDIT:
A question that arose in association with this post was, which of the following methods is more efficient in terms of computation speed: The function reshape(X,[],1), suggested by me, or the simpler colon version X(:), suggested by #Argyll.
After timing the reshape function versus the : method, I have to admit that the latter is more efficient.
I added my results and the code I used to time both functions:
sizes = linspace(100,10000,100);
time_reshape = [];
time_col = [];
for i=1:length(sizes)
X = rand(sizes(i)); % Create random squared matrix
r = #() ResFcn(X);
c = #() ColFcn(X);
time_reshape = [time_reshape timeit(r)/1000] % Take average of 1000 measurements
time_col = [time_col timeit(c)/1000] % Take average of 1000 measurements
end
figure()
hold on
grid on
plot(sizes(2:end), time_col(2:end))
plot(sizes(2:end), time_reshape(2:end))
legend("Colon","Reshape","Location","northwest")
title("Comparison: Reshape vs. Colon Method")
xlabel("Length of squared matrix")
ylabel("Average execution time [s]")
hold off
function res = ResFcn(X)
for i = 1:1000 % Repeat 1000 times
res = reshape(X,[],1);
end
end
function res = ColFcn(X)
for i = 1:1000 % Repeat 1000 times
res = X(:);
end
end

MATLAB "gradient" function swaps x and y dimensions?

I am trying to compute the gradient of a 3-D matrix using MATLAB (version 2016a). If I type "help gradient" it says the following:
"HX and HY can either be scalars to specify
the spacing between coordinates or vectors to specify the
coordinates of the points. If HX and HY are vectors, their length
must match the corresponding dimension of F." (emphasis mine).
Here is a sample code:
x = 1:30; nx = length(x);
y = 1:62; ny = length(y);
z = 1:23; nz = length(z);
F = rand(nx,ny,nz);
[FX,FY,FZ] = gradient(F,x,y,z);
Here, I am inputting vectors x, y, and z to compute the gradient. These are vectors and it says in the help that HX and HY must have a length matching the corresponding dimension of F. The x-dimension of F has length nx. So the x vector also has length nx. It should work, according to the help.
However, I get an error:
Index exceeds matrix dimensions.
Error in gradient (line 112)
h = h(3:n) - h(1:n-2);
When I dig a little deeper into the "gradient" function I come across this line in the "parse_inputs" embedded function:
% Swap 1 and 2 since x is the second dimension and y is the first.
loc = v;
if ndim > 1
loc(2:-1:1) = loc(1:2);
end
What is going on here?
Why does MATLAB swap the x and y dimensions?
If I do the following code and swap the x and y vectors, then the code works.
x = 1:30; nx = length(x);
y = 1:62; ny = length(y);
z = 1:23; nz = length(z);
F = rand(nx,ny,nz);
[FX,FY,FZ] = gradient(F,y,x,z);
I just don't understand why. I've looked around on stack overflow but can't find any answer to the question.
In any case, it seems that the help is somewhat misleading because you actually need to swap x and y to make the function work...
It is not gradient that swaps dimensions, it's everything else...
MATLAB indexes arrays as (row,column), and array sizes are given in the same order, as [height,width].
However, whenever the documentation to any function mentions x and y, the x is always horizontal and y vertical. So in a way MATLAB indexes as (y,x).
The right way to fix your code is:
x = 1:30; nx = length(x);
y = 1:62; ny = length(y);
z = 1:23; nz = length(z);
F = rand(ny,nx,nz); % <<< Note the order here!
[FX,FY,FZ] = gradient(F,x,y,z);
Personal opinion: This is terribly confusing, I have seen lots of people making mistakes because of this, and have made quite a few mistakes myself as well. But they are very consistent with this in the MATLAB documentation, using (i,j) or (x,y) depending on the required order -- with the exception of ndgrid, where the documentation uses x1,x2,x3,... but should really have used a different letter.

' vectors must be the same length' error

I've got a 250 x 250 image, I want to have a scatter plot of the intensity of every pixel and its nearest neighborhood. This is my code:
I = imread(image);
i = [1,249];
j = [1,250];
X = I(i,j);
Y = I(i+1,j);
scatter(X,Y);
why do I get the " X and Y vectors must be the same length" error? They are the same length !
Because scatter(X, Y) is only used for vectors, not matrix. In your example, both X and Y are 2x2 matrices, not vectors.
From its documentation:
scatter(X,Y) displays circles at the locations specified by the vectors X and Y. This type of graph is also known as a bubble plot.
Edit: if you want to plot matrix, use plotmatrix() instead:
plotmatrix(X,Y)
Scatter(X,Y) is used only for vectors as herohuyongtao correctly mentioned. You could try to do the following:
m = 250;
X = I(m+1:end);
Y = I(1:end-m);
scatter(X,Y);
You convert your image matrix I into a vector X while ignoring the first column and in a vector Y while ignoring the last column. X(n) is thus the neighbour of Y(n) on the right side.
I hope this helps!

MATLAB - Using for loops find all the combinations of x^2 + y

I have two for loops like this:
for x = 1:1:15
for y = 1:1:15
values(x,y) = x^2 + y
end
end
This allows me to calculate x^2 + y for every combination of x and y if they are integers.
However, what if I want to calculate x^2 + y for decimals as well?
So something like this:
for x = 0:0.1:15
for y = 0:0.1:15
????? = x^2 + y
end
end
Could anyone help me find a method that can calculate all the possibilities of x^2 + y if x and y are decimals so cannot be used as index references anymore?
use meshgrid, matlab's built in rectangular grid in 2-D and there's no need to loop!
[y x]=meshgrid(0:0.1:15)
values=x.^2+y
to visualize this:
imagesc(values);
title('values=x^2+y'); axis square
xlabel('x'); ylabel('y'); colorbar;
axis xy;
set(gca,'XTick',1:10:151,'YTick',1:10:151);
set(gca,'XTickLabel',0:1:15,'YTickLabel',0:1:15);
EDIT:
mdgrid is also fine the only thing to note is that [y x]=meshgrid... is the same [x y]=ndgird...
Use:
[x y] = ndgrid(0:0.1:15);
values = x.^2 + y;
Issues with the other answers:
#inigo's answer will change the order of x and y compared to your initial example (by using meshgrid rather than ndgrid.
#NominSim's answer has to go to extra effort get d_x from x
#mecid's answer has to count columns and rows separately (also there is no ++ operator in MATLAB). If I was to go down #mecid's route I would use the following.
x = 0:.1:15;
y = 0:.1:15;
values = zeros(numel(x),numel(y));
for xnum = 1:numel(x)
for ynum = 1:numel(y)
values(xnum,ynum) = x(xnum)^2 + y(ynum);
end
end
Since it generated some discussion, from the documentation (within MATLAB, not in the online documentation) on the difference between meshgrid and ndgrid:
meshgrid is like ndgrid except that the order of the first two input and output arguments are switched (i.e., [X,Y,Z] = meshgrid(x,y,z) produces the same result as [Y,X,Z] = ndgrid(y,x,z)) ... meshgrid is also limited to 2D or 3D.
for x =1:0.1:15
for y=1:0.1:15
values(x*10-10, y*10-10) =x^2+y;
end
end
Why not loop on integers from 1 to 151 then calculate the decimal to be used? Then you can still use index references.
i.e.
for x = 1:1:151
for y = 1:1:151
d_x = x / 10.0 - 0.1
d_y = y / 10.0 - 0.1
values(x,y) = d_x^2 + d_y
end
end
(Forgive me if my syntax is slightly off, haven't used MATLAB in a while).

Plotting a 3D graph of `sqrt(1+1/(kr)^2)`

I am trying to plot the following equation in MATLAB:
ratio = sqrt(1+1/(kr)^2)
With k and r on the x and y axes, and ratio on the z axis. I used meshgrid to create a matrix with values for x and y varying from 1 to 10:
[x,y] = meshgrid([1:1:10],[1:1:10]);
The problem now is to create values for z. I've tried to just type the whole equation in, but that gives this result:
>> Z = sqrt(1+1/(x .* y)^2)???
Error using ==> mldivide
Matrix dimensions must agree.
So what I did is go to through the whole process manually, which produces the right graph in the end:
z = z^2;
z = 1 ./ z;
z = 1 + z;
z = sqrt(z);
mesh(x,y,z)
Is there a more elegant way to do this? Or a way to type in the equation and let MATLAB handle the rest?
Try this:
Z = sqrt(1+1./(x .* y).^2);
surf(Z);
The problem that you had is related to using / instead of ./ and ^2 instead of .^2