Я пытаюсь выяснить угол (в градусах) между двумя 2D векторами. Я знаю, что мне нужно использовать триг, но я не слишком хорош в этом. Это то, что я пытаюсь решить (ось Y увеличивается вниз):
Я пытаюсь использовать этот код в данный момент, но он вообще не работает (по какой-то причине вычисляет случайные углы):
private float calcAngle(float x, float y, float x1, float y1)
{
float _angle = (float)Math.toDegrees(Math.atan2(Math.abs(x1-x), Math.abs(y1-y)));
Log.d("Angle","Angle: "+_angle+" x: "+x+" y: "+y+" x1: "+x1+" y1: "+y1);
return _angle;
}
Это мои результаты (Постоянная при предоставлении постоянной позиции, но при изменении положение, угол изменяется, и я не могу найти никакой связи между двумя углами):
Положение 1: х: 100 у: 100 х1: 50 у1: 50 Угол: 45
Положение 2: х: 92 у: 85 х1: 24 у1: 16 Угол: 44,58
Положение 3: х: 44 у: 16 х1: 106 у1: 132 Угол: 28.12
Редактировать: Спасибо всем, кто ответил и помог мне понять, что это неправильно! Извините, заголовок и вопрос сбивают с толку.
Ага! Оказывается, мне просто нужно было перевернуть угол и использовать atan2. Вот мой окончательный код:
private float calcAngle(float x, float y, float x1, float y1)
{
float _angle = (float)Math.toDegrees(Math.atan2(x1-x, y-y1));
return _angle;
}
Спасибо всем, кто помог мне разобраться в этом, а также за помощь в понимании того, что я на самом деле делаю! :)
Сначала вы должны понять, как вычислить угол между двумя векторами , а их несколько. Я дам вам то, что считаю самым простым.
v1x * v2x + v1y * v2y
Имея эту информацию, возьмите это определение:
dot(v1, v2) = norm(v1) * norm(v2) * cos(angle(v1, v2))
Теперь вы решаете для угол (v1, v2)
:
angle(v1, v2) = acos( dot(v1, v2) / (norm(v1) * norm(v2)) )
Наконец, взяв определения, данные в начале, вы получите:
angle(v1, v2) = acos( (v1x * v2x + v1y * v2y) / (sqrt(v1x^2+v1y^2) * sqrt(v2x^2+v2y^2)) )
Опять же, есть много способов сделать это, но мне нравится этот, потому что он полезен для скалярного произведения с заданным углом и нормой или углом, заданным векторов.
Ответ будет в радианах, но вы знаете, что пи радианы (то есть 3,14 радиана) равны 180 градусам, поэтому вы просто умножаете их на коэффициент преобразования 180 / пи.
Похоже, Найл понял это, но я все равно закончу свое объяснение. В дополнение к объяснению того, почему решение работает, мое решение имеет два преимущества:
atan2 ()
возвращает угол против часовой стрелки относительно положительной оси X. Найл искал угол по часовой стрелке относительно положительной оси Y (между вектором, образованным двумя точками, и положительной осью Y).
Следующая функция адаптирована из моей игры с астероидами, где я хотел вычислить направление, в котором «указывал» вектор корабля / скорости:
// Calculate angle between vector from (x1,y1) to (x2,y2) & +Y axis in degrees.
// Essentially gives a compass reading, where N is 0 degrees and E is 90 degrees.
double bearing(double x1, double y1, double x2, double y2)
{
// x and y args to atan2() swapped to rotate resulting angle 90 degrees
// (Thus angle in respect to +Y axis instead of +X axis)
double angle = Math.toDegrees(atan2(x1 - x2, y2 - y1));
// Ensure result is in interval [0, 360)
// Subtract because positive degree angles go clockwise
return (360 - angle) % 360;
}
Должно быть:
atan( abs(x1 - x)/abs(y1 - y) )
abs
обозначает абсолютное (чтобы избежать отрицательных значений)
Я считаю, что уравнение для угла между двумя векторами должно больше выглядеть:
toDegrees(acos((x*x1+y*y1)/(sqrt(x*x+y*y)*sqrt(x1*x1+y1*y1))))
Вышеупомянутое уравнение вычислит угол между вектором p1-p2 и линией, образованной удлинением ортогональной из точки p2 в вектор p1.
Скалярное произведение двух векторов V1 и V2 равно | V1 | * | V2 | cos (theta). Следовательно, theta равно acos ((V1 dot V2) / (| V1 | | V2 |)). V1 точка V2 - это V1.x V2.x + V1.y V2.y. Величина V (то есть | V |) - это патогорейская теорема ... sqrt (V.x ^ 2 + V.y ^ 2)
Моим первым предположением было бы вычислить угол каждого вектора с осями, используя атан (y / x), а затем вычесть эти ангелы и взять абсолютное значение, то есть:
abs (атан (y / x) - атан (y1 / x1))
Угол второго вектора относительно первого = atan2(y2,x2) - atan2(y1,x1)
.
http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
Не принимайте абсолютное значение аргументов atan2
. Весь смысл atan2
в том, что он использует знаки своих аргументов, чтобы определить, в каком qaudrant находится угол. Принимая абсолютные значения, вы заставляете atan2
возвращать значения только между 0 и pi / 2 вместо -pi для pi.
Вы используете целые числа? Аргументы должны быть двойниками, и я буду использовать фабулы для результата, а не для аргументов. Результат будет в радианах; чтобы получить градусы, используйте:
res * = (360.0 / (2.0 * Math.PI));