给定已经旋转的点,如何获得 3D 点的平移和旋转?

问题描述 投票:0回答:1

我有 3D 点 A、B、C、D 和 E。这些点不共面或共线。我可以在另一个坐标系中获得点 A' 和 B',从而保留原始 AB 距离。仅凭这些信息,我是否可以像原始 AC、AD 等一样获得具有 A'C'、A'D' 等距离、角度和关系的 C'、D' 和 E' 点?

我尝试了各种尝试旋转矩阵的方法,但没有成功。我试图找到一个旋转矩阵,将 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 是 3D 坐标的 numpy 数组)。 这给了我 C'、D' 和 E',它们是距 A' 的正确距离,但不是距 B' 的正确距离。使用 B 和 B_prime 代替 A 和 A_prime 会产生相反的结果。如何结合这两个约束? 我正在使用 python 和 numpy。

python 3d geometry
1个回答
0
投票

一个可能的图像来自

C_prime = A_prime + R(C - A)
等,其中
R
是将
AB
带到
A_prime B_prime
的旋转矩阵。后者(通常)可以从这两个向量和由它们的叉积形成的轴之间的角度找到......除非它们共线,因此叉积为 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,3,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 )

# Translation vector and rotation matrix
translate = Aprime - A
rotate = rotationMatrix( np.cross( Bprime - Aprime, B - A ), 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='r' )
ax.set_aspect( 'equal' )
plt.show()

输出:

© www.soinside.com 2019 - 2024. All rights reserved.