Instructions for treeTops

(produced at 02:51 a.m. UTC on 2023-09-19)

This task is part of project03 which is due at 23:00 EDT on 2023-09-26.

You have the option to work with a partner on this task if you wish. Working with a partner requires more work to coordinate schedules, but if you work together and make sure that you are both understanding the code you write, you will make progress faster and learn more.

You can download the starter code for this task using this link.

You can submit this task using this link.

Put all of your work for this task into the file treeTops.py
(which is provided among the starter files)

For this problem set, you have a choice: you may complete this task OR the highNotes task, but you do not need to complete both. treeTops (this task) is graphics-oriented and works with turtle graphics, while highNotes is based on audio and music instead, using the wavesynth library.

This task will help you practice the material on custom functions and how to use several functions together to achieve a complicated result. It will also have you work with functions that have both side effects and return values.

In this task, your ultimate goal is to draw simulated twigs, branches, and ultimately trees, like these ones:

On the left are two twigs, each composed of a brown line with two thick
green lines representing leaves branching from the tip. One twig is pointing upwards and the other downwards, each has a dashed blue line which indicates the top point of the twig (leaf tip for the one pointing up and branch base for the one pointing down). In the center, there's a branch, which is a brown line with three twigs branching from its tip (one straight and the others to the left and right). The branch has different bark and leaf colors, and is angled sideways, pointing up and to the left and a shallow angle from the horizontal. This means that it's highest point is the right-most leaf of its right-most twig, and again there is a dashed blue line marking this highest point. Finally, on the right, there is an entire tree: a thick brown line with four branches coming out of the end (angled equally around the direction of the trunk; two on either side). Since the tree is facing straight up, its middlemost leaves reach the highest, and there is a dashed blue line marking that highest point.

In addition to drawing the tree parts, your code will be able to calculate the highest point on each part, as marked by the dashed blue lines in the picture above.

You will accomplish this task by completing several subtasks. You should do these subtasks in order.

Tree Size and Shape

