Final Drawing project

After a lot of tinkering, I think I was able to get everything working
and the project was done in such a way that elements 20+ could be added
at a later time (without excessive code like before). I think I
learned a lot about functions and iteration in this project and
while the drawing itself is not super complex, I learned a lot about
functions and debugging. I am also happy that this will be something
that I could possibly use in teaching chemistry.
This commit is contained in:
Chris Mekelburg 2024-10-10 18:12:39 -04:00
parent 9cab60784c
commit 84c1c6cc27
2 changed files with 231 additions and 408 deletions

View File

@ -1,8 +1,8 @@
# drawing.py
# ----------
# By ____(you)___________
# By Chris Mekelburg
#
# (Briefly describe what this program does.)
# This program draws a Bohr model for any element from Hydrogen- Calcium (atomic #s 1-20)
from turtle import *
from math import sqrt
@ -15,14 +15,16 @@ ring_2_size= ring_1_size*2 #radii of shells 2-4
ring_3_size = ring_1_size*3
ring_4_size = ring_1_size*4
cycles =1 #relates to how fast the electrons move
cycles =1 #relates to how fast the electrons move
'''This function enables the user to pick and element and then retruns the number of
electrons for that element'''
def select_element():
choice = input("Enter the element symbol for any element with atomic number 1-10. What is your element?")
elements = ["H", "He", "Li", "Be", "B", "C", "N","O","F","Ne"]
choice = input("Enter the element symbol for any element with atomic number 1-20. What is your element?")
elements = ["H", "He", "Li", "Be", "B", "C", "N","O","F","Ne", "Na", "Mg", "Al", "Si", "P", "S","Cl", "Ar","K","Ca"]
while not (choice in elements):
print("Try again. Enter the element symbol for any element with atomic number 1-20. What is your element symbol?")
if choice in elements:
electron_number = elements.index(choice) + 1
return electron_number
@ -35,8 +37,9 @@ def return_to_center():
goto(0,0)
pendown()
'''Draws the nucleus, one dot per proton As wrriten keeps the nucleus centered but
'''Draws the nucleus, one dot per proton. As wrriten keeps the nucleus centered but
protons are not clearly outlined, however size of nucleus is proprotional to atomic number'''
def draw_nucleus(electron_number):
protons=electron_number
penup()
@ -45,223 +48,129 @@ def draw_nucleus(electron_number):
forward(sqrt(7.5))
pendown()
for proton in range(protons):
pencolor("Blue")
dot(ELECTRONSIZE)
right(36)
penup()
forward(sqrt(7.5))
pendown()
pencolor("Black")
if proton <10:
pencolor("Blue")
dot(ELECTRONSIZE)
right(36)
penup()
forward(sqrt(7.5))
pendown()
pencolor("Black")
else:
pencolor("Blue")
dot(ELECTRONSIZE*1.75)
right(36)
penup()
forward(sqrt(7.5))
pendown()
pencolor("Black")
return_to_center()
'''This function indicates the number of rings that will form, upt ot 2 electrons will eventually
go in ring 1 and 8 in ring 2. Has capability to have up to 4 rings if more atoms are added later. '''
'''This function indicates the number of rings that will form. Rings is called in a later function to
help determine where the electrons are located. '''
def number_of_rings(electron_number):
if electron_number < 3:
if electron_number <= 2:
rings = 1
return rings
if electron_number < 11:
rings = 2
return rings
if electron_number < 18:
if 3 < electron_number <= 10:
rings = 2
if 10 < electron_number <= 18:
rings = 3
return rings
elif electron_number < 21:
if 18 < electron_number <= 20:
rings = 4
return rings
return rings
'''This function draws the rings. Radius for smallest ring can be adjusted with
variable above.'''
variable above. This function also outputs the radius of each ring which can be called
in a later function.'''
def draw_ring(ring):
radius = ring*ring_1_size
circle(radius,360)
penup()
right(90)
forward(ring_1_size)
left(90)
pendown()
return_to_center()
radius = ring*ring_1_size
penup()
right(90)
forward(radius)
left(90)
pendown()
pencolor("black")
circle(radius,360)
return radius
def electron(radius):
"""Assumes the turtle already has the proper heading. Draws the electron at a certain
distance from the center and then returns the turtle to the center to draw the next
electron.
"""
with restore_state_when_finished():
pencolor("red")
penup()
forward(radius)
pendown()
dot(ELECTRONSIZE)
'''This function determines how far the electrons will be from each other in each ring.'''
def get_electron_ring_offset(ring, electron_number):
if ring ==1:
offset = 180
if ring ==2:
offset = 45
if ring ==3:
offset = 45
if ring ==4: #using if instead of else here enables incorporating more elements later, after #20 ring 3 can hold more electrons
offset = 45
return offset
'''This function animates the electrons and draws the appropraite number based on the
stored electron_number'''
'''This function determines how many electrons belong in each ring (shell) so that it can be called in a later function.'''
def electrons_per_shell(electron_number, ring):
if ring ==1:
if electron_number >= 2:
electrons_per_shelly = 2
else:
electrons_per_shelly = 1
if ring ==2:
if electron_number >=10:
electrons_per_shelly=8
else:
electrons_per_shelly = electron_number - 2
if ring == 3:
if electron_number >=18:
electrons_per_shelly = 8
else:
electrons_per_shelly = electron_number - 10
if ring ==4:
if electron_number >=36: #Ar
electrons_per_shelly = 8
else:
electrons_per_shelly = electron_number - 18
return electrons_per_shelly
def draw_and_move_electrons(electron_number):
if electron_number == 1:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
if electron_number ==2:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
if electron_number ==3:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
if electron_number ==4:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
if electron_number ==5:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
if electron_number == 6:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
if electron_number == 7:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(45)
electron(ring_2_size)
if electron_number == 8:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(45)
electron(ring_2_size)
right(180)
electron(ring_2_size)
if electron_number == 9:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(45)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
if electron_number == 10:
for frame in animate(360, loop=True):
draw_nucleus(electron_number)
'''This function draws an electron based on the radius (detemrines ring) and offset (how far apart the electrons are).'''
def draw_electron(radius, offset):
return_to_center()
rings= number_of_rings(electron_number) +1 #iterates to draw each ring
for ring in range(rings):
draw_ring(ring)
return_to_center()
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(45)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
#Code being run starts here
electron_number = select_element() #sets output from select_element and stores as variable
pencolor("red")
penup()
forward(radius)
pendown()
dot(ELECTRONSIZE)
penup()
return_to_center
right(offset)
electron_number = select_element() #input for which element to draw
rings=number_of_rings(electron_number) #saves rings variable for later use
#print(rings) helpful for troubleshooting
#print(electron_number)
for frame in animate(360, loop=True):
draw_nucleus(electron_number)
return_to_center()
rings_range = rings + 1 #adds 1 so that range function can be used later
with frame.rotate(0, 360):
with restore_state_when_finished():
for ring in range(1,rings_range): #iterates to draw each ring
radius2 = draw_ring(ring) #saves radius of each ring for use, new value on each iteration
offset = get_electron_ring_offset(ring,electron_number) #saves offset for later use, also new value on each iteration
electrons_per_shelly2 = electrons_per_shell(electron_number, ring) #saves electrons per shell so it can be called down below, also new on each iteration
#print(electrons_per_shelly2) helpful for troubleshooting
for electron in range(electrons_per_shelly2): #iterates to draw each electron
draw_electron(radius2, offset)
input() #pauses function so it does not close automatically
draw_and_move_electrons(electron_number) #draws electrons and moves them
draw_nucleus(electron_number)
return_to_center()
rings= number_of_rings(electron_number) +1 #iterates to draw each ring
for ring in range(rings):
draw_ring(ring)
input()

