Instructions for treeSize

(produced at 02:39 a.m. UTC on 2021-09-22)

This task is part of ps03 which is due at 23:59 EDT on 2021-09-28.

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 submit this task using this link.

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

For this problem set, you have a choice: you must do tasks 1 and 2, but you only need to do one of tasks 3 and 4. Task 3 (this task) is graphics-oriented and works with turtle graphics, while task 4 is based on audio and music instead.

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 trees, like these ones:

An image of three 2-dimensional abstract trees each of which has the structure described below. The trees are arranged in a row, with a small tree on the left, a medium tree in the middle, and a large tree on the right.

In addition to drawing the trees, your code will be able to calculate the volume of their trunks and branches (not counting the leaves), based on different initial trunk sizes, effectively serving as a very rudimentary simulation of tree growth.

A single basic tree (which is all you need to program) looks like this:

An image of a tree, with a trunk that splits into four branches, each of which splits into three twigs, which are just lines that have two oval leaves on the end. There are a total of 17 lines: 1 trunk, 4 branches, and 12 twigs, and a total of 24 leaves. The exact dimensions and angles are described below.

Note that the position of the turtle is at the base of the trunk, which is where the turtle returns to when the tree is complete. The position of the turtle before tree is called determines the orientation of the tree. If you just call the tree function in a blank window without moving or turning first, the result looks like this:

A slightly smaller tree than the tree described above, with all of the same elements, drawn sideways facing East.

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

Note: you must include a non-empty docstring for each function you write.

Tree Size and Shape

The following schematic shows the length of each part of a tree drawn by calling tree('Sienna', 225), as well as the angles between key parts. This structure is always the same (given the same length value). The same distances and angles are also described below.

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

  • Color The color of each part of the tree except the leaves is specified by the first argument to tree, which in this case is 'Sienna'.
  • Lengths The second argument given to the tree function directly determines the length of the first line drawn (the trunk).
  • The length of each of the four branches is 3/5 (0.6) of the length of the trunk, and the length of each of the three twigs attached to each branch is 3/5 of the length of that branch. These lengths are 135 and 81 for the tree shown above.
  • The length of each leaf is 1/2 the length of a twig, or 40.5 for the tree shown above. You will use the provided leaf function to draw the leaves, so you don't have to worry about their widths.
  • Angles The four branches coming out of the trunk are symmetric around the line made by the trunk, and have an angle of 40° between each pair. The total angle between the leftmost and rightmost branches is 120°.
  • The three twigs coming from each branch are each separated by an angle 30°, and the center twig is aligned at the same angle as the branch, with a total angle of 60° between the left and right twigs for each branch.
  • The two leaves attached to each twig are drawn with their major axes at 30° angles from the angle of the twig, with 60° total between their major axes.
  • Pen Sizes The pen size (i.e., diameter) for the trunk is the square root of the length of the trunk, which is 15 in this case.
  • The diameter of each branch is calculated using the provided splitDiameter function with numSplits = 4 (since there are 4 branches), which ends up being 7.5.
  • By the same logic, the diameter of each twig is calculated from the branch diameter using splitDiameter with numSplits = 3, which gives a value of about 4.33.

Subtask A: twig

First is the twig function, which takes three parameters: barkColor, diameter, and length. It has to draw a straight line with the given pen color, pen size (i.e., diameter), and length, then draw two leaves at 30° left and right from its own orientation (using the leaf function), and then return to where it started. When it is done, it must leave the turtle in the same position and orientation that it started in.

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.

Note that the turtle position after twig is done must be the same as where it was when it started. Note that our code draws left-hand leaves before right-hand leaves, and your result will look different if you draw them in the other order, but it will still be correct as long as you draw both leaves in the correct positions and with the correct orientations.

Your twig function must be fruitful: it must return the total volume of the woody part of the twig, which we model as a cylinder with the given diameter and length. You must use the provided cylinderVolume function to compute this volume.

