I'm trying to rotate a point cloud about an axis by an angle without distorting its shape. It's being deformed whenever I rotate it by a non-orthogonal angle (anything not a multiple of 90 degrees). I saw this post and I made sure to use a unit vector as the axis, but it's still being distorted.
import numpy as np
import math
import matplotlib.pyplot as plt
def rotation_matrix(axis, radian):
ax, ay, az = axis[0], axis[1], axis[2]
s = math.sin(radian)
c = math.cos(radian)
u = 1 - c
return ( ( ax*ax*u + c, ax*ay*u - az*s, ax*az*u + ay*s ),
( ay*ax*u + az*s, ay*ay*u + c, ay*az*u - ax*s ),
( az*ax*u - ay*s, az*ay*u + ax*s, az*az*u + c ) )
def get_ax():
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_ylim3d(-5, 5)
ax.set_xlim3d(-5, 5)
ax.set_zlim3d(-5, 5)
return ax
# torus parameters
major_radius = 1.5
minor_radius = 2.9
density = 15
theta = np.linspace(0, 2 * np.pi, density)
phi = np.linspace(0, 2*np.pi, density)
Theta, Phi = np.meshgrid(theta, phi)
# parametric equations for the torus
x = (major_radius + minor_radius * np.cos(Theta)) * np.cos(Phi)
y = (major_radius + minor_radius * np.cos(Theta)) * np.sin(Phi)
z = minor_radius * np.sin(Theta)
# coordinate array
original_points = np.array([x.flatten(), y.flatten(), z.flatten()])
angles = np.array([0, 45, 90])
for angle in angles:
# get R matrix for unit vec axis and angle
R = rotation_matrix([0,1,0], np.radians(angle))
# rotate points by R and plot
rotated_points = np.dot(R, original_points)
rotated_x = rotated_points[0]
rotated_y = rotated_points[1]
rotated_z = rotated_points[2]
ax = get_ax()
ax.scatter(rotated_x, rotated_y, rotated_z, color='black')
plt.show()
Here it is at 45 degrees. It's supposed to be a symmetric shape. It's easier to see the distortions when you tilt your head.
Rotation is good, it's just the viewing method that's distorting: "ax.set_aspect('equal', adjustable='box')" fixes it.