Christmas decorations, starry nights, and randomness

Christmas decorations, starry nights, and randomness#

A simple uniform starry sky. A  starry sky with randomly placed stars.

Which one of the starry skies above looks the most “natural”? When we create art with programming, it is easy to end up with very ordered and perfect-looking images. This can lead to gorgeous patterns, but nature is not perfectly ordered, so it can also look slightly “artificial”. A trick to include a little bit of nature’s “not quite perfect”-ness into our art is to use randomness. Adding randomness is a technique that is commonly found in art, game design, animation and music.

../_images/10print.svg

Art#

Generative art, variation of 10print

../_images/600px-Tiling_procedural_textures.jpg

Procedurally generated textures for game design#

Illustration of procedurally generated textures (illustrasjon by Drummyfish)

../_images/Terragen.jpg

Procedural landscape#

Procedurally generated landscape (illustration by Levyznin)

../_images/5612345200_a45d40bccb_c.jpg

Music#

Photograph of a modular synthesizer. These instruments can often play sequences of sounds in random order. (Image by Muff on Flickr (CC-BY 2.0))

Randomness with Python#

Below we se an example of the type of embroidery we will make in this tutorial.

An image of a random embroidered starscape.

Let’s start by looking at how to generate random numbers in Python. Below is some code to print a random number to the terminal.

1import random
2
3random_number = random.randint(1, 6)
4print(random_number)
5
Line 1:

Imports the random library, which we can use to draw random numbers.

Line 3:

Uses the random.randint-function to draw a random number between 1 and 6 (including endpoints) and stores this random number in the random_number variable.

Try it yourself

  • Run the code several times. Do you get a different number?

  • Modify the code so that it instead prints a random number between 50 and 100

  • Run the code several times again. Do you get different numbers now compared to before?

We can use this to make our embroidery patterns more interesting. The code below embroiders a simple star:

 1from turtlethread import Turtle
 2
 3needle = Turtle()
 4with needle.running_stitch(25):
 5    for ray in range(6):
 6        ray_length = 100
 7        needle.forward(ray_length)
 8        needle.backward(ray_length)
 9        needle.right(60)
10
11needle.visualise()
Result from the code above. A simple star with six rays.

To make this star look a little more “natural” and interesting, we can apply randomness to the length of the rays.

 1import random
 2from turtlethread import Turtle
 3
 4needle = Turtle()
 5with needle.running_stitch(25):
 6    for ray in range(6):
 7        ray_length = random.uniform(80, 120)
 8        needle.forward(ray_length)
 9        needle.backward(ray_length)
10        needle.right(60)
11
12needle.visualise()
Result from the code above. A simple star with six rays with slightly varying length.
Line 7:

draws a random number between 80 and 120 and stores it in the ray_length variable.

We can see that the star now looks a little more random and, therefore, a little more natural.

Try it yourself:

  • Modify the code, so the ray length is between 25 and 125 instead of 80 and 120. How does the look of the star change?

  • Modify the code, so the number of rays in the star is also random. (HINT: the angle between each ray must be 360 / number_of_rays)

Click here to see an example of how the finished code should look:
 1import random
 2from turtlethread import Turtle
 3
 4needle = Turtle()
 5with needle.running_stitch(25):
 6    number_of_rays = random.randint(3, 10)
 7    for ray in range(number_of_rays):
 8        ray_length = random.uniform(25, 125)
 9        needle.forward(ray_length)
10        needle.backward(ray_length)
11        needle.right(360 / number_of_rays)
12
13needle.visualise()
Result from the code above. A simple star with a random number of rays and random length on each ray.

Attention

Make sure your code matches the finished code above before you proceed.

So, we have created one random star, but we can kick it up a notch by drawing multiple stars randomly placed in the sky. We can, for example, use the goto command and let the needle move to a random position on the fabric for each star. The code below draws a starry sky with four random stars randomly placed in the sky.

 1import random
 2from turtlethread import Turtle
 3
 4needle = Turtle()
 5with needle.running_stitch(25):
 6    number_of_stars = 4
 7    for star in range(number_of_stars):
 8        x = random.randint(-250, 250)
 9        y = random.randint(-250, 250)
