Python 3D Graphics Tutorial 14: Three Dimensional Clock Face Model in Vpython

preview_player
Показать описание
You guys can help me out over at Patreon, and that will help me keep my gear updated, and help me keep this quality content coming:

In this video we show step-by-step instructions on how to build a 3D clock face model in Vpython. In future lessons we will animate the clock to keep time .
#Python
#Lessons
#Graphics
Рекомендации по теме
Комментарии
Автор

I started a month ago with the Arduino, python and now vpython. Some times i do 10+ a day you can imagine the numCups of coffee that corresponds to. thank you for the way you deliver the content you do it with great enthusiasm that i just say one more after completing a video which end up into long nights of productive work. thanks Paul through your course I'm now developing an understanding of tech and imagining ways i can integrate python, Arduino into my projects as M.E student at university.

tapiwanashengwena
Автор

I enjoy these lessons so much. I saw many of these problems in university (such as this homework with the frequency of signals), but it felt like professors would never provide a tangible application like Paul does. Going through these lessons has really cemented my understanding of these topics.

learningcode
Автор

I am in awe of your imagination to solve this problem. Great job. Thank you.

louistoweill
Автор

I Am LEGEND. I spent over an hour on it but it worked out great by using the easy way. my clock is turning with the right ratio of hour and minutes in the right direction ! :)

arnaudmasse
Автор

I am LEGEND!! I was able to create the Clock, I did the first 15 tics manually, by adding each tic marks position and orientation. To get this right, I had to draw it out on paper. As I was adding each tic mark, I could see just how repetitive my approach was going to be, so I decided I better figure out how to add these tic marks using the for loop.(Which Paul had shown us in a prior lesson) It really wasn't that bad. I copied a line down, created a variable "ThetaT" and had the loop step through it for 61 increments for the small tic and then for 13 increments for the bigger one. I'm not sure if we have any excel users out there, but stepping through these for loops reminds me a lot of grabbing the bottom right corner of a cell and dragging it down in excel. These for loops will be very useful in the future. my Clock does have multiple layers of Tics on it, but you really can't see them. For this assignment I don't think it will cause a problem. Thanks for another great lesson Paul! Here is my HW.

chrisb
Автор

I AM LEGEND! I had to play engineer and do some paper work, but I figured it out. My clock does not run at a constant speed so it would not be very useful. Thanks for all your work on developing these great lesson, Paul.

cbrombaugh
Автор

Definitely need to watch this video again. But now that I have it Witten, I can follow along and just listen to explaining while I see the parameters.

wayneswan
Автор

I am legend. I managed to do the clock face and I also added the spinning hour and minute hands before I watched this tutorial. So my homework for next lesson is already done. :)

ecassar
Автор

I am legend. Took longer then I thought, but I needed the challenge.

petefontana
Автор

OK I am not legend, but maybe I am semi-mythical. You manage to fool me pretty often by showing a new technique and the assigning homework that makes us go to older work rather than use the new technique as the main solve. This was another example for me. I made my clock face using the make_trail=True parameter for the circle, and then got ticks in a regular spacing around the circle (clock face) but the ticks were all in an x axis orientations and I could not seem to get them to point in the correct directions. Once I watch your solution using the cylinder to create the clock face, the rest seemed obvious as I watched. Now to see if I can get a minute and hour hand rotating in the correct direction and at differing speeds! Thank you for another great lesson!

pokerface
Автор

Thanks Paul.I appreciate all your hard work in putting these lessons together. I have learned a lot from you. Unfortunately, I folded up like a cheap lawn chair (again!). I had trouble getting the axis parameter right and I used balls instead of tick marks. However, I was able to go back and correct things.

leeg.
Автор

I have a lot of fun with this one, I succeeded after a good couple of hours struggling with it...

woodpython
Автор

Thanks again for great content and your comprehensive instruction! I completed the homework with something very similar. One thing that is just a personal preference for me is I prefer to write each line of code instead of copying/pasting as I have less chance of missing something. I also fall back on something that was pounded into me by a College Instructor when I was learning programming in the mid 80's, which is to COMMENT EVERYTHING! Not really an issue with short, simple programs, but it can really save your hide when you have hundreds or even thousands of lines of code!
On a side note, really like your shirt! I attended UTPB in Odessa, Texas for two years before transferring to Texas Tech.
Keep the great content coming! I appreciate the hard work and dedication this takes!

