Нахождение угла между осью x и вектором на единичной окружности

#python #arrays #numpy #math #vector

#python #массивы #numpy #математика #вектор

Вопрос:

У меня есть функция, которая находит угол между вектором единичной окружности [1,0] и вектором на единичной окружности.

 import numpy as np

def angle(a):
    b = [0,1]
    if a[1] >= 0:
        return round(np.degrees(np.arccos(np.dot(a, b)/ (np.linalg.norm(a) * np.linalg.norm(b)))), 2)
    else:
        return 180   round(np.degrees(np.arccos(np.dot(a, b)/ (np.linalg.norm(a) * np.linalg.norm(b)))), 2)

print(angle(np.array([1,0])))
90.0

print(angle(np.array([-4,2])))
63.43 # This value should be 150

print(angle(np.array([-1,0])))
90.0 # This value should be 180

print(angle(np.array([0,-1])))
360.0 # This value should be 270
  
  • Как мне установить, что входные a данные всегда являются 2D-вектором?
  • Как мне изменить код, чтобы векторы ниже оси x (т. Е. Отрицательные значения y) отображали правильное значение?

Комментарии:

1. как вы хотите, чтобы были представлены векторы ниже оси x? -5 или 355?

2. Есть arctan2 функция, которая делает то, что вы хотите сделать с angle function .

3. @anon01, представленный как 355, был бы идеальным

4. утверждение (тип (a) == np.ndarray) amp; утверждение (a.size == 2) может помочь с проверкой входных данных. Выдает ошибку, если эти условия не выполняются.

5. @QuangHoang как мне реализовать эту функцию в коде?

Ответ №1:

У вас неверный вектор x. Это должно быть

b = [1,0]

учитывая, что первая координата — это ось x, а вторая — ось y. Если вы поместите этот правильный вектор b, все вычисления будут работать так, как ожидалось.

Ответ №2:

Один из способов определить функцию, которая ожидает входные данные, — оставить оба в виде отдельных аргументов (это также исправляет некоторые ошибки и упрощает логику получения ваших значений угла):

 def angle(x, y):
    
    rad = np.arctan2(y, x)
    degrees = np.int(rad*180/np.pi)
    if degrees < 0:
        degrees = 360 - degrees
    return degrees
  

Кстати, atan2 имеет порядок ввода y, x , который легко перепутать. Преимущество их указания по отдельности заключается в том, что вы можете помочь избежать этого. Если вы хотите сохранить входные данные в виде массива, что-то вроде этого поможет вам проверить длину:

 def angle(a):
    
    if len(a) != 2:
        raise IndexError("vector a expected to be length 2")        
    x = a[0]
    y = a[1]
    rad = np.arctan2(y, x)
    degrees = np.int(rad*180/np.pi)
    if degrees < 0:
        degrees = 360 - degrees
    return degrees
  

Ответ №3:

Чтобы установить, что a всегда является 2D вектором, вы можете проверить его длину : if len(a) == 2 . вы можете дополнительно проверить, является ли это списком или кортежем с : if type(a) in [list, tuple] and len(a) == 2:

РЕДАКТИРОВАТЬ: мой плохой только что заметил, что в этом случае это на самом деле массивы numpy : if isinstance(x, np.ndarray) and x.shape[0] == 2

РЕДАКТИРОВАТЬ 2 : из комментариев : x.ndim == 2 звучит лучше.

Комментарии:

1. https://numpy.org/doc/stable/reference/generated/numpy.ndarray.ndim.html#numpy.ndarray.ndim