MATLAB - How to rotate an orbit/sphere using rotation matrix? - matlab

I am trying to rotate an "orbit" using rotation matrix given below:
[cos(angle) -sin(angle) 0;
sin(angle) cos (angle) 0;
0 0 1 ]
First thing I thought I should do was to use sphere():
[x y z] = sphere;
Then concatenate x, y, and z together in a vector:
xyz = [x; y; z];
rotatMat = [cos(angle) -sin(angle) 0; sin(angle) cos (angle) 0; 0 0 1 ];
multiply rotation matrix and xyz to rotate an orbit:
rotated = rotatMat .* xyz;
However, xyz turns out to be 62x22 dimension while my rotatMat is only 3x3 so I cannot multiply them together.
How can i fix this issue?
Thank you in advance.

You have to use the * operator for matrix multiplication, and not .* which is for element-wise multiplication.
Moreover, your xyz matrix should be of size n-by-3 (and not 62-by-22) and you have to use xyz*rotatMat' to match the dimensions correctly. Alternatively, you can have xyz of size 3-by-n and use the syntax rotatMat*xyz.
Best,

xyz = [x(:) y(:) z(:)].'; %'// put x, y, z as rows of a matrix
xyz_rotated = rotatMat*xyz %// use matrix multiplication
x_rotated = reshape(xyz_rotated(1,:), size(x)); %// reshape transformed rows
y_rotated = reshape(xyz_rotated(2,:), size(x));
z_rotated = reshape(xyz_rotated(3,:), size(x));

Related

How to find principal eigen direction?