The size of a tree is determined by arguments to the tree function: The trunk, branch, and twig lengths, the trunk diameter, and the bark and leaf colors. The following schematic shows the length of each part of a tree, with the values for these arguments shown on the left. It also shows the angles between different parts of the tree (which don't change). The same distances and angles shown in this diagram are also described below.

A schematic of the tree that diagrams the distances and angles explained below. The color used is "DarkOrange4", which is a medium-dark vibrant brown color like the color of milk chocolate.

  • Angles The angle of the entire tree is determined by the first parameter of tree, measured in degrees counterclockwise from due East (which is the same way that setheading works, and you must use setheading within tree to set the angle). Other angles are all pre-determined, and they include:
    • The two leaves attached to each twig have a 40° angle between them.
    • There are 40° angles between each pair of twigs, so the total angle from the leftmost to the rightmost twig is 80°.
    • There are 40° angles between each pair of branches, so the total angle from the leftmost to the rightmost branch is 120°.
  • Pen Sizes The pen size (i.e., diameter) for the trunk is determined by the second argument to tree. The branches and twigs each use a pen size that's half of this trunk diameter. The leaves will be drawn using the provided leaf function, so you don't have to worry about their diameters.
  • Lengths The values of the third, fourth, and fifth arguments to tree determine the lengths for the trunk, for the branches, and for the twigs respectively. The length of each leaf is 1/2 the length of the twig it's attached to.
  • Colors The bark and leaf colors are specified by the last two arguments to tree.

Subtask A: twig

First is the twig function, which takes four parameters: diameter, length, bark color, and leaf color. It has to: 1. Draw a straight line using the specified pen size (i.e., diameter), length, and bark color. 2. Draw two leaves at the end of this line, at 20° left and right from the orientation of the line (using the leaf function). 3. Go back to where it started in terms of both position and orientation, and make sure to leave the pen down. 4. Return the height of the highest point on the twig as its result value.

The first example shows how the twig function should work, including what it should draw, what it should print (due to turtleBeads) and what its result value should be. The provided test_treeTops.py file includes two tests for twig. These tests and the example below demonstrate that the 'top' of the tree doesn't account for the pen width: the measured value is the highest point that the turtle touches, regardless of how thick a line it draws. This is why the blue lines in some demos are drawn below the top-most colored-in region. Note that your printed output may appear in a different order from that shown in the snippet if you draw things in a different order, but the provided tests will accept any drawing order.

To figure out the highest point on the twig, you need to compute the maximum out of three possibilities: the highest point on the first leaf, the highest point on the second leaf, or the base of the twig (the point in the middle of the twig cannot be the highest point, because one of the other three points just mentioned would be higher). Because the leaf function already returns the highest point between the two ends of the leaf, your twig function must use max to find the largest value between these two results and the result of calling ycor.

ycor is a turtle function which returns the Y-coordinate of the turtle's current position; you will need to make sure that you call ycor while the turtle is at the base of the twig.

Subtask B: branch

The branch function draws a line and then three twigs branching out from that, and it needs to return the y-coordinate of the highest point on the branch, just like twig did. branch has five parameters:

  1. The diameter of the branch.
  2. The length of the branch.
  3. The length to use for each twig attached to the branch.
  4. The bark color
  5. The leaf color.

branch must call twig exactly three times, using the same diameter as it received and the specified twig length, along with the bark and leaf colors. It must store the results of these calls in variables, because it will need them to compute the highest point using ycor to get the y-coordinate of the base of the branch and using max to find the highest point among that point and the top points returned by each twig.

As with twig, branch must put the turtle back where it started when it is done.

This example shows what the branch function should draw, print, and return. We've provided one test in test_treeTops.py that tests the branch function. As with twig, your parts may be drawn in a different order, but this is fine as long as all of the correct pieces get drawn (the provided test will accept any drawing order).

Subtask C: tree

Finally, you are ready to draw a tree. The tree function has seven parameters, which specify:

  1. The angle (in degrees counterclockwise from due East) for the trunk (and thereby, the rest of the tree). You must use setheading to point the turtle in this direction before you start to draw the tree.
  2. The diameter of the trunk (i.e., the pen size value to use).
  3. The length of the trunk.
  4. The length of each branch.
  5. The length of each twig.
  6. The bark color (as a string).
  7. The leaf color (also a string).

The tree function draws a line for the trunk, and then has four branches in total, each of which is drawn using the branch function.

Unlike twig and branch, tree does NOT have to put the turtle back where it started when it is done, but like those functions, tree must return the y-coordinate of the highest point on the tree. It must do this by using max to find the maximum among the highest point returned by each branch, as well as the base of the tree (measured using ycor).

This tree example shows what the tree should look like.

Note that:

  • The diameter of the twigs and branches is half of the trunk diameter.
  • Drawing can be rather slow if you do not use noTrace. If you do use noTrace, remember to use showPicture.

Testing

We have provided tests in test_treeTops.py that use optimism to check both the results from your functions and parts of their printed output (which serves to confirm what they draw, since optimism can't check turtle drawings directly). This testing code also draws dotted blue lines based on the return values from your functions, if these are not in the right places, then your returned top points may be wrong. The very first image at the top of these instructions shows the correct appearance for the turtle window if all tests are working correctly, but you should also review the printed output in the Thonny shell to see if it has any failure messages.

Notes

Examples

Twig

This example shows what the twig function should draw, print, and return. It also includes some code to draw a blue line that illustrates the result value. As long as your result value is the same as the value shown here to within about 3 decimal places, that's good enough. Note that when the function is finished, the turtle is positioned back at the base of the twig, in the same place (and oriented in the same direction) that it started in. This is true for the following examples as well.

In []:
# Draw the twig: top = twig(10, 100, 'Sienna', 'SpringGreen2') # Show the turtle's position (it's back at the start) color('black') stamp() # Print a message and draw a line showing how high the top is print("The highest point is at y=" + str(round(top, 3))) teleport(-400, top) setheading(0) color('blue') pensize(0.5) fd(800) hideturtle()
Prints
A 10-pensize Sienna horizontal line from (0, 0) to (100, 0). A 25-pensize SpringGreen2 20° line from (100, 0) to (147, 17). A 25-pensize SpringGreen2 160° line from (100, 0) to (147, -17). The highest point is at y=17.101 A 0.5-pensize blue horizontal line from (-400, 17) to (400, 17).
Image 
A brown twig (a line) pointing to the right of the origin, with two
thick rounded green lines (leaves) attached to its end. The leaves are
angled +20° and -20° relative to the twig itself, which is perfectly
horizontal. A blue line drawn horizontally across the picture to
illustrate the height of the top of the twig; it goes through the end
point of the left leaf.

Branch

This example shows what the branch function should draw, print, and return. As with the twig, it's okay if your result value differs by a small amount (e.g., less than .01). Note how the height of the top point is measured relative to the origin (y=0), rather than to the base of the branch (which is this case has a negative y coordinate).

In []:
# First, rotate a bit and back up lt(25) leap(-60) # Draw the branch: top = branch(12, 80, 50, 'Wheat4', 'DarkOliveGreen2') # Show the turtle's position (it's back at the start) color('black') stamp() # Print a message and draw a line showing how high the top is print("The highest point is at y=" + str(round(top, 3))) teleport(-400, top) setheading(0) color('blue') pensize(0.5) fd(800) hideturtle()
Prints
A 12-pensize Wheat4 25° line from (-54, -25) to (18, 8). A 12-pensize Wheat4 65° line from (18, 8) to (39, 54). A 12.5-pensize DarkOliveGreen2 85° line from (39, 54) to (41, 79). A 12.5-pensize DarkOliveGreen2 45° line from (39, 54) to (57, 71). A 12-pensize Wheat4 25° line from (18, 8) to (63, 30). A 12.5-pensize DarkOliveGreen2 45° line from (63, 30) to (81, 47). A 12.5-pensize DarkOliveGreen2 5° line from (63, 30) to (88, 32). A 12-pensize Wheat4 165° line from (18, 8) to (66, -4). A 12.5-pensize DarkOliveGreen2 5° line from (66, -4) to (91, -2). A 12.5-pensize DarkOliveGreen2 145° line from (66, -4) to (87, -19). The highest point is at y=78.673 A 0.5-pensize blue horizontal line from (-400, 79) to (400, 79).
Image 
A brown branch pointing 25° up and to the right, starting below and to
the left of the origin and passing through it. It has three twigs
attached to its end, each of which is a brown line with two green lines
(leaves) attached (see previous description). The twigs are angled at
-40°, 0°, and +40° relative to the angle of the branch, and their bases
are at the tip of the line that forms the branch. A blue line is drawn
horizontally across the picture through the tip of the leftmost leaf,
which is the highest point on the whole branch.

Tree

This example shows what the tree function should draw, print, and return. Once again, your result value doesn't have to be perfectly exact, and the blue line illustrates the tree height. Notice that the turtle's final position (indicated by the black stamp) is NOT the same as its starting position.

In []:
# Setup teleport(0, -120) # Draw the tree top = tree(85, 18, 210, 140, 60, "Chocolate4", "Chartreuse2") # Show the turtle's position (it's back at the start) color('black') stamp() # Print a message and draw a line showing how high the top is print("The highest point is at y=" + str(round(top, 3))) teleport(-400, top) setheading(0) color('blue') pensize(0.5) fd(800) hideturtle()
Prints
A 18-pensize Chocolate4 85° line from (0, -120) to (18, 89). A 9-pensize Chocolate4 25° line from (18, 89) to (145, 148). A 9-pensize Chocolate4 65° line from (145, 148) to (171, 203). A 15-pensize Chartreuse2 85° line from (171, 203) to (173, 233). A 15-pensize Chartreuse2 45° line from (171, 203) to (192, 224). A 9-pensize Chocolate4 25° line from (145, 148) to (200, 174). A 15-pensize Chartreuse2 45° line from (200, 174) to (221, 195). A 15-pensize Chartreuse2 5° line from (200, 174) to (229, 176). A 9-pensize Chocolate4 165° line from (145, 148) to (203, 133). A 15-pensize Chartreuse2 5° line from (203, 133) to (233, 135). A 15-pensize Chartreuse2 145° line from (203, 133) to (228, 116). A 9-pensize Chocolate4 65° line from (18, 89) to (77, 216). A 9-pensize Chocolate4 105° line from (77, 216) to (62, 274). A 15-pensize Chartreuse2 125° line from (62, 274) to (45, 299). A 15-pensize Chartreuse2 85° line from (62, 274) to (65, 304). A 9-pensize Chocolate4 65° line from (77, 216) to (103, 270). A 15-pensize Chartreuse2 85° line from (103, 270) to (105, 300). A 15-pensize Chartreuse2 45° line from (103, 270) to (124, 292). A 9-pensize Chocolate4 25° line from (77, 216) to (132, 241). A 15-pensize Chartreuse2 45° line from (132, 241) to (153, 263). A 15-pensize Chartreuse2 5° line from (132, 241) to (162, 244). A 9-pensize Chocolate4 105° line from (18, 89) to (-18, 224). A 9-pensize Chocolate4 145° line from (-18, 224) to (-67, 259). A 15-pensize Chartreuse2 165° line from (-67, 259) to (-96, 267). A 15-pensize Chartreuse2 125° line from (-67, 259) to (-84, 283). A 9-pensize Chocolate4 105° line from (-18, 224) to (-33, 282). A 15-pensize Chartreuse2 125° line from (-33, 282) to (-51, 307). A 15-pensize Chartreuse2 85° line from (-33, 282) to (-31, 312). A 9-pensize Chocolate4 65° line from (-18, 224) to (7, 279). A 15-pensize Chartreuse2 85° line from (7, 279) to (10, 309). A 15-pensize Chartreuse2 45° line from (7, 279) to (29, 300). A 9-pensize Chocolate4 145° line from (18, 89) to (-96, 170). A 9-pensize Chocolate4 5° line from (-96, 170) to (-156, 164). A 15-pensize Chartreuse2 25° line from (-156, 164) to (-183, 152). A 15-pensize Chartreuse2 165° line from (-156, 164) to (-185, 172). A 9-pensize Chocolate4 145° line from (-96, 170) to (-146, 204). A 15-pensize Chartreuse2 165° line from (-146, 204) to (-175, 212). A 15-pensize Chartreuse2 125° line from (-146, 204) to (-163, 228). A 9-pensize Chocolate4 105° line from (-96, 170) to (-112, 227). A 15-pensize Chartreuse2 125° line from (-112, 227) to (-129, 252). A 15-pensize Chartreuse2 85° line from (-112, 227) to (-109, 257). The highest point is at y=312.272 A 0.5-pensize blue horizontal line from (-400, 312) to (400, 312).
Image 
A brown tree consisting of a line pointing 85° upwards with four branches
sprouting from its tip. Each branch has the structure described earlier
including three twigs and two leaves per twig. The branches are at -60°,
-20°, +20°, and +60° relative to the trunk. Note that the widths of the
branches and twigs are half the width of the trunk. A blue line is drawn
horizontally across the picture, passing through the topmost leaf tip,
which is the tip of the right leaf of the center twig on the center-left
branch.

Rubric

Group goals:
 
unknown All functions are documented
Each function you define must include a non-empty documentation string as the very first thing in the function.
 
unknown Do not define functions inside of other functions
None of your function definitions may be placed inside of other function definitions.
 
unknown Do not ignore the results of any fruitful function calls
According to the "Don't waste fruit" principle, every place you call a fruitful function (built-in or custom) you must store the result in a variable, or that function call must be part of a larger expression that uses its return value.
 
unknown Do not create any variables that you never make use of
According to the "Don't waste boxes" principle, every time you create a variable (using = or by defining a parameter for a function) you must also later use that variable as part of another expression. If you need to create a variable that you won't use, it must have the name _, but you should only do this if absolutely necessary.
 
unknown twig must return the correct result
The result returned when your twig function is run must match the solution result.
 
unknown branch must return the correct result
The result returned when your branch function is run must match the solution result.
 
unknown tree must return the correct result
The result returned when your tree function is run must match the solution result.
 
unknown twig net turtle movement
We will check the position and orientation of the turtle before and after twig is called. Any changes in the turtle's state must match exactly what is specified in the problem set description.
 
unknown twig net turtle movement
We will check the position and orientation of the turtle before and after twig is called. Any changes in the turtle's state must match exactly what is specified in the problem set description.
 
unknown branch net turtle movement
We will check the position and orientation of the turtle before and after branch is called. Any changes in the turtle's state must match exactly what is specified in the problem set description.
 
unknown branch net turtle movement
We will check the position and orientation of the turtle before and after branch is called. Any changes in the turtle's state must match exactly what is specified in the problem set description.
 
unknown twig draws leaves correctly.
We will check the turtle x/y position, heading, and pen state before each call to leaf made during a call to twig, along with the argument given to leaf. Regardless of order, these must match the correct positions and arguments.
 
unknown twig draws leaves correctly.
We will check the turtle x/y position, heading, and pen state before each call to leaf made during a call to twig, along with the argument given to leaf. Regardless of order, these must match the correct positions and arguments. These checks will move the turtle from the default starting position before twig is called.
 
unknown branch draws leaves correctly.
We will check the turtle x/y position, heading, and pen state before each call to leaf made during a call to branch, along with the argument given to leaf. Regardless of order, these must match the correct positions and arguments.
 
unknown branch draws leaves correctly.
We will check the turtle x/y position, heading, and pen state before each call to leaf made during a call to branch, along with the argument given to leaf. Regardless of order, these must match the correct positions and arguments. These checks will move the turtle from the default starting position before branch is called.
 
unknown tree draws leaves correctly.
We will check the turtle x/y position, heading, and pen state before each call to leaf made during a call to tree, along with the argument given to leaf. Regardless of order, these must match the correct positions and arguments.
 
unknown tree draws leaves correctly.
We will check the turtle x/y position, heading, and pen state before each call to leaf made during a call to tree, along with the argument given to leaf. Regardless of order, these must match the correct positions and arguments. These checks will move the turtle from the default starting position before tree is called.
 
unknown Define twig with 4 parameters
Use def to define twig with 4 parameters
 
unknown Call ycor
Within the definition of twig with 4 parameters, call ycor in at least one place.
 
unknown Call max
Within the definition of twig with 4 parameters, call max in at least one place.
 
unknown Call leaf
Within the definition of twig with 4 parameters, call leaf in exactly 2 places.
 
unknown Define twig with 4 parameters
Use def to define twig with 4 parameters
 
unknown Do not call setheading
Within the definition of twig with 4 parameters, do not call setheading, seth, or setHeading.
 
unknown Define branch with 5 parameters
Use def to define branch with 5 parameters
 
unknown Call ycor
Within the definition of branch with 5 parameters, call ycor in at least one place.
 
unknown Call max
Within the definition of branch with 5 parameters, call max in at least one place.
 
unknown Call twig
Within the definition of branch with 5 parameters, call twig in exactly 3 places.
 
unknown Define branch with 5 parameters
Use def to define branch with 5 parameters
 
unknown Do not call setheading
Within the definition of branch with 5 parameters, do not call setheading, seth, or setHeading.
 
unknown Define tree
Use def to define tree
 
unknown Call ycor
Within the definition of tree, call ycor in at least one place.
 
unknown Call max
Within the definition of tree, call max in at least one place.
 
unknown Call setheading
Within the definition of tree, call setheading, seth, or setHeading in at least one place.
 
unknown Call branch
Within the definition of tree, call branch in exactly 4 places.