The twig function should automatically print messages as it draws, which are included in the example.

Subtask B: branch

The branch function draws a line and then three twigs branching out from that, and it needs to return the total volume of all three twigs that are it draws, plus the volume of the branch itself. branch takes three arguments:

def branch(barkColor, diameter, length):
  • barkColor to specify the color to use.
  • diameter to control the pen size.
  • length to control the length of the line drawn.

To figure out the arguments that branch will pass to twig, note that the twig lengths are each 3/5 of the base branch length. For the diameters, use the provided splitDiameter function to compute the diameter of each twig based on splitting up the branch diameter into 3 parts.

(The splitDiameter function calculates the diameter for several smaller pipes such that their cross-sectional area is equal to the diameter of one larger pipe, using the formula for the area of a circle. Since tree branches function like pipes to transport water upwards from the roots to the leaves, this is approximately how tree branch diameters relate to each other as well.)

The three twigs are drawn 30° left, at the same angle, and 30° right compared to the angle of the branch.

You must use the twig function to draw the twigs (and their associated leaves), and you'll need to capture its results to figure out the total volume of the branch plus the twigs. Use the provided cylinderVolume function to calculate the contribution that the branch itself makes towards this total, but note that you may only use it once in the branch function itself: you'll have to rely on the twig function to give you the volumes for 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. As a reminder, you can use this free difference checker website to check for exact equivalence between two pieces of text, or you could also use optimism to test for certain outputs).

Subtask C: tree

Finally, you are ready to draw a tree. The tree function just two parameters:

  • barkColor defines the color for the tree.
  • length defines the length of the trunk.

Like branch and twig, tree must return the total volume of all woody parts that it draws, and it must do so by adding together the return values from each branch it draws, plus a value for the trunk itself, computed using cylinderVolume. Also similar to those functions, tree must put the turtle back where it started when it is done.

The diameter of the trunk is not provided as a parameter, and instead it is always set to the square root of the trunk length. The diameter of each branch must be computed using splitDiameter.

The tree function has four branches in total, each of which is drawn using the branch function. Each branch has a length equal to 3/5 of the trunk length, and the branches are evenly spaced across a 120° arc centered in the direction the trunk is facing (this means there is a 40° angle between each branch).

This example shows what the tree should look like, and it includes some set-up code so that the tree is actually standing up. The showTree testing function can be called to draw the same thing if your tree function is finished.

Testing

We have provided tests in the starter file 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).

The provided showTree and showGrowth functions can be used for manual testing. The tree example should look the same as what showTree draws, and showGrowth should draw something that looks like the first picture in these instructions.

The last four lines of output from showGrowth should be (note that it rounds to 3 decimal places, but you should not round your results):

Tree volumes are:
  Tree 1: 5033.009
  Tree 2: 10829.31
  Tree 3: 17938.778

Note that your tree should look correct even if the turtle starts at a position other than (0, 0) and faces a direction other than 0° or 90° (showTree tests this a bit).

If things are working correctly, then your code not only draws trees, but it's simulating their growth: you can call tree with different lengths to see how the volume of wood in a tree changes as the tree grows taller (this is a complicated relationship). Of course, our simulation is quite simplified: real trees don't just extend each part of themselves as they grow, but instead they grow new branches, and their complexity increases as well. We don't yet have the tools to produce a more realistic tree simulation, but once we cover recursion at the end of the class we will.

Notes

Examples

Twig

This example shows what the twig function should draw, print, and return. Note that it's okay if you draw the leaves in the other order causing them to overlap differently, as long as you draw them with the correct position/size/angle. Also, as long as your result value is the same as the value shown here to within about 3 decimal places, that's good enough. Finally, Note that the turtle is positioned back at the base of the branch, in the same place (and oriented in the same direction) that it started in. This is true for the following examples as well.

