Sunday, November 3, 2013

Simulating Abstract Art with R

Piet Mondrian Composition with Red, Blue, Black, Yellow, and Gray (1921):

An example draw from my simulation function:

We're in the midst of planning our spring course on Empirical Research Methods, and as a result, I've found myself spending a lot of time thinking about some of the fist ideas in statistics – For example, that the data we observe are actually draws from some (usually unobserved) generating function.

On a recent museum triup, I started thinking about how we could apply this idea to abstract art. Here, I thought, we could think of a particular painting as a single manifestation of some set of generating rules.

Piet Mondrian has a ton of work in a style I thought would be interesting to explore – his work involves combinations of a small number of lines and filled rectangles.

In order to experiment, I decided to write a function which would simulate the (1921) Composition with Red, Blue, Black, Yellow, and Gray (1921) featured above.

My first idea was to maintain the same set lines and colors, while varying (slightly) the locations and widths of those lines – we can think of these locations as parameters drawn from specified distributions. To start, I only use uniform distributions, with means near the values in the original.

For the color, I found a site that extracts hexadecimal colors, which R recognizes.

The result, I think, is interesting. While the variation is still quite constrained, this lets us examine the abstract art.. abstractly (ha!)

Here are a few more draws from the function:

Here is the code for the simulation – (it's a bit of a mess). Feel free to download, experiment with, and improve it!

sim.func = function() {

    # pick a place (near the middle) for central anchor line:
    left.anchor = runif(1, 40, 60)

    width = runif(1, 2, 3)

    right.anchor = left.anchor + width

    # plot:
    plot(0, 0, type = "n", xlim = c(0, 100), ylim = c(0, 10), xaxt = "n", yaxt = "n", 
        ann = FALSE)

    polygon(c(left.anchor, left.anchor, right.anchor, right.anchor), c(-1, 11, 
        11, -1), col = "#1c1b23")

    upper.left = runif(1, 7, 9)
    lower.left = runif(1, 2, 5)

    small.line.height = runif(1, 0.1, 0.2)

    polygon(c(-100, -100, left.anchor, left.anchor), c(lower.left, lower.left + 
        small.line.height, lower.left + small.line.height, lower.left), col = "#1c1b23")

    polygon(c(-100, -100, left.anchor, left.anchor), c(upper.left, upper.left + 
        small.line.height, upper.left + small.line.height, upper.left), col = "#1c1b23")

    polygon(c(-10, -10, left.anchor, left.anchor), c(upper.left + small.line.height, 
        12, 12, upper.left + small.line.height), col = "#cbccd4")

    polygon(c(-10, -10, left.anchor, left.anchor), c(-1, lower.left, lower.left, 
        -1), col = "#cbccd4")



    upper.right = runif(1, 7, 9)

    polygon(c(left.anchor, left.anchor, 200, 200), c(upper.right, upper.right + 
        small.line.height, upper.right + small.line.height, upper.right), col = "#1c1b23")

    polygon(c(left.anchor + width, left.anchor + width, 200, 200), c(upper.right + 
        small.line.height, 20, 20, upper.right + small.line.height), col = "#db5b2c")

    polygon(c(-10, -10, left.anchor, left.anchor), c(lower.left + small.line.height, 
        upper.left, upper.left, lower.left + small.line.height), col = "#273f70")

    lowest.left = runif(1, 0.1, 1.2)

    polygon(c(-100, -100, left.anchor, left.anchor), c(lowest.left, lowest.left + 
        small.line.height, lowest.left + small.line.height, lowest.left), col = "#1c1b23")

    lh.ref = runif(1, 5, 20)

    polygon(c(lh.ref, lh.ref, lh.ref + width, lh.ref + width), c(lowest.left, 
        upper.left, upper.left, lowest.left), col = "#1c1b23")


    lh.mid = lower.left + runif(1, 0.1, 0.4) * (upper.left - lower.left)

    polygon(c(lh.ref, lh.ref, 200, 200), c(lh.mid, lh.mid + small.line.height, 
        lh.mid + small.line.height, lh.mid), col = "#1c1b23")


    lowest.right = runif(1, 0.1, 1.6)

    polygon(c(left.anchor + width, left.anchor + width, 105, 105), c(lowest.right, 
        lowest.right + small.line.height, lowest.right + small.line.height, 
        lowest.right), col = "#1c1b23")

    rh.ref = runif(1, 75, 90)

    polygon(c(left.anchor + width, left.anchor + width, rh.ref, rh.ref), c(-1, 
        lowest.right, lowest.right, -1), col = "#1c1b23")

    polygon(c(rh.ref, rh.ref, 200, 200), c(-1, lowest.right, lowest.right, -1), 
        col = "#dccd1e")

    polygon(c(right.anchor, right.anchor, 200, 200), c(lowest.right + small.line.height, 
        lh.mid, lh.mid, lowest.right + small.line.height), col = colors()[358])

    polygon(c(right.anchor, right.anchor, 200, 200), c(lh.mid + small.line.height, 
        upper.right, upper.right, lh.mid + small.line.height), col = "#cbccd4")

    top.left = runif(1, 0.1, 0.3) * (10 - upper.left) + upper.left + small.line.height

    polygon(c(-100, -100, left.anchor, left.anchor), c(top.left, top.left + 
        small.line.height, top.left + small.line.height, top.left), col = "#1c1b23")

    polygon(c(-100, -100, left.anchor, left.anchor), c(upper.left + small.line.height, 
        top.left, top.left, upper.left + small.line.height), col = colors()[358])

}

No comments:

Post a Comment