Переместить круговое изображение

Я пытаюсь закодировать приложение, в котором я могу перемещать изображение только по определенному круговому пути.

@Override
public boolean onTouch(View view, MotionEvent event) {

    float touchedX = 0;
    float touchedY = 0;
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:  

            break;
        case MotionEvent.ACTION_UP:
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            break;
        case MotionEvent.ACTION_POINTER_UP:
            break;
        case MotionEvent.ACTION_MOVE:

            touchedX = event.getX();
            touchedY = event.getY();
            float deltaX = touchedX-widthHalf;
            float deltaY = touchedY-heightHalf;
            double angle = Math.atan(deltaY/deltaX);                        
            timeCircleButton.setX(widthHalf + ((float)(radius*(Math.cos(angle)))));
            timeCircleButton.setY(heightHalf + ((float)(radius*(Math.sin(angle)))));


            break;
    }

    return true;
}

Пока это мой onTouchListener. HeightHalf и WidthHalf являются Coord. центральной точки. Я думаю, что моя идея верна, но сейчас ImageView движется по части круга, а не по всему кругу, как я хочу.

Итак, мой вопрос: в чем моя вина?

Если вам нужна дополнительная информация, пожалуйста, дайте мне знать.


person Billabong    schedule 20.09.2014    source источник
comment
ты читал мат. атан документы?   -  person pskink    schedule 20.09.2014
comment
не напрямую. Но я пробовал и радианы, а не градусы.   -  person Billabong    schedule 20.09.2014
comment
Проверьте еще раз мой ответ. Я загрузил небольшое законченное приложение на github с перемещением ImageView по кругу.   -  person Gil Vegliach    schedule 20.09.2014


Ответы (1)


  • Проблема в том, что значения функции arctan находятся в (-pi/2, pi/2)

Это математическая задача, реализация Java следует математике. Касательная функция по умолчанию необратима, но ее можно инвертировать, если вы ограничите домен до (-pi/2, pi/2). Поэтому обратная функция arctan будет возвращать значения только в (-pi/2, pi/2). Реализация Java atan подталкивает эту идею к дальнейшему определению этого метода также в +/- бесконечности (которые математически не являются реальными числами). В результате вы видите, что ваш ImageView движется только по правой стороне круга.

Решение: используйте Math.hypot() для вычисления гипотенузы, затем вычислите синус и косинус по делениям.

touchedX = event.getX();
touchedY = event.getY();

double deltaX = touchedX - widthHalf;
double deltaY = touchedY - heightHalf;
double hypot = Math.hypot(deltaX, deltaY);
double cosine = deltaX / hypot;
double sine = deltaY / hypot;  

timeCircleButton.setX((float)(widthHalf + radius * cosine));
timeCircleButton.setY((float)(heightHalf + radius * sine)));

EDIT: я написал небольшой пример с этим кодом, и он работает. Вы можете найти его здесь.

person Gil Vegliach    schedule 20.09.2014
comment
Да, ты прав. Но я на самом деле не знаю, как это исправить. - person Billabong; 20.09.2014
comment
Да, конечно, проверьте код. Математически в каждом треугольнике синус = (противоположная сторона)/гипотенуза и косинус = (прилежащая сторона)/гипотенуза, где «противоположный» и «прилежащий» относятся к углу, который вы вычисляете синус/косинус - person Gil Vegliach; 20.09.2014
comment
Что ж, похоже, ты прав - я понял твое решение. Но это не работает. ImageView движется по круговой траектории, но я не могу повернуть - person Billabong; 20.09.2014
comment
Что вы имеете в виду под поворотом? Объясните, в чем именно проблема с этим кодом, к сожалению, я не могу запустить его как есть. - person Gil Vegliach; 20.09.2014
comment
@Billabong, почему бы тебе просто не использовать Math.atan2? - person pskink; 20.09.2014
comment
@pskink Я никогда не использовал atan2, но это хороший момент. Во всяком случае, я считаю, что гипот (2 умножения, 1 сложение, 1 квадрат) плюс 2 деления будет немного быстрее, чем atan2 (изменение координат реализовано изначально) - person Gil Vegliach; 20.09.2014
comment
Я имею в виду, что ImageView все еще движется по части круга. Но на этот раз это половина дела. А иногда мигает с одной стороны на противоположную сторону круга (может + и - быстро меняется) - person Billabong; 20.09.2014
comment
Изображение следует за вашим пальцем. Он будет размещен на воображаемой линии, соединяющей палец и центр. На этой линии изображение будет размещено точно по радиусу от центра (по направлению к пальцу). Посмотрите мой код на github, он делает именно это. Это логика, которую вы, похоже, преследуете. Если отличается, поясните. - person Gil Vegliach; 20.09.2014
comment
Извините за недопонимание. Нет, ваш код работает правильно. Я нашел свою ошибку в моем коде. У меня возникла проблема с текущей позицией изображения (я просто быстро копирую и вставляю ваш код). СПАСИБО! - person Billabong; 20.09.2014
comment
Я нашел другую проблему. Вы используете OnTouchEvent(). Теперь я использую фрагменты для своего приложения, теперь нет метода ontouchevent, и OnTouchListener() не работает (ImageView просто снова перемещается по части)..... - person Billabong; 20.09.2014
comment
Политика stackoverflow заключается в том, чтобы в таких случаях задавать другой вопрос, так что делайте это. В любом случае, вы можете добавить TouchListener в ViewGroup, содержащую ваш ImageView, и реализовать аналогичную логику. Или вы все еще можете реализовать onTouchEvent() в своей деятельности. Есть много возможностей, задайте другой вопрос, и люди скажут вам. - person Gil Vegliach; 20.09.2014