Creating a cylinder with axis centered differently - matlab

I know Matlab has a function called cylinder to create the points for a cylinder when number of points along the circumference, and the radius length. What if I don't want a unit cylinder, and also don't want it to center at the default axis (for example along z-axis)? What would be the easiest approach to create such a cylinder? Thanks in advance.

The previous answer is fine, but you can get matlab to do more of the work for you (because the results of cylinder separate x,y,z components you need to work a little to do the matrix multiplication for the rotation). To have the center of base of the cylinder at [x0 y0 z0], scaled by [xf yf xf] (use xf=yf unless you want an elliptic cylinder), use:
[x y z] = cylinder;
h=mesh(x*xf+x0,y*yf+y0,z*zf+z0)
If you also want to rotate it so it isn't aligned along the z-axis, use rotate. For example, to rotate about the x-axis by 90 degrees, so it's aligned along the y-axis, use:
rotate(h,[1 0 0],90)

Multiply the points by your favourite combination of a scaling matrix, a translation matrix, and a rotation matrix.

Related

Rotate 3D Surface until Level on MATLAB

I have yet to start creating the code because I am a little stuck and would like some help to guide me in the right direction. I have to use MATLAB to solve the following issue:
I am given the x,y,z of a 3D surface (about 300 points) that is tilted by an arbitrary angle theta about the x axis and tilted by an arbitrary angle alpha about the y axis. The goal is to tilt the surface so that all of the z values are the same, meaning that the surface is level.
I have tried using rotation matrices, but it has not worked out how I expected. Any suggestions and ideas are greatly appreciated.
It's not elegant, but you could try brute forcing the solution by rotating the graph in set increments about both the x and y axes. Then, simply take the solution where the maximum number of z-coordinates fall within a narrow range. This would mean that the surface is approximately level.
A similar approach but a bit more formal would be to calculated the vector parallel to the surface and knowing the direction of this vector, the rotation parameters got really easy to obtain by c=norm((a,b,c))*cos(angle).
If you have a plane-like surface, you could fit it the to a plane equation a*x+b*y+c*z+d=0 and the vector normal to plane is (a,b,c).
If you have another type of surface -- that is normally what one has -- you may still find the vector of the plane useful, as the plane may be parallel to the surface or may give the direction to compare to made the rotation.
Depending on how you implement it, it will just rotate having point of rotation at the origin (0,0,0). If you plane is far from the origin, both figures will be far from each other. A simple translation can solve it.
With some random point around a plane i got it:
With the code that i used.
n=300;
x= 20.*rand(n,1)-10; %interval
y= 20.*rand(n,1)-10; %interval
%if you want to plot a plane
z=(2*(y+rand(n,1)*0.3)+2*(x+rand(n,1)*0.3)-7)/.4+rand(n,1)*0.3;
figure()
plot3(x,y,z,'.')
hold on
%here i put the plane average data on zero
Centerplane=[mean(x) mean(y) mean(z)];
xc=x-mean(x);
yc=y-mean(y);
zc=z-mean(z);
%get the 'a' and 'b' component of the plane equation (z=a*x +b*y +d)
A=[xc yc]; B=zc;
r=A\B %%%Matlab!
r = vrrotvec( (([r(1) r(2) 1]/norm([r(1) r(2) 1]))),[0 0 1]);
RM=vrrotvec2mat(r); %get the rotation matrix
rdata=[xc,yc,zc]*RM; %rotate data
% put in the proper position back
rt_c_x=rdata(:,1)+mean(x);
rt_c_y=rdata(:,2)+mean(y);
rt_c_z=rdata(:,3)+mean(z);
%and plot
plot3(rt_c_x,rt_c_y,rt_c_z,'c.')
A=[x y]; B=z; %default data
r=A\B %%%Matlab!
r = vrrotvec( (([r(1) r(2) 1]/norm([r(1) r(2) 1]))),[0 0 1]);
RM=vrrotvec2mat(r); %get the rotation matrix
rdata2=[x,y,z]*RM; %rotate data
%and plot
plot3(rdata2(:,1),rdata2(:,2),rdata2(:,3),'g.')
xlabel('X')
ylabel('Y')
zlabel('Z')

Rotate nxn matrix around x-axis by an angle theta in Matlab

