Python 随机生成法向量的坐标变换

Python 随机生成法向量的坐标变换,python,3d,coordinate-transformation,rotational-matrices,Python,3d,Coordinate Transformation,Rotational Matrices,我试图为我用python编写的拟合例程随机生成坐标变换。我想围绕原点旋转我的数据(一组[x,y,z]坐标),理想情况下使用我已经创建的一组随机生成的法向量来定义平面——我只想移动我定义的每个平面,使其位于z=0平面上 这是我的一段代码,一旦我有了转换矩阵,它应该会处理好一些事情。我只是不知道如何从我的法向量得到我的变换矩阵,以及我是否需要比numpy更复杂的东西 import matplotlib as plt import numpy as np import math origin = n

我试图为我用python编写的拟合例程随机生成坐标变换。我想围绕原点旋转我的数据(一组[x,y,z]坐标),理想情况下使用我已经创建的一组随机生成的法向量来定义平面——我只想移动我定义的每个平面,使其位于z=0平面上

这是我的一段代码,一旦我有了转换矩阵,它应该会处理好一些事情。我只是不知道如何从我的法向量得到我的变换矩阵,以及我是否需要比numpy更复杂的东西

import matplotlib as plt
import numpy as np
import math

origin = np.array([35,35,35])
normal = np.array([np.random.uniform(-1,1),np.random.uniform(-1,1),np.random.uniform(0,1)])
mag = np.sum(np.multiply(normal,normal))
normal = normal/mag

a = normal[0]
b = normal[1]
c = normal[2]

#I know this is not the right transformation matrix but I'm not sure what is...
#Looking for the steps that will take me from the normal vector to this transformation matrix
rotation = np.array([[a, 0, 0], [0, b, 0], [0, 0, c]])

#Here v would be a datapoint I'm trying to shift?
v=(test_x,test_y,test_z)
s = np.subtract(v,origin) #shift points in the plane so that the center of rotation is at the origin
so = np.multiply(rotation,s) #apply the rotation about the origin
vo = np.add(so,origin) #shift again so the origin goes back to the desired center of rotation

x_new = vo[0]
y_new = vo[1]
z_new = vo[2]

fig = plt.figure(figsize=(9,9))
plt3d = fig.gca(projection='3d')
plt3d.scatter(x_new, y_new, z_new, s=50, c='g', edgecolor='none')

我认为你对旋转矩阵的概念是错误的。旋转矩阵定义一定角度的旋转,不能具有对角结构

如果将每个旋转想象为围绕X轴、Y轴、Z轴旋转的组合,则可以构建每个矩阵并将最终旋转组合为矩阵的乘积

R = Rz*Ry*Rx
Rotated_item = R*original_item

在这个公式中,Rx是第一个应用的旋转。
注意

  • 您可以通过组合许多不同的3个旋转集来获得旋转
  • 序列不是固定的,它可以是X-Y-Z或Z-Y-X或Z-X-Z或任何组合。角度值可能会随着顺序的变化而变化
  • 使用此矩阵旋转临界值(90-180-270-360度)是“危险的”
如何围绕一个轴组成每个旋转矩阵?看见Numpy有你需要的所有东西

现在只需定义3个角度值。 当然,在你写问题的时候,你可以从一个随机的标准化向量(a,b,c)中得到3个角度的值,但是旋转是一个将向量变换成另一个向量的过程。也许你必须具体说明一下
“我想找到围绕原点的旋转R,该原点将(0,0,1)变换为(a,b,c)”。一个完全不同的旋转R'是将(1,0,0)变换为(A,b,c)的旋转

多亏了数学堆栈交换中的人员,我得到了一个有效的答案。但是请注意,如果你还需要执行平移,那么它将不起作用,我没有这样做,因为我用一个法向量和一个点来定义平面,法向量改变了,但点没有。这是对我有用的东西

import matplotlib as plt
import numpy as np
import math

def unit_vector(vector):
    """ Returns the unit vector of the vector.  """
    return vector / np.linalg.norm(vector)

cen_x, cen_y, cen_z = 35.112, 35.112, 35.112
origin = np.array([[cen_x,cen_y,cen_z]])

z_plane_norm = np.array([1,1,0])
z_plane_norm = unit_vector(z_plane_norm)

normal = np.array([np.random.uniform(-1,1),np.random.uniform(-1,1),np.random.uniform(0,1)])
normal = unit_vector(normal)

