# Drawing Repetitive Images in Elm

Elm, the programming language created by Evan Czaplicki, is a revolutionary tool for building web apps. But it has other uses as well. In this article, we show how it can be used to produce repetitive images like the one above, left. The idea is simple: start with a basic shape, in this case a pentagon, then repeatedly apply a transformation to the original to build up modified copies. Put the original and all the modified copies together to make the final image. (Code is at GitHub).

# Transforming Shapes

To implement this strategy, I used the Kwarrtz/render graphics package, which makes it easy to manipulate SVG images (Scalable Vector Graphics images). We begin by defining the notion of a `Point`

and an `AbstractShape`

:

type alias Point = (Float, Float)type alias AbstractShape =

{ points : List Point, angle : Float }

Thus a `Point`

is a pair of numbers *(x,y)*, just as in high school analytic geometry class. A polygon, naturally enough, is just a list of points, with an extra number to give its angle of inclination with respect to the *x*-axis. In this way, we can define

`diamond = AbstractShape [ ( 0,0 ), ( 1,0 ), (1,1), (0,1) ] 45`

We will define some operations on `AbstractShapes`

and then at the last moment render them into SVG images using Kwarrtz/render to get the *Nautilus* image above.

To begin, we need to be able to translate shapes — move them horizontally and vertically with code like this:

`square |> translate 5 3`

Here we “piped” the value `square`

into a function `translate 5 3`

, thereby moving our shape 5 units to the right and 3 units up. To translate shapes, we need to be able to add one point to another, e.g..

`addPoint (1,0) (0,1) == (1,1)`

The `addPoints`

functon can be defined like this:

`addPoints : Point -> Point -> Point`

addPoints a b =

( Tuple.first a + Tuple.first b, Tuple.second a + Tuple.second b )

Now it is easy to define `translate`

:

translate : Float -> Float -> AbstractShape -> AbstractShape

translate tx ty s =

let

points =

s.points newPoints =

List.map (addPoints ( tx, ty )) points

in

AbstractShape newPoints s.angle

Thus `translate`

is a function which takes two numbers and an `AbstractShape`

as arguments, returning an `AbstractShape`

, while `translate 5 3`

is a function taking an `AbstractShape`

as argument and returning an `AbstractShape`

. Here we use the fact that in Elm, we can apply a function of *n* arguments to the first *k* arguments, obtaining a function of *n-k* arguments as result. This is *partial application*, aka *currying*. It makes life easier.

In a similar manner, we define functions to scale and rotate `AbstractShapes`

.

# Repeating Shapes

Now comes the fun part: repeatedly transforming the shapes and building up the composite image. This operation is an example of what mathematicians call an *orbit of a map.* Let *f* be a function and let *a* be a gizmo — a number, a shape, whatever. An orbit of *a* under* f* is an *n*-element list like *[a, f(a), f(f(a)), f(f(f(a)), … ]*.* *With an expressive language like Elm or Haskell (for example), it is easy to define a function `orbit f n a`

that does just this. See the code on GitHub. For a simple example, we can calculate a list of powers of two like this:

`orbit (\x -> 2*x) 5 1`

[1,2,4,8,16,32] : List number

Here `\x -> 2*x`

is the (anonymous) function that multiplies its argument by 2.

With the `orbit`

function, it is easy to create a list of shapes. First, we create a base shape, like `diamond`

. In the *Nautilus* figure, we used a pentagon. Then we apply `orbit`

to the base shape using the transformation `((rotate -10) >> (scale 0.95 0.95))`

. That is, we rotate counterclockwise by 10 degrees, then shrink the shape by a factor of 0.95 in both the *x* and *y* directions. The orbit: it has 80 transformed copies.

`shapes = orbit ((rotate -10) >> (scale 0.95 0.95)) 80 pentagon `

|> List.map (translate 300 300)

|> List.map render

In the code above,`f>>g`

is the composition of the functions `f`

and `g`

. As an example, let `f x = x + 1`

and let `g x = 2*x`

. Then `(f>>g) 1 == 4`

. First, we applied `f`

to `1`

, obtaining `2`

. Then we applied `g`

to the result, obtaining `4`

. **Pop Quiz:** what is `(g>>f) 1`

?

After computing the orbit, we “pipe” the result into the `translate 300 300`

function so that the image is not squished into the upper left corner of the screen at position (0,0). Finally, we pipe it into a `render`

function. See the code in the Nautilus GitHub repository. It is here that we use the Kwarrtz/render package to turn a list of `AbstractShapes`

into a list of SVG images.

The last step is to put the resulting list of SVG images into a single SVG image and display it:

`main = group shapes |> svg 0 0 500 500`

Here `group`

is function in `Kwarrtx/render`

.

# Conclusion

One of the beautiful/powerful aspects of Elm is the ease with which one can turn ideas into code. In the discussion above, we saw this in the definition of `Point`

and `AbstractShape`

, then in the functions that transform `AbstractShapes`

. This is a general feature of Elm, not something confined to graphics programming.