Есть ли быстрый способ рассчитать наименьшую дельту между двумя значениями вращения? - PullRequest
1 голос
/ 02 февраля 2010

Есть два вида:

viewA и viewB. Оба вращаются.

Система координат для вращения странная: она идет от 0 до 179,999999 или -179,99999 градусов. Таким образом, 179,99999 и -179,99999 очень близки друг к другу!

Я хочу вычислить, сколько градусов или радиан между этими вращениями.

Например:

viewA поворачивается на 20 градусов

viewB поворачивается на 30 градусов

Я мог бы просто сделать: вращение B - вращение A = 10.

Но проблема с этой формулой:

viewA поворачивается на 179 градусов viewB поворачивается на -179 градусов

что пошло бы не так: вращениеB - вращениеA = -179 - 179 = -358

358 совершенно неверно, потому что они очень близки в реальности. Поэтому я мог бы сделать одну вещь - проверить, больше ли абсолютное значение результата, чем 180, и, если это так, вычислить его наоборот, чтобы получить короткую истинную дельту. Но я чувствую, что это неправильно и плохо из-за возможных ошибок с плавающей запятой и неточности. Так что, если два обзора повернуты по существу одинаково на 179,99999999999 градусов, я могу получить странные 180 или 0, если мне повезет.

Может быть, есть математическая форма в гениальном стиле с PI, синусом или другим полезным материалом для решения этой проблемы?

Ответы [ 5 ]

2 голосов
/ 02 февраля 2010

РЕДАКТИРОВАТЬ: оригинальный ответ (с модом) был неправильным. дал бы 180 - правильный ответ в определенных обстоятельствах (например, углы 30 и -20 дали бы ответ 130, неправильный ответ 50):

Два правильных ответа для всех сценариев:

Если A1 и A2 - это два угла (между -179.99999 и 179.99999, и Abs означает принять Абсолютное значение, Угловое расстояние между ними выражается:

Angle between = 180 - Abs(Abs(A1 - A2) - 180)

Или, используя троичный оператор в стиле C:

Angle between = A1 < 180 + A2? A1 - A2: 360 + A1 - A2
0 голосов
/ 03 февраля 2010

В дополнение к отличный ответ Брэда Ларсона Я бы добавил, что вы можете сделать:

CGFloat adjustAngle(angle) { return fmod(angle + 180.0, 360.0); }
...
CGFloat difference = fmod(adjustAngle(angle1) - adjustAngle(angle2), 360.0);
0 голосов
/ 02 февраля 2010

Судя по последним вопросам, которые вы задавали, вы можете прочитать о единичном кружке . Это фундаментальное понятие в тригонометрии, и именно так рассчитываются углы при поворотах с использованием CGAffineTransforms или CATransform3Ds.

Как правило, единичный круг проходит от 0 до 360 градусов, или от 0 до 2 * пи (M_PI - это постоянная, используемая в iPhone) радиан. Любой угол больше 360 градусов такой же, как этот угол минус кратный 360 градусам. Например, 740 градусов - это то же самое, что и 380 градусов, что равняется 20 градусам, когда дело доходит до конечного положения чего-то, повернутого на столько.

Аналогично, отрицательные градусы такие же, как если бы вы добавили к ним кратное 360 градусов. -20 градусов - это 340 градусов.

За этими вычислениями нет никакой магии, вам просто нужно обратить внимание, когда что-то пересекает точку 0/360 градусов на окружности. В случае, который вы описываете, вы можете добавить 360 к любым отрицательным значениям, чтобы выразить их в положительных углах. При вычитании углов, если конечный угол меньше начального угла, вам также может понадобиться добавить 360 к результату, чтобы учесть пересечение нулевой точки на единичной окружности.

0 голосов
/ 02 февраля 2010

Давайте попробуем это снова:
Есть два угла между А и В. Один из них

θ 1 = A - B

Другой

θ 2 = 360 - θ 1

Так что просто возьмите минимум из этих двух.

0 голосов
/ 02 февраля 2010

Возьмите разницу, добавьте 360 и мод на 360.

...