У меня есть тысячи пар трехмерных векторов. В каждом случае векторы произвольно поворачиваются относительно осей, но угол между ними и направление этого угла важны.
В настоящее время я вычисляю угол между двумя векторами, просто используя скалярное произведение:
def CalculateAngleBetweenVector(vector, vector2):
"""
Does what it says on the tin, outputs an angle in degrees between two input vectors.
"""
dp = np.dot(vector, vector2)
maga = math.sqrt((vector[0] ** 2) + (vector[1] ** 2) + (vector[2] ** 2))
magb = math.sqrt((vector2[0] ** 2) + (vector2[1] ** 2) + (vector2[2] ** 2))
magc = maga * magb
dpmag = dp / magc
#These if statements deal with rounding errors of floating point operations
if dpmag > 1:
error = dpmag - 1
print('error = {}, do not worry if this number is very small'.format(error))
dpmag = 1
elif dpmag < -1:
error = 1 + dpmag
print('error = {}, do not worry if this number is very small'.format(error))
dpmag = -1
angleindeg = ((math.acos(dpmag)) * 180) / math.pi
return angleindeg
Кажется, все работает нормально. Следующее, но все же, вычисляет угол вокруг одного вектора, под которым находится другой. В каждом случае я хотел бы вычислить угол вокруг Vector1, который находится Vector2, чтобы я мог нанести его на график распределения angular. Это будет искать кластеризацию в определенных c направлениях.
Пока что мой лучший план - вычислить смещение одного вектора к другому с помощью функции выше, а затем вычислить перекрестное произведение и создать матрицу вращения для этого движения следующим образом:
def RotationMatrix(axis, rotang):
"""
This uses Euler-Rodrigues formula.
"""
#Input taken in degrees, here we change it to radians
theta = rotang * 0.0174532925
axis = np.asarray(axis)
#Ensure axis is a unit vector
axis = axis/math.sqrt(np.dot(axis, axis))
#calclating a, b, c and d according to euler-rodrigues forumla requirments
a = math.cos(theta/2)
b, c, d = axis*math.sin(theta/2)
a2, b2, c2, d2 = a*a, b*b, c*c, d*d
bc, ad, ac, ab, bd, cd = b*c, a*d, a*c, a*b, b*d, c*d
#Return the rotation matrix
return np.array([[a2+b2-c2-d2, 2*(bc-ad), 2*(bd+ac)],
[2*(bc+ad), a2+c2-b2-d2, 2*(cd-ab)],
[2*(bd-ac), 2*(cd+ab), a2+d2-b2-c2]])
def ApplyRotationMatrix(vector, rotationmatrix):
"""
This function take the output from the RotationMatrix function and
uses that to apply the rotation to an input vector
"""
a1 = (vector[0] * rotationmatrix[0, 0]) + (vector[1] * rotationmatrix[0, 1]) + (vector[2] * rotationmatrix[0, 2])
b1 = (vector[0] * rotationmatrix[1, 0]) + (vector[1] * rotationmatrix[1, 1]) + (vector[2] * rotationmatrix[1, 2])
c1 = (vector[0] * rotationmatrix[2, 0]) + (vector[1] * rotationmatrix[2, 1]) + (vector[2] * rotationmatrix[2, 2])
return np.array((a1, b1, c1))
def AngleOffset(Vector1, Vector2):
# Takes the two input vectors, calculates the offset and the RM required to rotate one onto the other.
# ensure things are unit vectors
Vector1 = Vector1 / np.linalg.norm(Vector1)
Vector2 = Vector2 / np.linalg.norm(Vector2)
# calculate the offset and axis of rotation to take vector to the z axis
angle = CalculateAngleBetweenVector(Vector1, Vector2) * -1
cross = np.cross(Vector1, Vector2)
RM = RotationMatrix(cross, angle)
return RM
Насколько я понимаю, я могу просто применить эту матрицу вращения к вектору (0,0,1), а затем использовать следующую функцию для вычисления угла вокруг оси, который вектор сидит:
def CalculateAngleAroundZ(Vector):
X,Y,Z = Vector[0], Vector[1], Vector[2]
AngleAroundZ = math.atan2(Y, X)
return AngleAroundZ
Затем я помещаю его на диаграмму рассеяния и получаю график полярного распределения.
Это кажется довольно длинным. Мне интересно, есть ли способ просто спроецировать желаемый вектор вниз, когда они произвольно повернуты, и получить угол, который я получаю после выхода?