旋转一个点使其与方向矢量平行会产生错误的矢量。为什么?
Rotating a point to be parallel to a direction vector delivers wrong vector. Why?
我需要旋转一个矢量,该矢量的起点为 (0,0,0),终点为给定点,以便与给定的方向矢量平行。出于这个原因,我的代码基于以下答案:
I guess by "parallel" you intend "pointing in the same direction."
We may as well rotate (d,e,f)
in the plane spanned by v=(d,e,f) and w=(a,b,c). The axis of rotation >would be around a vector perpendicular to this plane such as a=v×w, which >you'd normalize to a unit length vector u. Finally, we'd need the angle of >rotation θ, which can be retrieved from v⋅w=∥v∥∥w∥cos(θ) by solving for θ.
Then following the scheme for using quaternions to perform rotations, the >quaternion you're looking for is q=cos(θ/2)+usin(θ/2). The transformation >x→qxq−1 moves v to point in the same direction as w.
我已经设法实现了这个,尽管通过可视化结果,很明显它们不是平行的。
## Example code
def get_unit_vector(vector):
return vector / np.linalg.norm(vector)
def get_angle_between_vectors(vector1, vector2):
unit_vector_1 = get_unit_vector(vector1)
unit_vector_2 = get_unit_vector(vector2)
angle = np.arccos(np.dot(unit_vector_2, unit_vector_1))
return min(angle, np.pi-angle)
def rotate_point(point, direction):
# get the axis and normalize it
axis = np.cross(point, direction)
norm_axis = get_unit_vector(axis)
angle = get_angle_between_vectors(point, direction)
q = np.cos((angle/2))+norm_axis*np.sin(angle/2)
q = get_unit_vector(q)
new_point = (q*point)*np.conj(q)
new_angle = get_angle_between_vectors(new_point, direction)
if new_angle != 0:
q = np.cos((np.pi-angle / 2)) + norm_axis * np.sin(np.pi-angle / 2)
new_point = (q * point) * (np.conj(q))
return new_point
这里是结果:
如前所述,我希望橙色和绿色矢量是平行的,但它们不是。有没有我遗漏的步骤?
所以经过一些修改我设法得到了想要的输出。我从 .
得到了乘法函数
def get_unit_vector(vector):
return vector / np.linalg.norm(vector)
def get_angle_between_vectors(vector1, vector2):
unit_vector_1 = get_unit_vector(vector1)
unit_vector_2 = get_unit_vector(vector2)
angle = np.arccos(np.dot(unit_vector_2, unit_vector_1))
return min(angle, np.pi-angle)
def quaternion_conjugate(q):
first = q[0]
q_prime = -1*q
q_prime[0] = first
return q_prime
def quaternion_multiply(quaternion1, quaternion0):
w0, x0, y0, z0 = quaternion0
w1, x1, y1, z1 = quaternion1
return np.array([-x1 * x0 - y1 * y0 - z1 * z0 + w1 * w0,
x1 * w0 + y1 * z0 - z1 * y0 + w1 * x0,
-x1 * z0 + y1 * w0 + z1 * x0 + w1 * y0,
x1 * y0 - y1 * x0 + z1 * w0 + w1 * z0], dtype=np.float64)
def rotate_point(point, direction):
axis = np.cross(point, direction)
norm_axis = get_unit_vector(axis)
angle = -get_angle_between_vectors(point, direction)
q = np.array([np.cos((angle/2)),*(norm_axis*np.sin(angle/2))])
point_as_q = np.array([0,*point])
q3 = quaternion_multiply(q, point_as_q)
q3 = quaternion_multiply(q3, quaternion_conjugate(q))
new_point = q3[1:]
return new_point
我需要旋转一个矢量,该矢量的起点为 (0,0,0),终点为给定点,以便与给定的方向矢量平行。出于这个原因,我的代码基于以下答案:
I guess by "parallel" you intend "pointing in the same direction."
We may as well rotate (d,e,f) in the plane spanned by v=(d,e,f) and w=(a,b,c). The axis of rotation >would be around a vector perpendicular to this plane such as a=v×w, which >you'd normalize to a unit length vector u. Finally, we'd need the angle of >rotation θ, which can be retrieved from v⋅w=∥v∥∥w∥cos(θ) by solving for θ.
Then following the scheme for using quaternions to perform rotations, the >quaternion you're looking for is q=cos(θ/2)+usin(θ/2). The transformation >x→qxq−1 moves v to point in the same direction as w.
我已经设法实现了这个,尽管通过可视化结果,很明显它们不是平行的。
## Example code
def get_unit_vector(vector):
return vector / np.linalg.norm(vector)
def get_angle_between_vectors(vector1, vector2):
unit_vector_1 = get_unit_vector(vector1)
unit_vector_2 = get_unit_vector(vector2)
angle = np.arccos(np.dot(unit_vector_2, unit_vector_1))
return min(angle, np.pi-angle)
def rotate_point(point, direction):
# get the axis and normalize it
axis = np.cross(point, direction)
norm_axis = get_unit_vector(axis)
angle = get_angle_between_vectors(point, direction)
q = np.cos((angle/2))+norm_axis*np.sin(angle/2)
q = get_unit_vector(q)
new_point = (q*point)*np.conj(q)
new_angle = get_angle_between_vectors(new_point, direction)
if new_angle != 0:
q = np.cos((np.pi-angle / 2)) + norm_axis * np.sin(np.pi-angle / 2)
new_point = (q * point) * (np.conj(q))
return new_point
这里是结果:
如前所述,我希望橙色和绿色矢量是平行的,但它们不是。有没有我遗漏的步骤?
所以经过一些修改我设法得到了想要的输出。我从
def get_unit_vector(vector):
return vector / np.linalg.norm(vector)
def get_angle_between_vectors(vector1, vector2):
unit_vector_1 = get_unit_vector(vector1)
unit_vector_2 = get_unit_vector(vector2)
angle = np.arccos(np.dot(unit_vector_2, unit_vector_1))
return min(angle, np.pi-angle)
def quaternion_conjugate(q):
first = q[0]
q_prime = -1*q
q_prime[0] = first
return q_prime
def quaternion_multiply(quaternion1, quaternion0):
w0, x0, y0, z0 = quaternion0
w1, x1, y1, z1 = quaternion1
return np.array([-x1 * x0 - y1 * y0 - z1 * z0 + w1 * w0,
x1 * w0 + y1 * z0 - z1 * y0 + w1 * x0,
-x1 * z0 + y1 * w0 + z1 * x0 + w1 * y0,
x1 * y0 - y1 * x0 + z1 * w0 + w1 * z0], dtype=np.float64)
def rotate_point(point, direction):
axis = np.cross(point, direction)
norm_axis = get_unit_vector(axis)
angle = -get_angle_between_vectors(point, direction)
q = np.array([np.cos((angle/2)),*(norm_axis*np.sin(angle/2))])
point_as_q = np.array([0,*point])
q3 = quaternion_multiply(q, point_as_q)
q3 = quaternion_multiply(q3, quaternion_conjugate(q))
new_point = q3[1:]
return new_point