I have a combination lock rotating in a 360 degrees circle.
The combination lock has numerical values on it, these are purely graphical.
I need a way to translate the image’s rotation to the 0-99 values on the graphic.
In this first graphic, the value should be able to tell me “0”
In this graphic, after the user has rotated the image, the value should be able to tell me “72”
Here is the code:
I think I need to translate some information from the matrix to a 0-99 value.
You should reorganize your code completely. Post-multiplying new rotations into a matrix over and over again is a numerically unstable computation. Eventually the bitmap will become distorted. Trying to retrieve the rotation angle from the matrix is too complex and unnecessary.
First note that this is a useful prior article on drawing bitmaps with rotation about a chosen point.
Just maintain a single
double dialAngle = 0 that is the current rotation angle of the dial.
You are doing way too much work to retrieve the angle from the touch location. Let
(x0,y0) be the location where the touch starts. At that time,
This is the starting angle. When the touch drags to
(x,y), use this coordinate to adjust the dial with respect to the initial touch. Then update the matrix and redraw:
Math.atan2(y, x) does all of what you’re doing with quadrants and arcsines.
To get the “tick” of the current angle, you need 2 pi radians to correspond to 100, so it’s very simple:
To find the actual nearest tick as an integer, round the fraction and mod by 100. Note you can ignore the matrix!
This will always work because
dialAngle is in [0..2pi). The mod is needed to map a rounded value of 100 back to 0.
To better understand what the matrix does, it’s helpful to understand 2d graphics transform matrices: http://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_graphics . If the only thing that you are doing is rotating (not, say, transforming or scaling) it is relatively easy to extract rotation. But, more practically, you may modify the rotation code, and store a state variable
Keep a variable to store the total rotation in degrees, which you increment in your rotate function. Now, we know 3.6 degrees is a tick. Simple math yields
The one last thing you have to check for: If you have a rotation of exactly 360 degrees, or a tick number of 100, you have to treat it as 0 (since there is no tick 100)
This should be a simple multiplication with a “scale” factor that scales down your degree value (0-359) to your 0-99 scale:
EDIT: Correcting the getAngle function
For getAngle you could use the atan2 function instead, which transforms cartesian coordinates into an angle.
Just store the first touch coordinate on touch down and on move you can apply the following calculation:
The radians have a range of two pi. the modulo calculations rotate it so a value of 0 points up. The rotation direction is counter-clockwise.
So you’d need to convert that to degrees and change rotation direction for getting the correct angle.
The dial should be rotated exactly 3.6 degrees to go from one mark to the next or previous.
Everytime the user’s touch rotates(around the center) by 3.6 degrees, the dial should be rotated by 1 mark(3.6 degrees).
getTouchAngle()calculates the angle of user’s touch point wrt to dial center using
setDialMarkrotates the dial by number of marks changed.