Hi.
I'm just trying to make a simple analogue clock as I learn to use TKinter with python. I need to know the maths behind calculating the x, y values for drawing the end of the hands.

I don't need to post the whole program, all you need to see how I've done what I've got of the stuff you need to know (draws breath), is right here:

- I'm using the 'datetime' module for getting seconds, minutes and hours

- Have a canvas of size (300, 300) inside a window also (300, 300)

- The clock circle bounding box is (5, 5, 295, 295)

- I want to draw the hands as different lengths, so not quite as far as the edge of the clock circle.

- Hands originate from (150, 150)

- I only need to know how to calculate the end x and y values for the hands (eg. [origin_x, origin_y, end_x, end_y)

Thanks for your time!

Recommended Answers

All 7 Replies

Thanks for your time!

You're welcome!

First you should have a constant long hand length, and a constant short hand length.

Are you confident in math, particularly trigonometry?

circle of one unit is x**2+y**2=1 in normal x,y coordinates. computer graphics however have generally graphics pixels which run like text lines from up to down for y. Actually it does not matter for here as -y*-y=y*y

Therefore unit circle y = (x**2-1.0)**(1.0/2) , x is between -1 and 1. Solutions are y and -y (of course points -1 and 1 values are zero, 0**n=0)


Minute hand makes 360 degrees == 2*pi radians turn in 60 minutes, so it moves 360/60= 6 degrees or 2*pi/60 = (2*355/113)/60 = 710/6780 = 71/678 radians per minute.

So you solve the circle, multiply by your radius (length of hand), translate the circle to different location by just adding centre coordinates. You can work out what to do from here, not to give you the ready solution.

You just solve the end point with the radius you want to give for that hand.

One easy way to do this kind of job is to use the turtle graphics package. It produce lines by commanding turtle to set the line width, put filling on/off, put pen up/down, to move forward/backward and to turn left/right by given degrees. With these commands it is easy to do analogue clock without doing this above mentioned math yourself.

circle of one unit is x**2+y**2=1 in normal x,y coordinates. computer graphics however have generally graphics pixels which run like text lines from up to down for y. Actually it does not matter for here as -y*-y=y*y

Therefore unit circle y = (x**2-1.0)**(1.0/2) , x is between -1 and 1. Solutions are y and -y (of course points -1 and 1 values are zero, 0**n=0)


Minute hand makes 360 degrees == 2*pi radians turn in 60 minutes, so it moves 360/60= 6 degrees or 2*pi/60 = (2*355/113)/60 = 710/6780 = 71/678 radians per minute.

So you solve the circle, multiply by your radius (length of hand), translate the circle to different location by just adding centre coordinates. You can work out what to do from here, not to give you the ready solution.

You just solve the end point with the radius you want to give for that hand.

One easy way to do this kind of job is to use the turtle graphics package. It produce lines by commanding turtle to set the line width, put filling on/off, put pen up/down, to move forward/backward and to turn left/right by given degrees. With these commands it is easy to do analogue clock without doing this above mentioned math yourself.

Or pi/30 radians.

Here's a good solution that I hastily wrote down,
after thinking about how sine and cosine would be used:

import math

def clockhand_end(centerX,centerY,radius,rotations):
    '''Calculates the end value of the hand
from the coordinates of the center, the radius,
and the rotations (as a ratio), for example
30 seconds = 1/2 minute, so you would put .5 for
the rotations.'''
    angle = rotations * (2*math.pi)
        
    x = centerX + radius*math.sin(angle)
    y = centerY - radius*math.cos(angle)

    return round(x),round(y)

end_x, end_y = clockhand_end(150,  #That is hand's origin X
                    150,  #That is hand's origin Y
                    100,  #Radius
                    30.0/60.0  #30 out of 60 sixty seconds
                    )

After that, end_x = 150.0 and end_y = 250.0 .

Which is about where 30 seconds is.

(as a ratio), for example30 seconds = 1/2 minute, so you would put .5 for the rotations

So basically it's the mins over total minutes for the rotations?
Thanks for that!

PS
@jcao219: Yes I', confident with maths, and trig.
@tonyjv: No, not that confident ;)
"lol" is the term I think...

That bit works fine. But now how do I solve the problem of the fact that Python thinks that 7/12 = 0? This is the part of your code where the rotation is calculated.

Never mind! solved it...just converted the minute/hour/second values to float and divided by a float in the rotation bit.
Thanks again!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.