Определение направления 2D вектора с 8 дискретными направлениями (горизонтальное, вертикальное и диагонали)
У меня есть вход джойстика, это вектор. Диапазон значений вектора определяет окружность в прямоугольнике, который охватывает -1, -1 до +1, +1.
Я хочу знать, к какому из 8 возможных направлений подходит вектор. Не беспокойтесь о случае, когда вектор равен (0, 0), я буду разбираться с этим отдельно. Как я могу это сделать?
Примечание: это для игры, поэтому эта функция будет запускаться очень часто. Помогло бы что-нибудь для ускорения функции, например, я знаю, что могу использовать скалярное произведение и триггер, чтобы определить угол между моим вектором и каждым вектором направления, однако мне интересно, можно ли что-то сделать лучше, если мне не нужно точный угол.
3 ответа
Представьте квадрат внутри квадрата -1.1, где позиция палки (X) находится на одной из сторон:
+-----------------+ +-----------------+
| | | |
| | | |
| X | | +-----X-+ |
| | | | | |
| O | | | O | |
| | | | | |
| | | +-------+ |
| | | |
| | | |
+-----------------+ +-----------------+
Вам просто нужно выяснить, на какой стороне находятся координаты, и проверить, ближе ли это к центру стороны или углу. Если внутренний квадрат слишком мал, вы можете считать палочку центрированной.
Что-то вроде:
Public enum Direction {
None,
LeftUp, Up, RightUp, Right, RightDown, Down, LeftDown, Left
}
public Direction GetDirection(double x, double y) {
double absX = Math.Abs(x);
double absY = Math.Abs(y);
if (absX < 0.1 && absY < 0.1) {
// close to center
return Direction.None;
}
if (absX > absY) {
// vertical side
double half = absX * 0.4142;
if (x > 0) {
// left side
if (y > half) return Direction.LeftDown;
if (y < -half) return Diretion.LeftUp;
return Direction.Left;
} else {
// right side
if (y > half) return Direction.RightDown;
if (y < -half) return Direction.RightUp;
return Direction.Right;
}
} else {
// horisontal side
double half = absY * 0.4142;
if (y > 0) {
// bottom
if (x > half) return Direction.RightDown;
if (x < -half) return Direction.LeftDown;
return Direction.Down;
} else {
// top
if (x > half) return Direction.RightUp;
if (x < -half) return Direction.LeftUp;
return Direction.Up;
}
}
}
Никакой тригонометрии, только простые сравнения, поэтому все должно быть довольно быстро.:)
(Хотя я использовал тригонометрию для вычисления точки 0,4142, которая является загаром (22,5), или положения на стороне, где угол равен 45/2.)
sin a / cos a = tan a,
и у тебя есть
Y = грех
X = cos a
Итак, примените функцию обратной касательной к Y/X, и вы получите угол.
РЕДАКТИРОВАТЬ: в полном круге, есть два угла с одинаковым значением касательной (a
а также a
+ pi
). Используйте знаки X и Y, чтобы определить, какой из них является действительным.
Вы можете использовать готовую таблицу приближений tan^-1. Должно быть очень быстро вычислять угол на основе размера вашего входного вектора, и вам, вероятно, не понадобится очень большое разрешение в таблице (на самом деле, если вам нужно только 8 дискретных направлений, 8 записей в вашей таблице будет достаточно).