This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
You have to work out the centre of your circle for the face (call it x, y), then your hand runs from x, y, to x + cos (a)*l, y - sin(a)*l, where a is the angle of the hand and l is its length. Remember that the angles start from 0 at 3o'clock and run anti-clockwise to PI/2 (= 0.5PI) at 12o'clock, PI at 9 o'clock, 3/2PI (=1.5PI) at 6o'clock, and back to 2PI at 3o'clock again. PI is of course the ratio between the circumference and diameter of a circle, and is available as java.lang.Math.PI. You use PI because you work out all trig functions in radians, not degrees.
You will of course remember that you always quote x coordinates before y. On a computer, x runs from left to right across the screen, and y runs from top to bottom down the screen, which is why you write -sin and not +sin.
Have I lost you yet? If not, read on and all will become even more confusing . . .
To work out the angle a, remember you start from 12 o'clock (PI/2), and go clockwise, so you subtract 2PI/12 = PI/6 for every hour (use h % 12 for your hour), and on the hour hand 2PI/720 for each minute, using m % 60 for the minute. So, when you work out the angle a for the hour hand, a= PI/2 - h % 12 * PI / 6 - m % 60 * PI / 360,
and for the minute hand you can use the simpler formula of a = PI / 2 - m % 30 * PI.
See, it's easy isn't it.
Joined: Oct 13, 2005
Thank you for the e-mail. We had this exercise ourselves in our MSc class about two weeks ago, and most people had no end of trouble with the mathemitcal side of the problem.
So it's the maths you need to revise . . .
And it's not going to be easy.
You know the coordinates in any GUI are x, y, rather like when you drew graphs at school, but they don't run in the same directions. The x numbers run from 0 at the left of the screen, which is not too confusing, but the y coordinates run from top to bottom with 0 at the top. You measure in pixels; get a powerful magnifying glass (or if you have very good eyes, screw your eyes up and look at the screen from as close as you can get), and each of the tiny spots you see in front of you represents a pixel. [Pixel is short for "picture element."] I have my screen set at 1280x1024, which means I have about 1280 pixels fro left to right and about 1024 from top to bottom. So, the pixel at the very top left of my screen is (0, 0), at the top right it is (1280, 0), at the bottom left (0, 1024), and the bottom right (1280, 1024). It is also useful to know where the middle pixel is, about (640, 512). That might not be the absolute centre of the screen, but it's as near as you will get and nobody will notice the difference. If you have the average GUI window occupying about 1/3 of the average computer screen, you might have it set to 400x400. A bit like this, only with a JFrame you have to allow a little extra height and width because it has a title bar and margins:-
Then you put a JPanel in the middle of your JFrame in the usual fashion, and the JPanel ought to be about 400x400. So, your centre pixel is (200, 200) near as makes no difference. Now, if you draw a face, and try something like,you get the circumference of a circle set in a box 300x300 px, 50 px from the top and left of the panel. [If the 3rd and 4th int parameters which represent width and height are different, you get an oval, only they ought to have given it its proper name, an ellipse.]
If you can lay your hands on a mathematics book with the definition of sine and cosine using a circle in, you won't need to do the next exercise:- Now, a maths lesson. Take a sheet of paper, draw a pair of lines across it, crossing in the centre, forming a cross like a +, and now you have a pair of x and y axes. Draw a circle with its centre on the crossing of the two lines (which you call the origin). Label the line from left to right -x on the left and +x on the right, and label the line from top to bottom with y at its top and -y at its bottom. Later you will change the y. Draw four radii of the circle, from the centre to the top right, to upper left, to lower right, and then to lower left, rather like hands on a clock. Draw curves from the right x-axis round to each of the four radii, only going anti-clockwise; one of your curves will go nearly round the whole circle. Say that the radius of the circle is 1. Make up a new unit the same size as the radius of the circle, so it's 1 of them. Draw a line vertically from one of your radii to the x-axis, and the length of that line represents the sine of the angle. Similarly, draw a line from the end of the radius to the y-axis, which line represents the cosine.
Now, you will see that a sine going up is positive, and a cosine going right is positive, and they are negative in the opposite directions.
It gets even more confusing now.
Remember that on a computer screen down is positive and up is 0. Well, change the y on your diagram to read -y and the -y at the bottom to read +y.
Now write the numbers 0 at the right (near +x), PI / 2 (or 1/2 PI or 0.5PI) at the top, PI on the left, and 3 PI / 2 (or 1 1/2 PI or 1.5 PI) at the bottom, which represent the angles in radians. Note that the increase as you go round anti-clockwise. PI is of course the static double field in the Math class, which represents the Greek letter pronounced similarly, which represents the ratio of the diameter of a circle to its circumference.
I did say this was difficult, didn't I?
Now what you are trying to do is draw a line from your centre spot to your circumference. You start about 5 pages back at 200, 200, remember. Now you have to add the cos of the angle, multiplied by the length of the "hand" (say, 150) to the x figure, so your 3rd argument comes out as 200 + (int)(150*Math.cos(PI/2 - PI/30*m)) for the minute hand. Now you have to subtract the length of the "hand" multiplied by its sin from the y figure, so your 4th and final argument is 200 - (int)150*Math.sin(PI/2 - PI/2*m)), where m means minutes. Or you can have Try it. then work out the angle for the cosine for the hour hand as I told you the other day . . .
In the 2D API you can do things like: * flip the y axis so that "up" is the positive direction * translate so that the origin is in the middle of the component * rescale so that units are more appropriate for what you are doing