I have nxn matrix in 2D space; I would like to rotate the matrix around the x-axis using matlab. Where the x-axis pass through the center of the matrix (pass through the point [n/2 n/2].
I found the Matlab function B = rot90(A) which rotate the matrix A by 90 degree. But I’m looking for a method that rotate matrix A by any given angle (e.g. 30, 45, 170 degree) around the x-axis.
You can as well try imrotate(). This function is from the Image Processing Toolbox, but since its main input is a matrix (either real or logical) it'll work also for non picture-related matrices (I've tried with a magic matrix).
The syntax is:
B=imrotate(A,theta);
where A is you matrix, B is the rotated version of A and theta is the rotation in degrees. The rotation is performed in counterclockwise direction around its center point; to rotate the matrix clockwise, specify a negative value for theta.

Calculate image rotation based on old and new positions of two points

I have images of faces in different positions. I want to rotate them, to make the line connecting the eyes always be horizontal. But I don't know how to do this in MATLAB.
And how can I calculate the angle of rotation?
Descriptive drawing of problem:
If you already have the locations of the eyes, then it's easy :) Here's an outline:
%// left eye - right eye
pos = [ 30 90 %// X
80 40]; %// Y
%// The angle equals the arctangent of dy/dx
angle = atan2(diff(pos(2,:)), diff(pos(1,:)));
%// Rotate in the opposite direction
img = imrotate(img, -angle);
Since you seem to have the Image Processing Toolbox, you can also look into the built-in landmark-based registration functions (especially if your transform is not limited to pure rotation), in particular cpselect with a syntax like:
cpselect(moving,fixed)
And then use fitgeotrans to construct the geometrical transform and imwarp to warp the moving image.

Creating a mask with 3 point in Matlab?

I have this 3 points (x,y) and I need to obtain a mask with a triangle where vertices is the points. I should respect some parameters, like the pixel pitch and I need a grid from the minimum x cordinate to the maximum x coordinate (the same for the y).
I tried to do this in matlab with the function poly2mask but the problem is the resultant image: when I have negative coordinates, I cannot see the polygon.
So I tried to center the polygon but I loose the original coordinates and I cannot have they back again because I need to do some elaboration on the image.
How I can obtain a mask triangle from 3 points without modifying the points and respecting the parameters?

Extract arbitrarily rotated plane of data from 3D array as 2D array

I have a 3D matrix of data in matlab, but I want to extract an arbitrarily rotated slice of data from that matrix and store it as a 2D matrix, which I can access. Similar to how the slice() function displays data sliced at any angle, except I would also like to be able to view and modify the data as if it were an array.
I have the coordinates of the pivot-point of the plane as well as the angles of rotation (in x, y and z axis), I have also calculated the equation of the plane in the form:
Ax + By + Cz = D
and can extract a 3D matrix containing only the data that fall on that plane, but I don't know how to then convert that into a simple 2D array.
Another way of doing it would be to somehow rotate the source matrix in the opposite direction of the angle of the plane, so as to line up the plane of data with the XY axis, and simply extract that portion of the matrix, but I do not know if rotating a matrix like that is possible.
I hope this hasn't been answered elsewhere, I've been googling it all day, but none of the problems seem to exactly match mine.
Thanks
You can take a look at the code here. I think the function is similar to what you are trying to solve.
The function extracts an arbitrary plane from a volume given the size of the plane, the center point of the plane, and the plane normal, i.e. [A,B,C]. It also outputs the volumetric index and coordinate of each pixel on the plane.
Aha! May have just solved it myself.
To produce the plane equation I rotate a normal vector of (0,0,1) using rotation matrices and then find D. If I also rotate the following vectors:
(1,0,0) //step in the x direction of our 2D array
and
(0,1,0) //step in the y direction of our 2D array
I'll have the gradients that denote how much my coordinates in x,y,z have to change before I step to the next column in my array, or to the next row.
I'll mock this up ASAP and mark it as the answer if it works
EDIT: Ok slight alteration, when I'm rotating my vectors I should also rotate the point in 3D space that represents the xyz coordinates of x=0,y=0,z=0 (although I'm rotating around the centre of the structure, so it's actually -sizex/2,-sizey/2,-sizez/2, where size is the size of the data, and then I simply add size/2 to each coordinate after the rotations to translate it back to where it should be).
Now that I have the gradient change in 3D as I increase the x coordinate of my 2D array and the gradient change as I increase the y coordinate, I can simply loop through all possible x and y coordinates (the resulting array will be 50x50 for a 50x50x50 array, I'm not sure what it will be for irregular sizes, which I'll need to work out eventually) in my 2D array and calculate the resulting 3D coordinates on my plane in the data. My rotated corner value serves as the starting point. Hooray!
Just got to work out a good test for this encompassing all angles and then I'll approve this as an answer