I'm trying to code an app, where I'm able to move an Imageview only on a specific circular path.
@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;
}
This is my onTouchListener so far. HeightHalf and WidthHalf are the Coord. of the center point. I think my idea is right, but right now the ImageView is moving on a part of the circle and not on the whole circle like I want to.
So my question: Where is my fault?
If you need more information please let me know.
(-pi/2, pi/2)
This is a mathematical problem, the java implementation follows the maths. The tangent function is by default not invertible, but it can be inverted if you restrict the domain to (-pi/2, pi/2)
. Therefore the inverse function arctan will only gives back values in (-pi/2, pi/2)
. The java implementation atan
pushes this idea further defining this method also at +/-infinity (which mathematically aren't real numbers). As a result you see your ImageView
moving only on the right-hand side of the circle.
Solution: use Math.hypot()
to calculate the hypotenuse then calculate sine and cosine by divisions.
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: I coded up a small example with this code and it works. You can find it here.