10        needle.goto(x, y)
11
12        number_of_rays = random.randint(3, 10)
13        for ray in range(number_of_rays):
14            ray_length = random.randint(25, 100)
15            needle.forward(ray_length)
16            needle.backward(ray_length)
17            needle.right(360 / number_of_rays)
18
19needle.visualise()
Result from the code above. Four stars randomly placed. Each star has a random number of rays, each with a random length. There is a seam between each star.
Line 6:

Defines a number_of_stars variable that decides how many stars we want to draw

Line 7:

Starts the loop we will use to draw multiple stars

Lines 8-9:

Draws random coordinates between -250 and 250 for each star

Line 10:

Moves the needle to a random position before drawing a star

This is a beautiful, random starry sky! But now we also embroider a line between each star, which gives a cool effect that can look like constellations. However, if we don’t want these lines, we can use jump stitches to tell the needle to move without stitches between each star.

 1import random
 2from turtlethread import Turtle
 3
 4needle = Turtle()
 5
 6number_of_stars = 4
 7for stjerne in range(number_of_stars):
 8    x = random.randint(-250, 250)
 9    y = random.randint(-250, 250)
10    with needle.jump_stitch():
11        needle.goto(x, y)
12
13    with needle.running_stitch(25):
14        number_of_rays = random.randint(3, 10)
15        for ray in range(number_of_rays):
16            ray_length = random.randint(25, 100)
17            needle.forward(ray_length)
18            needle.backward(ray_length)
19            needle.right(360 / number_of_rays)
20
21needle.visualise()
Result from the code above. Four stars randomly placed. Each star has a random number of rays, each with a random length. There is a seam between each star. The stars are now connected with a red line that symbolises that the needle should "jump over" this stretch. There is also a black cross in the start of each red line that symbolises that the thread should be cut and a red circle at the end that symbolises the end of a jump stitch.
Lines 6-7:

The loop that iterates over the stars is moved outside the code block that defines stitch type. We move the loop to allow for different stitch types when embroidering a star and moving the needle between stars.

Line 10:

Instructs the needle to move without creating any stitches. If the embroidery machine supports it, the thread will be cut (if some stitches have already been embroidered so far).

Line 13:

Starts the code block where we embroider each star with a running stitch.

Try it yourself:

Modify the code to create a random number of stars.

Click here to see an example of how the finished code should look:
 1import random
 2from turtlethread import Turtle
 3
 4needle = Turtle()
 5
 6number_of_stars = random.randint(1, 10)
 7for star in range(number_of_stars):
 8    x = random.randint(-250, 250)
 9    y = random.randint(-250, 250)
10    with needle.jump_stitch():
11        needle.goto(x, y)
12
13    with needle.running_stitch(25):
14        number_of_rays = random.randint(3, 10)
15        for ray in range(number_of_rays):
16            ray_length = random.randint(25, 100)
17            needle.forward(ray_length)
18            needle.backward(ray_length)
19            needle.right(360 / number_of_rays)
20
21needle.visualise()
Result from the code above. A random number of stars randomly placed. Each star has a random number of rays, each with a random length. There is a seam between each star. The stars are now connected with a red line that symbolises that the needle should "jump over" this stretch. There is also a black cross in the start of each red line that symbolises that the thread should be cut and a red circle at the end that symbolises the end of a jump stitch.
An image of the embroidery machine while it embroiders a random starscape.

Attention

For this example, we use the randint function from the random library. This function draws random numbers that can include the endpoints. However, if we use the randint function from numpy.random or pylab, we would omit the second endpoints. For example, random.randint(1, 6) draws one of these numbers: 1, 2, 3, 4, 5 or 6, while numpy.random.randint(1, 6) and pylab.randint(1, 6) draws one of these numbers: 1, 2, 3, 4 or 5.

Try it yourself:

  • Create your own embroidery pattern that uses randomness. Below is a gallery of that you can take inspiration from.

Example patterns with randomness#

Example 1

A sort of spiral where each line has a random but increasing length.

Example 2

Randomly placed circles with a line connecting them.

Example 3

A snow flake with arms that have random length and a random number of branches

Example 4

A christmas tree where the length and angle of the branches have some randomness.