7 views (last 30 days)

Hello everyone,

I am havign a bit of a headache and am a little stuck. I would really appreciate any help.

I have some 3D points (in a cube shape shown as blue in the figure). I would like to rotate these points such that one face of the cube is normal to a line passing through the origin of the system (red dot in the figure) and the centre of the cube. I have tried a few things but it doesn't quite work and some edge cases throw the system way off.

In the example below it looks about right but when you rotate the right hand figure you can see that the cube is not quite normal to the line.

Hopefully the script below will help explain what I mean.

%% Variables for Matlab question

% Centre of system

coords_source_xyz= [-0.5,-0.5,0; -0.5,0,0;-0.5,0.5,0;0,-0.5,0;0,0,0;0,0.5,0;0.5,-0.5,0;0.5,0,0;0.5,0.5,0];

array_centre =[0,0,0];

% Grid of unrotated cloud points.

sample_grid_coords_x = linspace(2,3,10);

sample_grid_coords_y = linspace(-2,-3,10);

sample_grid_coords_z = linspace(2,3,10);

% Centre of un-rotated point cloud

centre_grid_x = mean(sample_grid_coords_x);

centre_grid_y = mean(sample_grid_coords_y);

centre_grid_z = mean(sample_grid_coords_z);

% NDGRID OF points

[sample_X, sample_Y, sample_Z] = ndgrid(sample_grid_coords_x, sample_grid_coords_y, sample_grid_coords_z);

% Distance from centre of array to centre of unrotated point cloud.

array_to_grid_x = centre_grid_x-array_centre(1);

array_to_grid_y = centre_grid_y-array_centre(2);

array_to_grid_z = centre_grid_z-array_centre(3);

array_to_grid_xy = sqrt((array_to_grid_x^2) + (array_to_grid_y^2));

% Move the point cloud back to the origin temporarily.

sample_X = sample_X - array_to_grid_x;

sample_Y = sample_Y - array_to_grid_y;

sample_Z = sample_Z - array_to_grid_z;

% Step 1 - Calculate rotation angle about Y.

rot_y_axis_deg = atand(array_to_grid_z / array_to_grid_x);

rot_y_axis_deg(isnan(rot_y_axis_deg))=0;

% Rotate points about Y axis first.

X_rot_1 = sample_X*cosd(rot_y_axis_deg) + sample_Z*sind(rot_y_axis_deg);

Y_rot_1 = sample_Y;

Z_rot_1 = sample_Z*cosd(rot_y_axis_deg) - sample_X*sind(rot_y_axis_deg);

% Step 2 - Calculate rotation angle about Z.

rot_z_axis_deg = atand(array_to_grid_x / array_to_grid_y);

rot_z_axis_deg(isnan(rot_z_axis_deg))=0;

% Rotate points about Z axis second.

X_rot_2 = X_rot_1*cosd(rot_z_axis_deg) - Y_rot_1*sind(rot_z_axis_deg);

Y_rot_2 = X_rot_1*sind(rot_z_axis_deg) + Y_rot_1*cosd(rot_z_axis_deg);

Z_rot_2 = Z_rot_1;

% Move them back to their original centre

X_rot_2 = X_rot_2+centre_grid_x;

Y_rot_2 = Y_rot_2+centre_grid_y;

Z_rot_2 = Z_rot_2+centre_grid_z;

figure(1)

subplot(1,2,1);

% Location of array points

scatter3(coords_source_xyz(:,1), coords_source_xyz(:,2), coords_source_xyz(:,3),'k', 'filled'); daspect([1 1 1]); title('Un-Rotated');

hold on

% Location of centre of array

scatter3(array_centre(1), array_centre(2), array_centre(3),'r', 'filled'); daspect([1 1 1]);

% Location of sample grid points - unrotated

scatter3(sample_X(:)+array_to_grid_x, sample_Y(:)+array_to_grid_y, sample_Z(:)+array_to_grid_z, 'b');

% Line connecting centre of array and centre of grid

x = [array_centre(1), centre_grid_x];y = [array_centre(2), centre_grid_y]; z=[array_centre(3), centre_grid_z]

plot3(x*1.5, y*1.5, z*1.5); hold off

subplot(1,2,2);

% Location of array points

scatter3(coords_source_xyz(:,1), coords_source_xyz(:,2), coords_source_xyz(:,3),'k', 'filled'); daspect([1 1 1]); title('Rotated');

hold on

% Location of centre of array

scatter3(array_centre(1), array_centre(2), array_centre(3),'r', 'filled'); daspect([1 1 1]);

% Location of sample grid points - rotated

scatter3(X_rot_2(:), Y_rot_2(:), Z_rot_2(:), 'b');

% Line connecting centre of array and centre of grid

x = [array_centre(1), centre_grid_x];y = [array_centre(2), centre_grid_y]; z=[array_centre(3), centre_grid_z]

plot3(x*1.5, y*1.5, z*1.5); hold off

Matt J
on 21 Oct 2020

Edited: Matt J
on 21 Oct 2020

If I can choose the missing rotation angle freely, then here is one solution.

% Centre of system

coords_source_xyz= [-0.5,-0.5,0; -0.5,0,0;-0.5,0.5,0;0,-0.5,0;0,0,0;0,0.5,0;0.5,-0.5,0;0.5,0,0;0.5,0.5,0];

array_centre =[0,0,0];

% Grid of unrotated cloud points.

sample_grid_coords_x = linspace(2,3,10);

sample_grid_coords_y = linspace(-2,-3,10);

sample_grid_coords_z = linspace(2,3,10);

[sample_X, sample_Y, sample_Z] = ndgrid(sample_grid_coords_x, sample_grid_coords_y, sample_grid_coords_z);

Cube=[sample_X(:), sample_Y(:), sample_Z(:)];

% Perform rotation

cube_centre=mean(Cube,1); %Cube center

ray=cube_centre-array_centre;

R=normalize([ray(:),null(ray)],1,'norm'); %rotation matrix

C = num2cell( (Cube-cube_centre)*R.'+ cube_centre, 1);

[X_rot, Y_rot, Z_rot] = deal(C{:});

%%%% Plot %%%%

figure(1)

% Location of array points

scatter3(coords_source_xyz(:,1), coords_source_xyz(:,2), coords_source_xyz(:,3),'k', 'filled'); daspect([1 1 1]); title('Rotated');

hold on

% Location of centre of array

scatter3(array_centre(1), array_centre(2), array_centre(3),'r', 'filled'); daspect([1 1 1]);

% Location of sample grid points - rotated

scatter3(X_rot, Y_rot, Z_rot, 'b');

% Line connecting centre of array and centre of grid

x = [array_centre(1), cube_centre(1)];

y = [array_centre(2), cube_centre(2)];

z= [array_centre(3), cube_centre(3)];

plot3(x*1.5, y*1.5, z*1.5);

hold off

Matt J
on 21 Oct 2020

You're quite welcome. You might also find this Fle Exchange submission useful,

if you decide you need to correct the rotation of the cube about the oblique axis, L.

Opportunities for recent engineering grads.

Apply TodayFind the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!
## 5 Comments

## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074638

⋮## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074638

## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074648

⋮## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074648

## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074658

⋮## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074658

## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074668

⋮## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074668

## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074673

⋮## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/620603-how-to-rotate-3d-cube-so-that-one-face-is-normal-to-a-given-axis#comment_1074673

Sign in to comment.