如何获取已旋转3D点的平移和旋转?

1 投票
1 回答
54 浏览
提问于 2025-04-14 15:20

我有五个三维点,分别是A、B、C、D和E。这些点不在同一个平面上,也不是在一条直线上。我可以在另一个坐标系中找到点A'和B',并且保持原来A和B之间的距离不变。仅凭这些信息,我能否找到点C'、D'和E',使得它们与A'的距离、角度和关系和原来的AC、AD等一样呢?

我尝试了各种方法,包括旋转矩阵,但都没有成功。我想找到一个旋转矩阵,可以把A映射到A',把B映射到B',然后用这个矩阵来得到C'、D'和E',但结果不理想。

C_prime = A_prime + (C - A)
D_prime = A_prime + (D - A)
E_prime = A_prime + (E - A)

(A_prime、A、C、D和E都是三维坐标的numpy数组)。这样得到的C'、D'和E'与A'的距离是正确的,但与B'的距离就不对了。如果用B和B'代替A和A',结果又是相反的。我该如何把这两个条件结合起来呢?我在使用python和numpy。

1 个回答

0

一种可能的图像来自于 C_prime = A_prime + R(C - A) 等等,这里 R 是一个旋转矩阵,它可以把 AB 转换成 A_prime B_prime,而 C 是其他任意点。旋转矩阵通常可以通过这两个向量之间的角度和它们的叉积形成的轴来找到……不过如果它们是共线的,叉积就会变成0,这种情况下就不能用这个方法了。

需要注意的是,这种变换并不是唯一的,因为你可以在 A_prime B_prime 周围随意旋转,而仍然保持距离和相对角度不变。

你还必须确保 AB 的长度和 A_prime B_prime 一样。

在下面的代码中,点是数组 pts[,] 的行。抱歉,3D图的效果不太好,这不是我的强项。

import math
import numpy as np
import matplotlib.pyplot as plt


def rotationMatrix( a, theta ):        # rotation matrix for active rotation, angle theta about axis a
    R = np.zeros( ( 3, 3 ) )
    n = a / np.linalg.norm( a )
    C = math.cos( theta )
    S = math.sin( theta )

    R[0,0] = C + n[0] * n[0] * ( 1.0 - C )
    R[0,1] =     n[0] * n[1] * ( 1.0 - C ) - n[2] * S
    R[0,2] =     n[0] * n[2] * ( 1.0 - C ) + n[1] * S
    R[1,1] = C + n[1] * n[1] * ( 1.0 - C )
    R[1,2] =     n[1] * n[2] * ( 1.0 - C ) - n[0] * S
    R[1,0] =     n[1] * n[0] * ( 1.0 - C ) + n[2] * S
    R[2,2] = C + n[2] * n[2] * ( 1.0 - C )
    R[2,0] =     n[2] * n[0] * ( 1.0 - C ) - n[1] * S
    R[2,1] =     n[2] * n[1] * ( 1.0 - C ) + n[0] * S

    return R


pts = np.array( [ [0,0,0], [1,0,0], [1,1,0], [0.5,1.5,0.5], [0,1,0] ], dtype=float )

A = pts[0,:]
B = pts[1,:]
Aprime = np.array( [2,2,0] )
Bprime = np.array( [2,2,-1] )
# Ensure that A'B' has the same length as AB
length = np.linalg.norm( B - A )
Bprime = Aprime + length * ( Bprime - Aprime ) / np.linalg.norm( Bprime - Aprime )

# Rotation matrix
rotate = rotationMatrix( np.cross( B - A, Bprime - Aprime ), math.acos( np.dot( Bprime - Aprime, B - A ) / length ** 2 ) )

# Transform points
ptsprime = np.zeros_like( pts )
for i in range( len( pts[:,0] ) ): ptsprime[i,:] = Aprime + rotate @ ( pts[i,:] - A ).T

# Draw it
ax = plt.figure().add_subplot( projection='3d' )
ax.plot( pts[:,0], pts[:,1], pts[:,2], color='r' )
ax.plot( ptsprime[:,0], ptsprime[:,1], ptsprime[:,2], color='b' )
ax.set_aspect( 'equal' )
plt.show()

输出: enter image description here

撰写回答