hmccall
Автор

First off, I AM LEGEND.
I decided to add, and animate, the hands of the clock after creating the tick marks.
The lines of code to declare the ticks inside the for loops used were quite long so apologies if they get jumbled when pasted below.
I found the tick marks reasonably intuitive, but struggled to successfully get all three hands rotating properly (turns out I was over-thinking it as usual).
Quite happy with my clock in the end. Due to Paul's teaching it is of course fully parameterised....!

from vpython import *
import numpy as np

# Face parameters
clockrad = 1 # radius of outer rim
Mtickrad = 0.025*clockrad # radius of major ticks
MtickL = 8*Mtickrad # length of major ticks
SMtickrad = (3/5)*Mtickrad # radius of semi-major ticks
SMtickL = 6.5*SMtickrad # length of semi-major ticks
mtickrad = 0.005*clockrad # radius of minor ticks
mtickL = 10*mtickrad # length of minor ticks
Toptickdist = 0.025*clockrad # distance between two top ticks (at 12)
offset = 0.07*clockrad # distance between ticks and outer rim

# Hand parameters
handD = 0.005*clockrad # depth of clock hands
sechandH = 0.045*clockrad # second hand height (from clockface)
sechandW = 0.01*clockrad # second hand width
sechandL = (clockrad - offset)*0.95 # second hand length
minhandH = sechandH*2/3 # minute hand height (from clockface)
minhandW = 0.02*clockrad # minute hand width
minhandL = (clockrad - offset)*0.95 # minute hand length
hourhandH = sechandH/3 # hour hand height (from clockface)
hourhandW = 0.04*clockrad # hour hand width
hourhandL = minhandL*(2/3) # hour hand length

for angle in np.linspace(0, 2*pi, 1800): # Makes the outer rim of the clock, we want this instantly, hence no rate().
edge = cylinder(radius = 0.005, length = clockrad*2*pi/1800, pos = vector(clockrad*cos(angle), clockrad*sin(angle), 0), axis = vector(-sin(angle), cos(angle), 0), color = color.cyan)

# Two major ticks (at 12):
Topticks = cylinder(length = MtickL, radius = Mtickrad, pos = vector(Toptickdist + Mtickrad/2, clockrad - MtickL - offset, 0), axis = vector(0, 1, 0))
Topticks = cylinder(length = MtickL, radius = Mtickrad, pos = vector(-(Toptickdist + Mtickrad/2), clockrad - MtickL - offset, 0), axis = vector(0, 1, 0))
# (No point in using a for loop here)

# Three remaining Major ticks (at 3, 6, & 9):
for angle in np.linspace(0, pi, 3):
Mtick = cylinder(length = MtickL, radius = Mtickrad, pos = vector((clockrad - MtickL - offset)*cos(angle), -(clockrad - MtickL - offset)*sin(angle), 0), axis = vector(cos(angle), -sin(angle), 0))

# Semi major ticks (every 5 minutes):
for angle in np.linspace(2*pi/12, 2*pi - 2*pi/12, 11):
SMtick = cylinder(length = SMtickL, radius = SMtickrad, pos = vector((clockrad - SMtickL - offset)*sin(angle), (clockrad - SMtickL - offset)*cos(angle), 0), axis = vector(sin(angle), cos(angle), 0))

# Minor ticks (every minute):
for angle in np.linspace(2*pi/60, 2*pi - 2*pi/60, 59):
mtick = cylinder(length = mtickL, radius = mtickrad, pos = vector((clockrad - mtickL - offset)*sin(angle), (clockrad - mtickL - offset)*cos(angle), 0), axis = vector(sin(angle), cos(angle), 0))