View File

@ -1,8 +1,8 @@
# drawing.py
# ----------
# By ____(you)___________
# By Chris Mekelburg
#
# (Briefly describe what this program does.)
# This program draws a Bohr model for any element from Hydrogen- Calcium (atomic #s 1-20)
from turtle import *
from math import sqrt
@ -15,14 +15,16 @@ ring_2_size= ring_1_size*2 #radii of shells 2-4
ring_3_size = ring_1_size*3
ring_4_size = ring_1_size*4
cycles =1 #relates to how fast the electrons move
cycles =1 #relates to how fast the electrons move
'''This function enables the user to pick and element and then retruns the number of
electrons for that element'''
def select_element():
choice = input("Enter the element symbol for any element with atomic number 1-10. What is your element?")
elements = ["H", "He", "Li", "Be", "B", "C", "N","O","F","Ne"]
choice = input("Enter the element symbol for any element with atomic number 1-20. What is your element?")
elements = ["H", "He", "Li", "Be", "B", "C", "N","O","F","Ne", "Na", "Mg", "Al", "Si", "P", "S","Cl", "Ar","K","Ca"]
while not (choice in elements):
print("Try again. Enter the element symbol for any element with atomic number 1-20. What is your element symbol?")
if choice in elements:
electron_number = elements.index(choice) + 1
return electron_number
@ -35,8 +37,9 @@ def return_to_center():
goto(0,0)
pendown()
'''Draws the nucleus, one dot per proton As wrriten keeps the nucleus centered but
'''Draws the nucleus, one dot per proton. As wrriten keeps the nucleus centered but
protons are not clearly outlined, however size of nucleus is proprotional to atomic number'''
def draw_nucleus(electron_number):
protons=electron_number
penup()
@ -45,218 +48,129 @@ def draw_nucleus(electron_number):
forward(sqrt(7.5))
pendown()
for proton in range(protons):
pencolor("Blue")
dot(ELECTRONSIZE)
right(36)
penup()
forward(sqrt(7.5))
pendown()
pencolor("Black")
if proton <10:
pencolor("Blue")
dot(ELECTRONSIZE)
right(36)
penup()
forward(sqrt(7.5))
pendown()
pencolor("Black")
else:
pencolor("Blue")
dot(ELECTRONSIZE*1.75)
right(36)
penup()
forward(sqrt(7.5))
pendown()
pencolor("Black")
return_to_center()
'''This function indicates the number of rings that will form, upt ot 2 electrons will eventually
go in ring 1 and 8 in ring 2. Has capability to have up to 4 rings if more atoms are added later. '''
'''This function indicates the number of rings that will form. Rings is called in a later function to
help determine where the electrons are located. '''
def number_of_rings(electron_number):
if electron_number < 3:
if electron_number <= 2:
rings = 1
return rings
if electron_number < 11:
rings = 2
return rings
if electron_number < 18:
if 3 < electron_number <= 10:
rings = 2
if 10 < electron_number <= 18:
rings = 3
return rings
elif electron_number < 21:
if 18 < electron_number <= 20:
rings = 4
return rings
return rings
'''This function draws the rings. Radius for smallest ring can be adjusted with
variable above.'''
variable above. This function also outputs the radius of each ring which can be called
in a later function.'''
def draw_ring(ring):
radius = ring*ring_1_size
circle(radius,360)
penup()
right(90)
forward(ring_1_size)
left(90)
pendown()
return_to_center()
radius = ring*ring_1_size
penup()
right(90)
forward(radius)
left(90)
pendown()
pencolor("black")
circle(radius,360)
return radius
def electron(radius):
"""Assumes the turtle already has the proper heading. Draws the electron at a certain
distance from the center and then returns the turtle to the center to draw the next
electron.
"""
with restore_state_when_finished():
pencolor("red")
penup()
forward(radius)
pendown()
dot(ELECTRONSIZE)
'''This function determines how far the electrons will be from each other in each ring.'''
def get_electron_ring_offset(ring, electron_number):
if ring ==1:
offset = 180
if ring ==2:
offset = 45
if ring ==3:
offset = 45
if ring ==4: #using if instead of else here enables incorporating more elements later, after #20 ring 3 can hold more electrons
offset = 45
return offset
'''This function determines how many electrons belong in each ring (shell) so that it can be called in a later function.'''
def electrons_per_shell(electron_number, ring):
if ring ==1:
if electron_number >= 2:
electrons_per_shelly = 2
else:
electrons_per_shelly = 1
if ring ==2:
if electron_number >=10:
electrons_per_shelly=8
else:
electrons_per_shelly = electron_number - 2
if ring == 3:
if electron_number >=18:
electrons_per_shelly = 8
else:
electrons_per_shelly = electron_number - 10
if ring ==4:
if electron_number >=36: #Ar
electrons_per_shelly = 8
else:
electrons_per_shelly = electron_number - 18
return electrons_per_shelly
'''This function draws an electron based on the radius (detemrines ring) and offset (how far apart the electrons are).'''
def draw_electron(radius, offset):
return_to_center()
pencolor("red")
penup()
forward(radius)
pendown()
dot(ELECTRONSIZE)
penup()
return_to_center
right(offset)
electron_number = select_element() #input for which element to draw
rings=number_of_rings(electron_number) #saves rings variable for later use
#print(rings) helpful for troubleshooting
#print(electron_number)
for frame in animate(360, loop=True):
draw_nucleus(electron_number)
return_to_center()
rings_range = rings + 1 #adds 1 so that range function can be used later
with frame.rotate(0, 360):
with restore_state_when_finished():
for ring in range(1,rings_range): #iterates to draw each ring
radius2 = draw_ring(ring) #saves radius of each ring for use, new value on each iteration
offset = get_electron_ring_offset(ring,electron_number) #saves offset for later use, also new value on each iteration
electrons_per_shelly2 = electrons_per_shell(electron_number, ring) #saves electrons per shell so it can be called down below, also new on each iteration
#print(electrons_per_shelly2) helpful for troubleshooting
for electron in range(electrons_per_shelly2): #iterates to draw each electron
draw_electron(radius2, offset)
input() #pauses function so it does not close automatically
'''This function animates the electrons and draws the appropraite number based on the
stored electron_number'''
def draw_and_move_electrons(electron_number):
if electron_number == 1:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
if electron_number ==2:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
if electron_number ==3:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
if electron_number ==4:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
if electron_number ==5:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
if electron_number == 6:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
if electron_number == 7:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(45)
electron(ring_2_size)
if electron_number == 8:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(45)
electron(ring_2_size)
right(180)
electron(ring_2_size)
if electron_number == 9:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(45)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
if electron_number == 10:
for frame in animate(360, loop=True):
with frame.rotate(0, 359, cycles=cycles):
right(90)
electron(ring_1_size)
right(180)
electron(ring_1_size)
with frame.rotate(0, -359, cycles=cycles):
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(45)
electron(ring_2_size)
right(180)
electron(ring_2_size)
right(90)
electron(ring_2_size)
right(180)
electron(ring_2_size)
#Code being run starts here
electron_number = select_element() #sets output from select_element and stores as variable
draw_nucleus(electron_number)
return_to_center()
rings= number_of_rings(electron_number) +1 #iterates to draw each ring
for ring in range(rings):
draw_ring(ring)
draw_and_move_electrons(electron_number) #draws electrons and moves them
input()