How can I plot a meshgrid in 2D? - matlab

I have this code, which takes a meshgrid, and applies a transformation to every point:
function [newx, newy] = transform(x, y)
newx = 10 * x + y*y;
newy = 5 * y;
end
[x, y] = meshgrid(1:5, 1:5);
[u, v] = arrayfun(#transform, x, y);
I want to plot the new mesh in 2D. The closest I can get is to do so in 3D by adding a Z component of 0:
mesh(u, v, zeros(size(u)))
How can I get matlab/octave to just show this plot on a 2d set of axes?

Maybe I'm missing the point here, but what's wrong with a simple plot(u,v,'b-x',u',v','b-x')?

Related

How plot a two-dimensional function in three-dimensional space with MATLAB?

I want to plot a two-dimensional function of the polar coordinates r and theta in three-dimensional cartesian coordinates. I have that (sorry about bad maths formatting, LaTeX not compatible, it seems)
f(r,theta) = r/2 * (cos(theta - pi/4) + sqrt(1 + 1/2 * cos(2*theta)))
Converting r and theta to cartesian coordinates
x = r * cos(theta), y = r * sin(theta)
Further, the domain is -1<r<1 and 0<theta<2 * pi, which I define by
r = -1:2/50:1;
and
theta = 0:2*pi/50:2*pi;
giving me two vectors of the same dimensions.
I can define the x and y values used for plotting as row vectors by
x = r. * cos(theta);
and
y = r. * sin(theta);
So now I need to define the z values, which will depend on the values of x and y. I thought I should make a 101x101 where each matrix element contains a data point of the final surface. But how should I do this? I thought about using a double for loop:
for i=1:numel(r)
for j=1:numel(theta)
z(i,j) = r(i)/2 .* cos(theta(j) - pi/4) + r(i).*sqrt(1 + 1/2 * cos(2.*theta(j)));
end
end
Then simply surf(z)
While this definitely gives me a surface, it gives me the incorrect surface! I don't know what is happening here. The incorrect surface is given in Figure 1, while the correct one is given in Figure 2. Can anyone help me out? For reference, the correct surface was plotted with GeoGebra, using
A = Function[<expression 1>, <Expresison 2>, <Expression 3>, <var 1>, <start>, <stop>, <var 2>, <start>, <stop>]
Figure 1. Incorrect surface.
Figure 2. Correct surface.
As others have said, you can use meshgrid to make this work.
Here's your example using gridded r and theta and an anonymous function to replace the double loop:
r = -1:2/50:1;
theta = 0:2*pi/50:2*pi;
% define anonymous function f(r,theta)
f = #(r,theta) r/2 .* (cos(theta - pi/4) + sqrt(1 + 1/2 .* cos(2.*theta)));
% generate grids for r and theta
[r, theta] = meshgrid(r,theta);
% calculate z from gridded r and theta
z = f(r,theta);
% convert r,theta to x,y and plot with surf
x = r.*cos(theta);
y = r.*sin(theta);
surf(x,y,z);
You need to use meshgrid to get matrix coordinates if you want to use surf. Taking your x and y (lower case), call
[X,Y] = meshgrid(x,y);
Then X and Y (upper case) will have the same values as you gave it, but laid out in the two-dimensional array as expected by surf. Loop over the indices here and compute your Z, which should have all(size(Z) == size(X)).
https://www.mathworks.com/help/matlab/ref/meshgrid.html

How to get the pixel indices from the world coordinates with a calibrated camera in matlab

I have calibrated my camera and I have now cameraParams, rotation and translation matrices (R ,t)
I know that there is a way to get the world coordinates from the pixel indices by the function "pointsToWorld(__)" but I want to do the otherwise , I can't find anything about that in the Matlab help !
So I don't know what to do, any suggestions?
Currently you have to do that yourself. If you have R and t, you can use the cameraMatrix function to compute the camera projection matrix P. Then you can compute the projection of a world point into the image as follows:
P = cameraMatrix(cameraParams, R, t);
p = [X, Y, Z, 1] * P;
x = p(1) / p(3);
y = p(2) / p(3);
X, Y, and Z are the world coordinates. x and y are the image coordinates in pixels.

Retain meshgrid structure when subsetting a meshgrid

When I subset an array constructed from meshgrid, I cannot work out how to keep its meshgrid structure. Thus, you cannot use it in a call to mesh or surface. I will demonstrate this in my example of constructing the unit sphere.
Possible alternate titles for this question:
How do you make the top half of the meshgrid sphere from scratch in Matlab?
How do you use mesh to plot a subset of a meshgrid?
This is motivated using the following toy example of constructing a sphere of unit radius in Matlab from scratch, so that it is like the one generated by:
[x, y, z] = sphere(100)
mesh(x, y, z)
Using the equation for a sphere:
Define a meshgrid and z to be:
x = linspace(-1, 1, 201);
y = linspace(-1, 1, 201);
[x, y] = meshgrid(x, y);
z = sqrt(1 - x.^2 - y.^2);
So far so good, except z takes imaginary values where the sphere does not exist over the xy-plane, that is, anywhere outside of the unit circle.
A call to mesh now returns an error:
>> mesh(x, y, z)
Error using mesh (line 58)
X, Y, Z, and C cannot be complex.
Thus, a logical step is to remove all complex values:
% get logical vector index where real z is
LI = z == real(z)
x = x(LI)
y = y(LI)
z = z(LI)
But now x, y, and z are no longer 3d arrays, and calling mesh gives another error:
>> mesh(x, y, z)
Error using mesh (line 58)
Z must be a matrix, not a scalar or vector.
So, in general I have no idea how to preserve the meshgrid structure when subsetting the data. Hence, I can't generate the top half of this sphere from scratch.
In general, you can "exclude" values from plotting while maintaining the matrix structure by using NaN value. In your case, try this:
LI = z == real(z);
z(~LI) = NaN;
mesh(x,y,z);

How do I rotate a cylinder in matlab using matrices?

So, I'm really new to MatLab, and I was trying to make a cylinder using [X Y Z] = cylinder;.Then I got these 3 matrices: X Y and Z that generate an actual cylinder if I mesh them. Now, what I need help to do is rotate this [X Y Z] cylinder 90 degrees clockwise in the y axis. I know there is this command called rotate but my teacher wants me to use rotation and translation matrices explicitly. How could I create these matrices and multiply them to the cylinder?Is there a better way to make the cylinder? I'm really not used to matlab, if you could explain in a detailed form, I would be very thankful.
You should use a rotation matrix for the R^3 which serves as a linear map. There are built in fucntions in MATLAB for that but I guess you are not allowed to use them.
Here is a quick and dirty solution:
[X Y Z] = cylinder;
figure;
surf(X,Y,Z);
% set up rotation matrix:
angle_in_degrees = 90;
angle_in_rad = angle_in_degrees* pi/180;
rotationMatrix = [cos(angle_in_rad) 0 sin(angle_in_rad); 0 1 0; -sin(angle_in_rad) 0 cos(angle_in_rad)];
% get points at the two rings and rotate them separately:
positionOld1 = [X(1,:)',Y(1,:)',Z(1,:)'];
positionOld2 = [X(2,:)',Y(2,:)',Z(2,:)'];
positionNew1 = positionOld1*rotationMatrix;
positionNew2 = positionOld2*rotationMatrix;
% reassemble the two sets of points into X Y Z format:
X = [positionNew1(:,1),positionNew2(:,1)];
Y = [positionNew1(:,2),positionNew2(:,2)];
Z = [positionNew1(:,3),positionNew2(:,3)];
figure;
surf(X,Y,Z);

Drawing a surface with x,y,z points

I have a list of x, y, z in this form:
-0.2894 1.2835 0.5405
-0.8171 -0.3034 0.1824
2.7864 0.5506 0.0037
I could plot using plot3(x,y,z, '*') and it works fine.
Now I would like to draw a surface, but when I do:
>> surf(x,y,z)
??? Error using ==> surf at 78
Z must be a matrix, not a scalar or vector.
How should I draw it?
I suggest you do a Delaunay triangulation of the x,y values, and then use z as height for a surface plot:
x = randn(100,1);
y = randn(100,1);
z = (exp(-x.^2-y.^2));
tri = delaunay(x,y);
trisurf(tri,x,y,z)
EDIT
Since you seem to have problems with your Matlab version, here's an alternative: use griddata to interpolate your data onto a regular grid, so that you can use surf for plotting.
x = randn(100,1);
y = randn(100,1);
z = (exp(-x.^2-y.^2));
[xx,yy]=meshgrid(-2:0.1:2,-2:0.1:2);
zz = griddata(x,y,z,xx,yy);
dfig,surf(xx,yy,zz)