I am trying to generate points within ellipsoid and then trying to fit with smooth ellipsoid surfaces. The goal is to fit with unknown data where i have to find value of a,b and c in 3 principal axes.
Rinv should be equivalent to pc. But what i am getting pc in different order. So i have to find correct order to rotate my data to matlab coordinate.
a=3;
b=5;
c=1;
index=1;
for i=1:500000
x=10*rand-5;
y=10*rand-5;
z=10*rand-5;
if ((x^2/a^2) + (y^2/b^2) + (z^2/c^2) -1) <0
C(index,:)=[x,y,z];
index=index+1;
end
end
theta=pi/4; phi=pi/6; omega = pi/3;
Rx= [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Ry= [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rz= [cos(omega) -sin(omega) 0; sin(omega) cos(omega) 0; 0 0 1];
R= Rz*Ry*Rx;
Rinv = inv(R);
X = C*R;
[pc,val]=eig(X'*X); E=diag(val);
[sa,sb]= sort(pc*E, 'descend'); sb
order = [2,3,1];
nC= X*pc(:,order);
plot3(nC(:,1),nC(:,2),nC(:,3),'.')
hold on
[x, y, z] = ellipsoid(0,0,0,a,b,c,30);
hSurface=surf(x, y, z, 'FaceColor','blue','EdgeColor','none');
alpha(0.5)
Specially in this line nC= X*pc(:,order);
I am finding order manually. Can any one tells (1) how to find pc order correctly. (2) Value of a,b,c for unknown data set here "[x, y, z] = ellipsoid(0,0,0,a,b,c,30)"
Thanks
To compute the values of a,b,c from the eigen-space, you just need to compute the radius of the eigen-space projected ellipsoid. This is trivial because the ellipsoid is axis-oriented in eigen-space (which I assume is the only reason you are doing this in the first place). Just get the max and min in each direction!
nC= X*pc;
plot3(nC(:,1),nC(:,2),nC(:,3),'r.')
hold on
a2=(max(nC(:,1))-min(nC(:,1)))/2;
b2=(max(nC(:,2))-min(nC(:,2)))/2;
c2=(max(nC(:,3))-min(nC(:,3)))/2;
[x, y, z] = ellipsoid(0,0,0,a2,b2,c2,30);
hSurface=surf(x, y, z, 'FaceColor','blue','EdgeColor','none');
alpha(0.5)
axis equal
Note that this code actually makes order obsolete.

Rotating and working on MATLAB 3D objects

How do you rotate 3D objects around each of the three axes when coordinates are of MATLAB style (X, Y and Z kept in different arrays).
This code is a start. I think I have found the rotation matrix (for pi/2 rotation around x), here it is called rotX90_2. But how should rotX90_2 operate on X, Y, Z?
[X,Y,Z] = cylinder;
% rotX90_1 = makehgtform('xrotate',pi/2) gives
rotX90_1 = ...
[1 0 0 0;
0 0 -1 0;
0 1 0 0;
0 0 0 1];
rotX90_2 = rotX90_1(1:3, 1:3);
% Here rotX90_2 should operate on [X,Y,Z] in order to ...
% rotate it 90 degrees around x, but how is this done?
% == What code should be put here to rotate the cylinder? ==
surf(X,Y,Z);
I have just started using MATLAB. As I understand, the basic ways to manipulate 3D graphics are to either operate on the X, Y, Z, like here or, you can first run graphics routines like h = surf(X, Y, Z); and then operate on graphics objects, using f.ex. hgtransform.
It is convenient to translate and scale using X, Y, Z. - You just add and multiply by scalars. But I ask this question to understand how to rotate.
If you operate on the graphic objects, on the other hand, you can use the function hgtransform. But you must then first create other objects, since hgtransform does not operate directly on the graphic objects, as I understand. (Except functions like rotatex(h, angle). F.ex, I have not found a corresponding "translatex(h, distance)". That surprised me. Maybe I didn't look well enough.)
OK I am new to this. Any simple, practical pointers how to easily rotate, scale and translate MATLAB 3D coordinates/objects (around the coordinate system axes) would be appreciated.
Edit:
According to Prakhar's answer below, which works, the code needed to fill the gap above is the following. Thank you, Prakhar.
[row, col] = size(X);
coordinates = [reshape(X, [row*col, 1]), reshape(Y, [row*col, 1]), reshape(Z, [row*col, 1])];
rC = coordinates * rotX90_2;
X = reshape(rC(:, 1), [row, col]);
Y = reshape(rC(:, 2), [row, col]);
Z = reshape(rC(:, 3), [row, col]);
Let's say R is the appropriate 3x3 rotation matrix.
coordinates = [X Y Z];
rotatedCoordinates = coordinates * R;
(Assuming X, Y, and Z are column vectors of same size)
Now, you can get the new X, Y, and Z coordinates from rotatedCoordinates as rotatedCoordinates(:, 1), rotatedCoordinates(:, 2), and rotatedCoordinates(:, 3), respectively.
EDIT: Another alternative when X, Y, Z are 2D matrices:
[X, Y, Z] = cylinder;
[row, col] = size(X);
coordinates = [reshape(X, [row*col, 1]), reshape(Y, [row*col, 1]), reshape(Z, [row*col, 1])];
rC = coordinates*R;
Xn = reshape(rC(:, 1), [row, col]);
Yn = reshape(rC(:, 2), [row, col]);
Zn = reshape(rC(:, 3), [row, col]);

How to map a matrix to a coordinate and plot it

I have been struggling with this problem for a while and I would appreciate if anyone can help me out. I am able to generate a 10 by 10 matrix and have it randomly assign "1"s in the matrix. My goal is to plot a "star" at the location of each element in the vector that has a value of "1", but I can't seem to figure out how to map the vector to a x-y coordinate system. The code I wrote below generates a plot of 100 stars at each cell and also generates a vector "v", but I don't know how I can link the plot to the vector that instead of having 100 "star"s in my plot, I have however many that there is a value of "1" at the corresponding location of the element.
Thanks!!
David
davidtongg#gmail.com
close all
clear all
clc
a=10;b=10;
v = zeros(a,b);
xy = int32(randi(a, 100, 2));
z = randi(1, 100, 1); % 100 values.
indexes = sub2ind([a, b], xy(:,1), xy(:,2))
v(indexes) = z
m=length(v);
ctr=0;
for i=1:m^2
x_cor(i)=(i-(floor(i/m)*m))*200-100;
y_cor(i)=(floor(i/m)+1)*200-100;
for j=1:m
if i==j*m
x_cor(i)=((i-(floor(i/m)*m))*200-100)+(2*m*100);
y_cor(i)=(floor(i/m))*200-100;
end
end
end
figure(1)
plot(x_cor,y_cor,'*');
grid on
I may of course have misinterpreted this because that code is confusingly complicated, but this is what I think you're after.
For an axb matrix with a random number of ones:
v = randi([0 1], a, b);
Or for a specific number n of ones, in random locations:
v = zeros(a, b);
idx = randi([1 numel(v)], n, 1);
v(idx) = 1; % linear indexing into a matrix
Then to plot them in arbitrarily scaled coordinates:
[y x] = find(v);
x = x * xscale + xoffset;
y = y * yscale + yoffset;
plot(x, y, '*');
Or the really cheaty way:
spy(v);
You can do it easily taking into account that plot(A) , where A is a matrix, plots the columns of the matrix vs their index, and that NaNs are not plotted:
v =[ 1 0 0 0
1 1 0 0
0 0 0 1
1 1 1 1
0 1 1 0 ]; %// example data
v2 = double(v); %// create copy; will be overwritten
v2(~v2) = NaN; %// change zeros to NaNs
plot(bsxfun(#plus, fliplr(v2.'), 0:size(v,1)-1) ,'b*')
%'// transpose and flip from left to right.
%// Add 1 incrementally to each column to have all of them "stacked" in the plot
axis([0 size(v,2)+1 0 size(v,1)+1]) %// set axis limits
set(gca,'xtick',1:size(v,2),'ytick',1:size(v,1)) %// set ticks
grid

MatLab--How would I generate an n-sided shape wher n >= 4

I'm new to Matlab but I know a bit about programming.
For class, we have been asked to generate a matrix that gives the vertices of a two dimensional n-sided shape where n>=4. Then, generate the vectors to connect the vertices. We were also given a hint: a vector for each segment can be found by adding the vectors drawn from the origin to each of two adjacent vertices.
I know how to create a matrix using A = [1 1; 1 2; 2 2; 2 1] but I'm not sure how to draw the vectors given this or any other matrix.
The plot() function looks promising, but I'm unsure how to use it with the matrix.
Thank you for any suggestions.
Btw, I'm using Matlab 2011a
I'm not exactly sure how your matrix represents your shape but you might for example let the x-coordinates of the shape be the first column of your array, then let the y-coordinates be the 2nd column, like:
A = [1 1; 1 2; 2 2; 2 1];
x = A(:,1);
y = A(:,2);
fill(x,y,'g');
axis([0 3 0 3]);
axis square;
Which in your case plots a square from the matrix A:
Or construct something a little more complicated like a pentagon:
theta = [0:pi/2.5:2*pi];
x = sin(theta);
y = cos(theta);
% your matrix is then:
B(:,1) = x;
B(:,2) = y;
B
figure;fill(x,y,'g');
axis square;
Which gives:
If you just want to plot the outline with plot (not fill the interior with fill), just remember you have to repeat the initial point at the end so that the polygonal line is closed:
A = [1 1; 1 2; 2 2; 2 1];
B = [A; A(1,:) ]; %// repeat first row at the end
plot(B(:,1),B(:,2))
axis equal %// same scale on both axes
axis([min(x)-.5 max(x)+.5 min(y)-.5 max(y)+.5]) %// larger axes for better display

loop through element of meshgrid matlab

I am trying to loop through a meshgrid to create a matrix of vectors. If I have:
[x,y] = meshgrid(1:2,1:2)
can someone explain looping through each element to get a matrix which equals:
matrix =
[x(1,1) y(1,1)] [x(1,2) y(1,2)]
[x(2,1) y(2,1)] [x(2,2) y(2,2)]
thanks in advance
If you want a 2x4 matrix with the values of x and y interleaved, this will work:
matrix = zeros(2,4);
matrix(:,[1 3]) = x;
matrix(:,[2 4]) = y;
If instead you want a 2x2x2 matrix with x and y stacked, use cat:
matrix = cat(3,x,y);
This concatenates x and y along the third dimension.
Maybe you could arrange each pair of coordinates as one row:
[x,y] = meshgrid(1:2,1:2)
xy = [x(:) y(:)];
Thus:
>> xy =
1 1 %# xy(1,:) = [x(1,1),y(1,1)]
1 2 %# xy(2,:) = [x(2,1),y(2,1)]
2 1 %# xy(3,:) = [x(1,2),y(1,2)]
2 2 %# xy(4,:) = [x(2,2),y(2,2)]