Мое решение не элегантное, и, может быть, мне не хватает более чистого решения, но это то, что я сделал недавно.Хитрость заключается в том, чтобы отслеживать угол с момента последнего вызова touchesMoved:
.Затем добавьте дельту вашего текущего угла и сохраненное значение ангела к вашему итогу.
Проблема в «границах», которые atan2 создает необходимый уродливый код для преодоления.Скажем, ваше lastAngle
равно 359, и вы пересекаете исходную точку, поэтому ваш следующий угол равен 1. Разница будет не равной 2, а -358, поэтому при каждом пересечении этой границы ваше общее значение будет сбрасываться в 0.
Вот что я сделал:
CGFloat angle = atan2f(center.y - point.y, point.x - center.x);
//Translate to Unit circle
if (angle > 0) {
angle = (M_PI - angle) + M_PI;
} else {
angle = fabsf(angle);
}
CGFloat delta = angle - lastAngle;
//Adjust for boundaries
if (fabsf(delta) > (2*M_PI)-fabsf(delta)) {
BOOL greaterThanZero = (delta > 0);
delta = (2*M_PI)-fabsf(delta);
if (greaterThanZero) {
delta = -1 * delta;
}
}
totalAngle += delta;
lastAngle = angle;
Большое / безобразное условие в разделе «Корректировка границ» в основном просто смотрит, есть ли более короткий угол, чтобы добраться до новой точки (так, 2 вместо -258) & предполагает, что если оно есть, это, вероятно, означает, что вы пересекли это начало и соответственно изменили дельту.
Я перевел результаты Atan2 так, чтобы они представляли полный единичный круг от 0 до 2π.Бонус побочный эффект, он тогда учитывает движение по часовой стрелке / против часовой стрелки лучше, чем стандартное от -π до π Atan2.