sechand = box(color = color.green, length = sechandL, height = sechandW, width = handD, axis = vector(0, sechandL/2, 0), pos = vector(0, sechandL/2, sechandH))
minhand = box(color = color.blue, length = minhandL, height = minhandW, width = handD, axis = vector(0, minhandL/2, 0), pos = vector(0, minhandL/2, minhandH))
hourhand = box(color = color.red, length = hourhandL, height = hourhandW, width = handD, axis = vector(0, hourhandL/2, 0), pos = vector(0, hourhandL/2, hourhandH))

while True:
for t in np.linspace(0, 2*1440*pi - 2*pi/60, 86400):
rate(1)
sechand.pos = vector((sechandL/2)*sin(t), (sechandL/2)*cos(t), sechandH)
sechand.axis = vector(sechandL*sin(t), sechandL*cos(t), 0)
minhand.pos = vector((minhandL/2)*sin(t/60), (minhandL/2)*cos(t/60), minhandH)
minhand.axis = vector(minhandL*sin(t/60), minhandL*cos(t/60), 0)
hourhand.pos = vector((hourhandL/2)*sin(t/720), (hourhandL/2)*cos(t/720), hourhandH)
hourhand.axis = vector(hourhandL*sin(t/720), hourhandL*cos(t/720), hourhandH)

JackVersey
Автор

1) Your videos rock! 2) I actually created a custom class of clocks back when you taught me how to do that (I also made one for thermometers), so I cheated a bit on the homework by using my old code. But I wouldn't have ever put that together if it weren't for your lessons. Thanks a bunch!

sherlocksrobot
Автор

I am Legend! Your lessons are not only interesting, they are also funny. I was amazed to see that you made the same mistake as I did in dividing by 60 instead of 12. Many of us, I think, are in this case.
My clock is very simple (no sugar, no sweetness...) but it works :

clockFace = cylinder(axis=vector(0, 0, -.01), radius=1)
rd = clockFace.radius

mHand = arrow(color=color.red, length=rd*.8, shaftwidth=.02*rd)
hHand = arrow(color=color.red, length=rd*.6, shaftwidth=.03*rd)
mHl, hHl = mHand.length, hHand.length

for nbTicks, size in ((13, .1), (61, .04)):
for theta in np.linspace(0, 2*np.pi, nbTicks):
ax=vector(rd*cos(theta), rd*sin(theta), 0)
box(axis=ax, pos=ax*.9, size=vector(rd*size, rd*.015, .01), color=color.black)

t = 0
while True:
t += .002
rate(300)
mHand.axis = vector(mHl*sin(t), mHl*cos(t), 0)
hHand.axis = vector(hHl*sin(t/12), hHl*cos(t/12), 0)

jeas
Автор

Yes, I did it. Not the same as Paul, but it worked. I couldn't resist putting it in a Clock class for later maybe. I found it easier to work in degrees ie range(0, 360, 6) and convert degrees to radians as doing linspace had rounding errors.

steveholt
Автор

I really enjoyed the homework from lesson 13. I am lgend. It was challenging for me to figure out how to get the tick/minute marks the way they should be. Over all it probably took me about three hours to complete, as my poor laptop does not like running two animations at the same time, and it took forever for me to finally accept my laptops limits.

starRunnerX
Автор

There are still protuberances of the tick mark edges outside of the clock face from where the linear width of the tickmark rectangle meet the arc (that has curvature) of the clock cylinder that need to be fixed.

thomaskosvic
Автор

That was a tough one and I didn't manage it but I learnt a lot from this tutorial and I have added heaps of comments to your code. Now I have to review again to fully understand it.

Mr '\' is your friend to allow a line of code to extend to a new line. Saves all that tedious horizontal scrolling along long lines of code.

Additionally, to defeat the autocomplete prompt when you type 'import numpy' just type a space and the autocomplete disappears.

All in all I don't regard Visual Studio Code as the 'most excellent', I'd probably call it 'mostly excellent'. When I can tear myself away from your tutorials, (maybe after the Visual Python set), I will do a deep dive into the settings for this program and try and make it less intrusive while I am typing. If I'm stuck for the arguments etc for a function I'll check the language documentation rather than have a huge popup which obscures several lines of code as well as my CURSOR!!

martinjones