Recursive Mondrian

On this page, you will use recursion to create abstract art in the style of Piet Mondrian. Tough Stuff

  1. Recursion is not just for fractals. Search for the Dutch painter Mondrian to see examples of his artwork.
Why aren't these fractals?

They're like fractals in that the picture is made up of smaller pictures of the same kind. But, because of the use of randomness, the smaller pictures don't look quite like the big one. A fractal is "self-similar," which means that it looks just like a piece of itself.

Mondrian did not use a computer, but you can use recursion to model his paintings and create similar images. The base case is one rectangle with a black border around it. That's more complicated than any base case you have worked with before, so you'll use an abstraction called rectangle to hide the drawing script for the base case.
Mondrian picture created recursively Mondrian base case: a blue rectangle with a black border

  1. Click here to load a starter project. Then save it.

    Some code is already created for you. There is an instruction to initialize the colors variable with a list of commands.
    set (color) to {(set pen color to red), (set pen color to yellow), (set pen color to blue), (set pen color to white), (set pen color to black)}

    Notice that this is a list of scripts. The ability to use code as data is a very important abstraction in Snap!.

    There are partially written blocks for the base case, rectangle, and for the complete recursive procedure, Mondrian.
    rectangle, width: (400) height: (300) Mondrian, level: (5) width: (400) height: (300)

    You might want to make a script that starts with when (r) key pressed for the rectangle and another one with when (m) key pressed for the Mondrian. You can include a clear and the sprite's initial position and direction.

    There are also the two complete block definitions below. Read them both so you understand what they do.
    set pen to paint with thickness (thickness) {
    set pen size to (thickness)
    run (item (random) of (colors))
    set (flat line ends) to (true)
} set pen to black line {
    set pen size to (5)
    set pen (brightness) to (0)
    set (flat line ends) to (false)
}

  2. Finish programming the base case, the rectangle block. Your code should
    • Paint a rectangle with a random color.
    • Draw a black border.
    You can do these in either order, whichever works best with your algorithms.
  3. How do you paint?

    One way is to draw a line of color using the width or height of the rectangle as the pen size.

  4. Debug; be sure you have rectangle set up correctly. Each time you run it, you should see a rectangle with one of the five colors inside and a black border.
    Mondrian base case: a blue rectangle with a black border Mondrian base case: a yellow rectangle with a black border
  5. Start writing the code for Mondrian by writing its base case, which will just call rectangle.
  6. Now, program the code for the recursive case. Your code should
    Suggestion: If you have two slightly different cases that depend on which of width and height is bigger, you might make a Mondrian helper block as an abstraction for the part in common.
    • Decide how to subdivide the rectangle. Pick a random decimal value from 0.2 to 0.8 and store it in a variable; you will use it more than once.
    • Split the rectangle along whichever side is bigger: the width or the height.
    • Draw a lower-level Mondrian in each part.

      The 0.2 to 0.8 range makes sure that each subdivision is wide enough to see.

      How can you get the negative of a value?

      There are several ways:
      (0) - (value) (-1) × (value) (neg) of (value)

      Buggy code? Here are some things to consider.

      It will be easier to think about your code if rectangle and Mondrian are state invariant. The sprite should end up in the same position and direction as it started. Check for this in each piece of code (that is, in rectangle and in each branch of the if statement inside Mondrian).
      • If any piece of your code (such as rectangle or one branch of an if) turns, the sprite should finish facing in the same direction in which it started.
      • It's harder to keep your code state invariant if you move to a particular place or turn in a particular direction, such as by using go to, set x, set y, or point in direction. Instead, use blocks like turn ↻, turn ↺, and move so that you can undo these changes before leaving that piece of code.

      Here are a few tips for specific situations.

      • If you have two recursive calls to Mondrian in the same piece of code, it might help you debug to add a pause all just before the second one.
      • If your first recursive call moves width × fraction, make sure the second call moves through width × (1 - fraction).
      • If you sometimes rotate 90 degrees before a recursive call to Mondrian, you may need to swap width and height in the recursive call. This is possible but can be confusing to think through.
      When you have Mondrian working, it should produce pictures like this:
      Mondrian picture created recursively Mondrian picture created recursively
  7. Look at some actual Mondrian paintings and count how many rectangles he used in each. (If you visit other pages, make sure you are looking at actual Mondrians and not imitations, of which there are very many on the Web.) Think about what level input makes your pictures look as much like Mondrian's as possible.
  1. So far on this page, you've used only primary colors (red, yellow, and blue) plus black and white. Mondrian used these colors in most of his geometric paintings, with only occasional use of softer colors. But now you're the artist, and you can use different colors if you prefer. Why do you think Mondrian chose these intense colors? If you like, do some research to find out.
    Aren't the primary colors red, green, and blue?

    Color is complicated. When mixing different colors of light, as your computer display does, you use red, green, and blue. But when mixing paint colors, you use red, yellow, and blue as primary.

  2. Do a careful comparison of your program's paintings and Mondrian's. How faithful is this algorithm (dividing a rectangle, and dividing each piece recursively) to the way Mondrian used lines to divide his canvas? The random choice of color in each rectangle sometimes uses the same color in rectangles next to each other. Is that something you see in Mondrian's work? Think about how your program could be improved. (That is, for each problem you notice, what specific changes to the code would help?)

These geometric paintings came near the end of Mondrian's career. He started out painting realistic landscapes, and moved to greater and greater abstraction over time. If you want to learn more about the range of Mondrian's work, read the Wikipedia article.