Построение трехмерных векторов в полярной системе координат относительно друг друга - PullRequest
0 голосов
/ 16 июня 2020

У меня есть тысячи пар трехмерных векторов. В каждом случае векторы произвольно поворачиваются относительно осей, но угол между ними и направление этого угла важны.

В настоящее время я вычисляю угол между двумя векторами, просто используя скалярное произведение:

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

Затем я помещаю его на диаграмму рассеяния и получаю график полярного распределения.

Это кажется довольно длинным. Мне интересно, есть ли способ просто спроецировать желаемый вектор вниз, когда они произвольно повернуты, и получить угол, который я получаю после выхода?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...