Random Snowflake Generator

Svetlana Eden

2017-12-07

If you are tired of the point types available in R base graphics and want to break your report routine, you can use the package snowflakes. The package contains one function that plots random snowflakes that can be used instead of points. The snowflakes have some useful properties. Just like points in R base graphics, the snowflakes are round, no matter what aspect ratio you are using. Another nice property is that the snowflakes are scaleable: if you increase the size of the snowflake, its crystal width will increase accordingly. Most importantly, there is an infinite number of snowflake patterns that you can choose from. Each pattern is uniquely determined by a random seed. Snowflakes can be plotted using different sizes, widths, angles, and of course, colors. The following examples demonstrate how to create all kinds of realistic looking snowflakes.

Getting started. Using random seed.

library('snowflakes')

First, let’s create a simple plot. Suppose we need to plot a quadratic function, \(Y = (X-1)^2\). Instead of points, we use snowflakes plotted in a transparent gray color. Transparent colors make snowflakes look more like crystals.

xCoor = seq(0, 2, .25)
yCoor = (xCoor-1)^2
radius = 0.1
set.seed(1)
par(mar = c(0, 0, 0, 0))
plot(xCoor, yCoor, type="l", axes = FALSE, ylab="", xlab="", ylim = range(yCoor) + radius*c(-1, 1)*0.7, xlim = range(xCoor) + radius*c(-1, 1)*0.7, col=gray(.9))
snowflakes(xCoor = xCoor, yCoor = yCoor, radius = radius, color = "#22222222")
## [1] 24 34 51 80 18 77 87 55 52
Quadratic function plotted using snowflakes (in transparent gray) instead of points.
Quadratic function plotted using snowflakes (in transparent gray) instead of points.

Note that in the above plot, every snowflake is unique. The pattern of each snowflake is defined by a random seed. The function also returns the seeds it used for generating the snowflakes in case you want to reproduce them later.

Exploring the arguments

The next example demonstrates the use of argument deltaCoef. It defines the width of the snowflake’s crystal.

xCoor = seq(0, 1, .25)
yCoor = xCoor
radius = 0.15
set.seed(1)
par(mar = c(0, 0, 0, 0))
plot(xCoor, yCoor, type="l", axes = FALSE, ylab="", xlab="",
ylim = range(yCoor) + radius*c(-1, 1)*0.7,
xlim = range(xCoor) + radius*c(-1, 1)*0.7, col=gray(.9))
returnedSeeds = snowflakes(xCoor = xCoor, yCoor = yCoor, radius = radius, seeds = c(9492), deltaCoef = 15 - (0:(length(xCoor)-1))*3, color = "#22222222")
Same snowflake pattern, but different crystal widths.
Same snowflake pattern, but different crystal widths.

Here is another example. In the plot below, we only use three snowflake patterns with seeds 1, 2, and 3. We also vary the orientation and the color of the snowflakes. In order to define the colors we use arguments color and anotherColor. Argument color changes and argument anotherColor stays the same in order to create an interesting effect. Also in this example, we modified the aspect ratio argument of function plot, but the snowflakes are still round. Note that each snowflake is facing the center of the spiral because of the way we chose argument orientation. You can see, however, that the orientation is not exact. This happens because of the way the aspect ratio correction of the snowflakes was implemented. In order for orientation to be exact the aspect ratio of the plot should be 1:1.

t = seq(0, 5*pi, .5)
xCoor = t*cos(t)
yCoor = t*sin(t)
radius = seq(.6, 1.8, 1.2/(length(t)-1))
orientation = -(pi + t)
set.seed(1)
par(mar = c(0, 0, 0, 0))
plot(xCoor, yCoor, type="l", axes = FALSE, ylab="", xlab="",
ylim = range(yCoor) + max(radius)*c(-1, 1)*0.5,
xlim = range(xCoor) + max(radius)*c(-1, 1)*0.5, col=gray(.9), asp = 2/3)
segments(x0 = rep(0, length(xCoor)), y0 = rep(0, length(xCoor)), x1 = xCoor, y1 = yCoor, col = gray((1:length(xCoor))/(length(xCoor)+1)), lty = 3)
returnedSeeds = snowflakes(xCoor = xCoor, yCoor = yCoor, radius = radius, orientation = orientation, seeds = 1:3, color = gray((1:length(xCoor))/(length(xCoor)+1)), anotherColor = "gray")
Snowflake spiral with each snowflake oriented toward the center of the spiral (well, almost).
Snowflake spiral with each snowflake oriented toward the center of the spiral (well, almost).

Note that in the example above, we used opaque gray colors. If we used transparent colors instead, the snowflakes would look more interesting, which is demonstrated by the next example.

Cool looking snowflakes.

Here, we take the snowflake generator to a higher artistic level :). We first write a function that plots snowflakes using layers of transparent colors.

fancySnowflakes = function(xCoor, yCoor, radius, seeds, orientation = pi/6){
colorCoord = as.hexmode(col2rgb("blue"))
transpBlue =paste("#", paste(colorCoord, collapse=""), "44", sep="")
colorCoord = as.hexmode(col2rgb("white"))
transpWhite =paste("#", paste(colorCoord, collapse=""), "66", sep="")
for (i in 1:length(xCoor)){
snowflakes(xCoor = xCoor[i], yCoor = yCoor[i], radius = radius, color = transpBlue, anotherColor = "#33333333", seeds = seeds[i])
snowflakes(xCoor = xCoor[i], yCoor = yCoor[i], radius = radius, color = transpWhite, anotherColor = transpWhite, seeds = seeds[i])
}
}

Now let’s plot some cool snowflakes. We also print each snowflake’s seed.

numSnowflPerRow = 5
set.seed(2018)
selectSeeds = sample(1:100000, numSnowflPerRow^2)
xCoor = rep(1:numSnowflPerRow, numSnowflPerRow)
yCoor = rep(1:numSnowflPerRow, each = numSnowflPerRow)
radius = .4
par(mar = c(0, 0, 0, 0))
plot(range(xCoor)+c(-1, 1)*.5, range(yCoor)+c(-1, 1)*.5, type="n", axes = FALSE, ylab="", xlab="")
selectSeeds = c(90068, 46258, 41165, 66142, 4636, 37906, 17295, 9250, 30595, 74555, 12669, 62970, 96997, 43447, 81975, 23841, 73197, 8419, 14318, 83885, 29343, 47445, 66721, 29854, 77912)
fancySnowflakes(xCoor = xCoor, yCoor = yCoor, radius = radius, seeds = selectSeeds)
text(xCoor, yCoor, selectSeeds, cex=.5, pos = 3)
Cool looking snowflakes.
Cool looking snowflakes.

There are many other ways to play with snowflakes. For example, they can be generated using a transparent white color and displayed on a dark background. They can also be saved in an svg format and used as static or animated images, see the front page of my website (which is still under construction) as an example.

I hope that using this package will brighten up your day!