On this page:
Warm-up:   A Couple Circles and Several Spirals
A Generative Fractal
Koch Style Fractal
Accumulators

Lab 10h Generative Recursion and Accumulators: Drawing Cool Stuff

home work!

Purpose This lab is lets you play more with cool generative recursion and accumulators.

Warm-up: A Couple Circles and Several Spirals

We want to begin by drawing some circles and before we start, here is a bit of setup code:

(require 2htdp/image)
(require 2htdp/universe)
 
; Constants
(define WIDTH 300)
(define HEIGHT 160)
(define MT (empty-scene WIDTH HEIGHT))
 
; next-size : Number -> Number
(define (next-size s)
  (/ s 2))

This is our first target image. Note that the circles get smaller as they move to the right.

Exercise 1 Design the function circles that takes two numbers, x and size and a Scene scn. If size is less-than or equal to 2, then your function returns the scn unchanged (base case). Otherwise, your function should place a circle in the Scene that results from a recursive call to circles with x shifted by (+ size (next-size size)), a new size of (next-size size), and using the original Scene.

Exercise 2 Adjust next-size so that it divides by 3/2 (or something a bit smaller), instead of 2. Modify WIDTH so you get something like the image below.

Exercise 3 Now we create a similar function spiral that takes four numbers and a Scene. In addition to x and size, the function also takes y and ang, which represent the center y coordinate of a circle, and the current angle (in radians).

Hint In your recursive call to spiral, you must update x and y based on your expert knowledge of trigonometry: next-x = x + (size+nextsize) * cos(ang) next-y = y + (size+nextsize) * sin(ang) Hint You can also add to the ang. Try (/ pi 10). Using that starting angle should give you something like the image below.

Exercise 4 Modify the various parameters to your function to get interesting results. For example, if you modify the function to be structurally recursive (using sub1 instead of next-size), and draw the same size circles each time (be sure you terminate!), you might get something like the image below.

A Generative Fractal

Now that we’ve refreshed your trig senses, lets do a few generative fractals. First up is a simple "tree" fractal.

Here’s some helper code to get you started:

; put-line : Number Number Number Number String Scene -> Scene
; Put a line in the scene starting at (x,y) len distance in the given direction
;   with the given color
(define (put-line x y ang len color scn)
  (place-image (line (* (cos ang) len)
                     (* (sin ang) len) color)
               (+ x (* (cos ang) (/ len 2)))
               (+ y (* (sin ang) (/ len 2))) scn))

Exercise 5 Design the function tree that takes four numbers, x, y, ang and len and draws a tree into a given Scene. If the length is less than 3, then the function just puts a line at x/y/ang/len of some color (say green?) into the scene.

Otherwise the function puts a brown line at x/y/ang/len, and recursivaly calls itself twice: once with x/y placed one third up the trunk at an angle off to the left, and another with x/y placed two thirds up the trunk at an angle off to the right. The length should be cut in half.

Hint Altogether it should be something like: next-x = x + len/3 * cos(ang) next-y = y + len/3 * sin(ang) next-ang = ang + pi/3 next-len = len/2

And the same for ang - pi/3, at 2*len/3 away.

You should be able to modify the parameters to get various images such as the using pi/6. That only cut the length in half.

Koch Style Fractal

Exercise 6 Similar to the tree fractal, we can do interesting things by changing recursive calls. The Koch snowflake is a rather cool recursive fractal. is a rather cool recursive fractal. Design the function koch that takes the same arguments as tree, with an additional iter parameter that tracks the number of iterations left. For each iteration you cut the line into three pieces and make four recursive calls. The key is that you only put a line when the number of iterations are up (i.e., zero). The images below show the first 4 iterations and a more elaborate version (bigger, with 6 iterations), of a "snowflake" variation that I think looks pretty cool. See if you can emulate it.

Accumulators

Consider the program below. What does it do? Run it and find out.
(require 2htdp/image)
(require 2htdp/universe)
 
; Width and Height of our Scene
(define WIDTH 300)
(define HEIGHT 300)
 
; Basic empty scene
(define base-scene (empty-scene WIDTH HEIGHT))
 
; A World is a [Listof Posn]
 
; put-dot : Scene Posn -> Scene
; Put a single Dot into the Scene at the given Posn
(define (put-dot scn p)
  (place-image (circle 3 "solid" "blue")
               (posn-x p) (posn-y p)
               scn))
 
; draw-dots : World -> Scene
; Draw the dots of the World (a list of Posn)
(define (draw-dots ps)
  (cond [(empty? ps) base-scene]
        [else (put-dot (draw-dots (rest ps)) (first ps))]))
 
; mouse-click : World Number Number String -> World
; Add a new Posn to the World if the mouse was clicked
(define (mouse-event w x y what)
  (cond [(string=? what "button-down")
         (cons (make-posn x y) w)]
        [else w]))
 
(big-bang '()
          (to-draw draw-dots)
          (on-mouse mouse-event))

Exercise 7 Add a number/label to each dot by designing new functions, put-num-dot and draw-num-dots. Make sure draw-num-dots is in accumulator style. Example pictures shown below.

Hint: You’ll need to use text and number->string, which you might have already guessed.

If your numbers aren’t in order, then fix them so they do not change as dots are added. You may need to modify the accumulator’s starting value and its update expression.

Exercise 8 Design the function draw-lines, in accumulator style that draws lines between the dots. Hint: you’ll also want to pass the previous point’s coordinates (in addition to the accumulator) when you make your recursive call, since the image function line creates a line from (0,0) to the given x/y.

Exercise 9 Design the function draw-num-lines that draws both lines and number/labels on the dots. This function doesn’t have to be in accumulator style, but if you’re working off your other function it probably will be.

Examples: Original Just numbers Just lines All together