a1 = normal[0]
b1 = normal[1]
c1 = normal[2]

rot = np.matrix([[b1/math.sqrt(a1**2+b1**2), -1*a1/math.sqrt(a1**2+b1**2), 0], [a1*c1/math.sqrt(a1**2+b1**2), b1*c1/math.sqrt(a1**2+b1**2), -1*math.sqrt(a1**2+b1**2)], [a1, b1, c1]])

init = np.matrix(normal)

fin = rot*init.T
fin = np.array(fin)

# equation for a plane is a*x+b*y+c*z+d=0 where [a,b,c] is the normal
# so calculate d from the normal
d1 = -origin.dot(normal)

# create x,y
xx, yy = np.meshgrid(np.arange(cen_x-0.5,cen_x+0.5,0.05),np.arange(cen_y-0.5,cen_y+0.5,0.05))

# calculate corresponding z
z1 = (-a1 * xx - b1 * yy - d1) * 1./c1

#-------------

a2 = fin[0][0]
b2 = fin[1][0]
c2 = fin[2][0]

d2 = -origin.dot(fin)
d2 = np.array(d2)
d2 = d2[0][0]

z2 = (-a2 * xx - b2 * yy - d2) * 1./c2

#-------------

# plot the surface
fig = plt.figure(figsize=(9,9))
plt3d = fig.gca(projection='3d')

plt3d.plot_surface(xx, yy, z1, color='r', alpha=0.5, label = "original")   
plt3d.plot_surface(xx, yy, z2, color='b', alpha=0.5, label = "rotated")  


plt3d.set_xlabel('X (Mpc)')
plt3d.set_ylabel('Y (Mpc)')
plt3d.set_zlabel('Z (Mpc)')

plt.show()

如果您确实需要进行翻译,请参阅我的完整答案。

您的问题是什么?当前代码是否正常工作?谢谢。我的问题是如何从法向量得到正确的变换矩阵?现在我明白你的问题了。几个变换矩阵可以给出正确的答案,因为可以绕z轴旋转平面。也许可以试试?
import matplotlib as plt
import numpy as np
import math

def unit_vector(vector):
    """ Returns the unit vector of the vector.  """
    return vector / np.linalg.norm(vector)

cen_x, cen_y, cen_z = 35.112, 35.112, 35.112
origin = np.array([[cen_x,cen_y,cen_z]])

z_plane_norm = np.array([1,1,0])
z_plane_norm = unit_vector(z_plane_norm)

normal = np.array([np.random.uniform(-1,1),np.random.uniform(-1,1),np.random.uniform(0,1)])
normal = unit_vector(normal)

a1 = normal[0]
b1 = normal[1]
c1 = normal[2]

rot = np.matrix([[b1/math.sqrt(a1**2+b1**2), -1*a1/math.sqrt(a1**2+b1**2), 0], [a1*c1/math.sqrt(a1**2+b1**2), b1*c1/math.sqrt(a1**2+b1**2), -1*math.sqrt(a1**2+b1**2)], [a1, b1, c1]])

init = np.matrix(normal)

fin = rot*init.T
fin = np.array(fin)

# equation for a plane is a*x+b*y+c*z+d=0 where [a,b,c] is the normal
# so calculate d from the normal
d1 = -origin.dot(normal)

# create x,y
xx, yy = np.meshgrid(np.arange(cen_x-0.5,cen_x+0.5,0.05),np.arange(cen_y-0.5,cen_y+0.5,0.05))

# calculate corresponding z
z1 = (-a1 * xx - b1 * yy - d1) * 1./c1

#-------------

a2 = fin[0][0]
b2 = fin[1][0]
c2 = fin[2][0]

d2 = -origin.dot(fin)
d2 = np.array(d2)
d2 = d2[0][0]

z2 = (-a2 * xx - b2 * yy - d2) * 1./c2

#-------------

# plot the surface
fig = plt.figure(figsize=(9,9))
plt3d = fig.gca(projection='3d')

plt3d.plot_surface(xx, yy, z1, color='r', alpha=0.5, label = "original")   
plt3d.plot_surface(xx, yy, z2, color='b', alpha=0.5, label = "rotated")  


plt3d.set_xlabel('X (Mpc)')
plt3d.set_ylabel('Y (Mpc)')
plt3d.set_zlabel('Z (Mpc)')

plt.show()