In []:
twig('Sienna', 10, 100)
Prints
A 10-pensize Sienna horizontal line from (0, 0) to (100, 0). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (122, 12) with a 25-unit major axis at 30° and a 12.5-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (122, -12) with a 25-unit major axis at 150° and a 12.5-unit minor axis Filled in shape using SpringGreen2.
Out[]:
3141.592653589793
Image A brown twig pointing to the right of the origin, with two green oval leaves attached to its end. The leaves are ellipses and the ends of their long axes touch the end of the brown line that makes up the twig. They are angled +30° and -30° relative to the twig itself, which is perfectly horizontal.

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).

In []:
branch('Sienna', 12, 80)
Prints
A 12-pensize Sienna horizontal line from (0, 0) to (80, 0). A 6.9-pensize Sienna 30° line from (80, 0) to (122, 24). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (128, 34) with a 12-unit major axis at 60° and a 6-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (134, 24) with a 12-unit horizontal major axis and a 6-unit minor axis Filled in shape using SpringGreen2. A 6.9-pensize Sienna horizontal line from (80, 0) to (128, 0). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (138, 6) with a 12-unit major axis at 30° and a 6-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (138, -6) with a 12-unit major axis at 150° and a 6-unit minor axis Filled in shape using SpringGreen2. A 6.9-pensize Sienna 150° line from (80, 0) to (122, -24). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (134, -24) with a 12-unit horizontal major axis and a 6-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (128, -34) with a 12-unit major axis at 120° and a 6-unit minor axis Filled in shape using SpringGreen2.
Out[]:
6150.17424884293
Image A brown branch pointing to the right of the origin, with three twigs attached to its end, each of which is a brown line with two green oval leaves attached (see previous description). The twigs are angled at -30°, 0°, and +30° relative to the angle of the branch, and their bases are at the tip of the line that forms the branch.

Tree

This example shows what the tree function should draw, print, and return. Some setup is included to draw the tree upright. Once again, your result value doesn't have to be perfectly exact.

In []:
# Setup lt(90) leap(-120) # Draw the tree tree('Sienna', 120)
Prints
A 11-pensize Sienna vertical line from (0, -120) to (0, 0). A 5.5-pensize Sienna 30° line from (0, 0) to (62, 36). A 3.2-pensize Sienna 60° line from (62, 36) to (84, 73). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (84, 84) with a 10.8-unit vertical major axis and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (93, 79) with a 10.8-unit major axis at 30° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 3.2-pensize Sienna 30° line from (62, 36) to (100, 58). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (105, 67) with a 10.8-unit major axis at 60° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (111, 58) with a 10.8-unit horizontal major axis and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 3.2-pensize Sienna horizontal line from (62, 36) to (106, 36). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (115, 41) with a 10.8-unit major axis at 30° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (115, 31) with a 10.8-unit major axis at 150° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 5.5-pensize Sienna 70° line from (0, 0) to (25, 68). A 3.2-pensize Sienna 100° line from (25, 68) to (17, 110). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (10, 118) with a 10.8-unit major axis at 130° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (21, 120) with a 10.8-unit major axis at 70° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 3.2-pensize Sienna 70° line from (25, 68) to (39, 108). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (38, 119) with a 10.8-unit major axis at 100° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (48, 115) with a 10.8-unit major axis at 40° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 3.2-pensize Sienna 40° line from (25, 68) to (58, 95). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (61, 106) with a 10.8-unit major axis at 70° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (68, 97) with a 10.8-unit major axis at 10° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 5.5-pensize Sienna 110° line from (0, 0) to (-25, 68). A 3.2-pensize Sienna 140° line from (-25, 68) to (-58, 95). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-68, 97) with a 10.8-unit major axis at 170° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-61, 106) with a 10.8-unit major axis at 110° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 3.2-pensize Sienna 110° line from (-25, 68) to (-39, 108). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-48, 115) with a 10.8-unit major axis at 140° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-38, 119) with a 10.8-unit major axis at 80° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 3.2-pensize Sienna 80° line from (-25, 68) to (-17, 110). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-21, 120) with a 10.8-unit major axis at 110° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-10, 118) with a 10.8-unit major axis at 50° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 5.5-pensize Sienna 150° line from (0, 0) to (-62, 36). A 3.2-pensize Sienna horizontal line from (-62, 36) to (-106, 36). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-115, 31) with a 10.8-unit major axis at 30° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-115, 41) with a 10.8-unit major axis at 150° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 3.2-pensize Sienna 150° line from (-62, 36) to (-100, 58). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-111, 58) with a 10.8-unit horizontal major axis and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-105, 67) with a 10.8-unit major axis at 120° and a 5.4-unit minor axis Filled in shape using SpringGreen2. A 3.2-pensize Sienna 120° line from (-62, 36) to (-84, 73). Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-93, 79) with a 10.8-unit major axis at 150° and a 5.4-unit minor axis Filled in shape using SpringGreen2. Start of filled shape. A 2-pensize SpringGreen3 ellipse centered at (-84, 84) with a 10.8-unit vertical major axis and a 5.4-unit minor axis Filled in shape using SpringGreen2.
Out[]:
14235.498296908734
Image A brown tree consisting of a line pointing 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 (vertical, this time) trunk. Note that the widths of the trunk, branches, and twigs diminish at each level (see earlier description of their relationships).

