$ mkdir ~/cs170/labs/lab12 $ cd ~/cs170/labs/lab12
Fractals are mathematicals structures that exhibit self-similarity on an astonishing scale. The beauty of the fractal isn't always the incredibly complicated pattern that arises. Many times the real beauty of the fractal is the really elegant and simple recursive definition that generates it.
The Sierpinski triangle (or the Sierpinski Gasket) is a fractal that is probably fairly familiar to you,
. The real Sierpinski Triangle has an infinite depth. Our version of a Sierpinski Triangle will have a fixed, finite depth.Construction of a Sierpinski Triangle is very straight forward:
Draw a triangle.
Draw another triangle by connecting the midpoints of the three sides of your original triangle. This will split your triangle into four smaller triangles: one in the center, and three around the outside.
Repeat step 2 for each of the outside triangles.
You might want to draw a few rounds of this on paper, just to see how it works.
Create a file called sierpinski.py. This program should draw a sierpinski triangle that fills as much of a tk window as possible. You will want to define a global constant DEPTH, which is how deep your recursive process should continue. Let's define the depth of a sierpinski triangle as the number of directly nested triangles at the deepest point. So a triangle is a sierpinski triangle of depth 0. When you draw the first internal triangle you have a depth of 1, etc. A DEPTH of 8 or 9 gives a nice looking triangle in a reasonable amount of time.
Try changing the colors of your triangles and the location of the starting verticies, to create a more interesting fractal. When you are happy with your fractal, take a screen shot and save the image in your directory.
The midpoint of a line segment can be calculated using linear interpolation. In order to find a point that is some fraction between two points \((x_1, y_1)\) and \((x_2, y_2)\) the following equation can be used:
\[ \begin{eqnarray} x_i &=& t \times x_2 + (1 - t) \times x_1\\ y_i &=& t \times y_2 + (1 - t) \times y_1 \end{eqnarray} \]Where t is a floating point value between 0 and 1 that represents the fraction of the distance between points 1 and 2 that \((x_i, y_i)\) is located. For the midpoint, you want t = 0.5.
On the surface, it might not seem like the order you specify the points matters. However, it really does. You should always specify the points for your triangle in the same order, in the same direction. I suggest clock-wise starting with the northern most point.
Seeing the triangle generated is one thing. However, seeing all of
the steps of the generation is really interesting, to see how each
recursive step changes. Add a Scale
widget to your program, which controls the maximum depth that the
triangle gets drawn to. You should make sure that the triangle gets
updated with every change of the scale.
The Koch snowflake (sometimes called the Koch curve or Koch Star) is one of the earliest known fractals. Similar to the Sierpinski Triangle, it starts off with a triangle shape. However, instead of recursing towards the inside of the triangle, the snowflake grows outwards. The concept of the snowflake is easy, but you will need to spend some time thinking about where your should be performing certain tasks.
Once again, the formal definition recurses infinitely. We will want to create a global constant DEPTH, which is going to represent how deep we generate the snowflake.
The snowflake begins by using 3 line segments to form a triangle (This is a Koch snowflake of order 0). The algorithm for generating higher order fractals involves splitting each line segment into three equal segments, then replacing the middle segment by two line segments that protrude outwards. The same algorithm is then recursively applied to each of the 4 new line segments. See the diagram below:
The actual amount that the point \((x_3, y_3)\) protrudes is up to you, but a value that is about one third of the original segment length produces a nice looking fractal.
You can use trigonometry to figure out the (x_{3}, y_{3}) point, but that begins to become very complex as the line segment sizes get very low. Instead, you can compute this protrusion directly using the following equations:
\[ \begin{eqnarray} x_3 &=& x_1 + \frac{\Delta x}{2} - \Delta y \times p\\ y_3 &=& y_1 + \frac{\Delta y}{2} + \Delta x \times p \end{eqnarray} \]where
\[ \begin{eqnarray} \Delta x &=& x_5 - x_1\\ \Delta y &=& y_5 - y_1 \end{eqnarray} \]and p is a value between -1 and 1 that is the percent length of the original segment that the protrusion will be. That is, if p is 0.5 then the protrusion would be half the size of the segment from \((x_1, y_1)\) to \((x_5, y_5)\). If p is -0.5 then it would also be half the size of the segment, but protrude off of the other side of the segment.
Try changing the color of the triangles and the location and number of original line segments. Also play around with the amount of protrusion you are using. When you are happy with your fractal, take a screen shot of it and save it in your directory.
In order to calculate the four line segments that represent the transformation of the segment defined by the points (x_{1}, y_{1}) and (x_{5}, y_{5}) the points that divide the segment into thirds, (x_{2}, y_{2}) and (x_{4}, y_{4}), must be calculated. These can be calculated using interpolation and the equations from earlier.
It may seem counter-intuitive, but the only place you want to perform any drawing is your base case. If you draw in a different location, you are going to end up with line segments you need to erase, which is going to make your code quite ugly.
The typical definition of the koch snowflake uses triangles. However, triangles are a little played out. Instead of using triangles, let's use a different polygon, like a square. For each line segment in the original shape, instead of protruding out to a point, create a square with the protrusion. How different does the curve look afterwards?
Play around with different types of polygons. Do any of them create interesting shapes?
When you have finished, create a tar file of your lab12
directory. To create a tar file, execute the following commands:
cd ~/cs170/labs tar czvf lab12.tgz lab12/
To submit your activity, go to inquire.roanoke.edu. You should
see an available assignment called Lab Assignment 12
.
Make sure you include a header listing the authors of the file.