Rubric

 
unknown Style Requirements
How your code is written.
 
unknown Core goals
Complete all core goals for core credit. Get partial credit for completing at least half, and more partial credit for completing at least 90%.
 
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 Procedure Requirements
What code you use to solve the problem.
 
unknown Core goals
Complete all core goals for core credit. Get partial credit for completing at least half, and more partial credit for completing at least 90%.
 
unknown Do not define functions inside of other functions
None of your function definitions may be placed inside of other function definitions.
 
unknown Define twig
Use def to define twig
 
unknown Call leaf
Within the definition of twig, call leaf in exactly 2 places.
 
unknown Call cylinderVolume
Within the definition of twig, call cylinderVolume in exactly one place.
 
unknown Define branch
Use def to define branch
 
unknown Call twig
Within the definition of branch, call twig in exactly 3 places.
 
unknown Call splitDiameter
Within the definition of branch, call splitDiameter in at least once place.
 
unknown Call cylinderVolume
Within the definition of branch, call cylinderVolume in exactly one place.
 
unknown Define tree
Use def to define tree
 
unknown Call branch
Within the definition of tree, call branch in exactly 4 places.
 
unknown Call splitDiameter
Within the definition of tree, call splitDiameter in at least once place.
 
unknown Call cylinderVolume
Within the definition of tree, call cylinderVolume in exactly one place.
 
unknown Do not use loops
Don't use advanced features yet.
 
unknown Extra goals
Complete all extra goals in addition to the core goals for a perfect score.
 
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 Product Requirements
Your code's result values.
 
unknown Core goals
Complete all core goals for core credit. Get partial credit for completing at least half, and more partial credit for completing at least 90%.
 
unknown twig returns the correct result
The result returned when your twig function is run must match the solution result.
 
unknown branch returns the correct result
The result returned when your branch function is run must match the solution result.
 
unknown tree returns the correct result
The result returned when your tree function is run must match the solution result.
 
unknown Behavior Requirements
What your code does from the user's perspective.
 
unknown Core goals
Complete all core goals for core credit. Get partial credit for completing at least half, and more partial credit for completing at least 90%.
 
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 tree net turtle movement
We will check the position and orientation of the turtle before and after tree 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 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 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 Extra goals
Complete all extra goals in addition to the core goals for a perfect score.
 
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 tree net turtle movement
We will check the position and orientation of the turtle before and after tree 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. 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. 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. These checks will move the turtle from the default starting position before tree is called.