2. Geometric patterns

VCMNA254: level 7: Design and implement mathematical algorithms using a simple general purpose programming language
  • constructing geometric patterns such as a honeycomb, using dynamic geometry functionality


2.1. Turtle basics

The python turtle module can be used to generate patterns of shapes.

2.2. Tessellation (tiling)

A tessellation is a repeated pattern in the plane or on a surface where shapes completely fill all the space around a given point where their boundaries meet.
For example, a honeycomb is a tessellation using hexagons.
Tiling patterns are tessellations using rectangular tiles or brick pavers in paths, mosaics in buildings, quilts and art.
A regular tessellation is created by tessellating regular polygons.
If more than one regular polygon is used, it is a semi-regular tessellation.

2.3. Square patterns

A grid of squares
../_images/squares.png
Squares rotated 45 degrees.
../_images/squares_at_45.png

Python code for both examples, where the initial angle can be set to 0 or 45 degrees.
 1import turtle
 2
 3
 4def square(t, length=50, start_pos=(0, 0), start_h=0, penw=1, penc="black", fillc=None):
 5    """Draw a square given side length, turning clockwise.
 6
 7    Args:
 8        t (class turtle.Turtle): turtle instance.
 9        length (int, optional): side length. Defaults to 50.
10        start_pos (tuple, optional): start position. Defaults to (0, 0).
11        start_h (int, optional): initial heading. Defaults to 0.
12        penw (int, optional): pensize. Defaults to 1.
13        penc (str, optional): pencolor. Defaults to "black".
14        fillc (str, optional): fillcolor. Defaults to None.
15
16    """
17    t.pu()
18    t.goto(start_pos)
19    t.pd()
20    t.seth(start_h)
21
22    t.pensize(penw)
23    t.pencolor(penc)
24
25    if fillc is not None:
26        t.fillcolor(fillc)
27        t.begin_fill()
28
29    for _ in range(4):
30        t.fd(length)
31        t.rt(90)
32
33    if fillc is not None:
34        t.end_fill()
35        
36
37def tes_square(t, screen_width, screen_height, side_length, start_h=0):
38    xrep = screen_width // side_length
39    yrep = screen_height // side_length
40    for i in range(yrep):
41        for j in range(xrep):
42            start_pos = (-screen_width//2 + (j * side_length), screen_height//2 - (i * side_length))
43            square(t, length=side_length, start_pos=start_pos, start_h=start_h)
44
45
46def main():
47    SCREEN_WIDTH = 810
48    SCREEN_HEIGHT = 610
49    SIDE_LENGTH = 50
50    START_H = 0
51
52
53    # Set up the turtle screen
54    s = turtle.Screen()
55    s.bgcolor("white")
56    s.title("draw_quares")
57    s.setup(width=SCREEN_WIDTH, height=SCREEN_HEIGHT, startx=0, starty=0)
58    s.tracer(0, 0)
59
60    # Create a turtle object
61    t = turtle.Turtle()
62    t.speed(0) # Set the turtle's speed to the fastest
63    t.ht()
64
65    tes_square(t, screen_width=SCREEN_WIDTH, screen_height=SCREEN_HEIGHT, side_length=SIDE_LENGTH, start_h=START_H)
66
67    s.update()
68    s.exitonclick()
69
70
71if __name__ == "__main__":
72    main()

2.4. Hexagon patterns

Aligned touching hexagons creating diamond gaps.
../_images/hexagon_diamonds.png

Python code:
 1import turtle
 2
 3
 4def hexagon(t, length=50, start_pos=(0, 0), start_h=60, penw=1, penc="black", fillc=None):
 5    """Draw a square given side length, from centre left at 60 degrees, turning clockwise.
 6
 7    Args:
 8        t (class turtle.Turtle): turtle instance.
 9        length (int, optional): side length. Defaults to 50.
10        start_pos (tuple, optional): start position. Defaults to (0, 0).
11        start_h (int, optional): initial heading. Defaults to 0.
12        penw (int, optional): pensize. Defaults to 1.
13        penc (str, optional): pencolor. Defaults to "black".
14        fillc (str, optional): fillcolor. Defaults to None.
15
16    """
17    t.pu()
18    t.goto(start_pos)
19    t.pd()
20    t.seth(start_h)
21
22    t.pensize(penw)
23    t.pencolor(penc)
24
25    if fillc is not None:
26        t.fillcolor(fillc)
27        t.begin_fill()
28
29    for _ in range(6):
30        t.fd(length)
31        t.rt(60)
32
33    if fillc is not None:
34        t.end_fill()
35        
36
37def tes_hexagon(t, screen_width, screen_height, side_length, start_h=0):
38    slsqr3 = side_length * (3 ** 0.5)
39    xrep = int(screen_width / side_length)
40    yrep = int(screen_height / slsqr3) + 1
41    print(yrep)
42    for i in range(yrep):
43        for j in range(xrep):
44            start_pos = (-screen_width//2 + (j * 2 * side_length), screen_height//2 - (i * slsqr3))
45            hexagon(t, length=side_length, start_pos=start_pos, start_h=start_h)
46
47
48def main():
49    SCREEN_WIDTH = 810
50    SCREEN_HEIGHT = 610
51    SIDE_LENGTH = 50
52    START_H = 60
53
54
55    # Set up the turtle screen
56    s = turtle.Screen()
57    s.bgcolor("white")
58    s.title("hexagons and diamonds")
59    s.setup(width=SCREEN_WIDTH, height=SCREEN_HEIGHT, startx=0, starty=0)
60    s.tracer(0, 0)
61
62    # Create a turtle object
63    t = turtle.Turtle()
64    t.speed(0) # Set the turtle's speed to the fastest
65    t.ht()
66
67    tes_hexagon(t, screen_width=SCREEN_WIDTH, screen_height=SCREEN_HEIGHT, side_length=SIDE_LENGTH, start_h=START_H)
68
69    s.update()
70    s.exitonclick()
71
72
73if __name__ == "__main__":
74    main()

Staggered hexagons creating a tessalation with no overlap.
../_images/hexagon_tessalation.png

Python code:
 1import turtle
 2
 3
 4def hexagon(t, length=50, start_pos=(0, 0), start_h=60, penw=1, penc="black", fillc=None):
 5    """Draw a square given side length, from centre left at 60 degrees, turning clockwise.
 6
 7    Args:
 8        t (class turtle.Turtle): turtle instance.
 9        length (int, optional): side length. Defaults to 50.
10        start_pos (tuple, optional): start position. Defaults to (0, 0).
11        start_h (int, optional): initial heading. Defaults to 0.
12        penw (int, optional): pensize. Defaults to 1.
13        penc (str, optional): pencolor. Defaults to "black".
14        fillc (str, optional): fillcolor. Defaults to None.
15
16    """
17    t.pu()
18    t.goto(start_pos)
19    t.pd()
20    t.seth(start_h)
21
22    t.pensize(penw)
23    t.pencolor(penc)
24
25    if fillc is not None:
26        t.fillcolor(fillc)
27        t.begin_fill()
28
29    for _ in range(6):
30        t.fd(length)
31        t.rt(60)
32
33    if fillc is not None:
34        t.end_fill()
35        
36
37def tes_hexagon(t, screen_width, screen_height, side_length, start_h=0):
38    slsqr3 = side_length * (3 ** 0.5) * 0.5
39    xrep = int(screen_width / side_length)
40    yrep = int(screen_height / slsqr3)
41    print(yrep)
42    for i in range(yrep):
43        for j in range(xrep):
44            if (i % 2) == 0:
45                start_pos = (-screen_width//2 + (j * 3 * side_length), screen_height//2 - slsqr3 - (i * slsqr3))
46            else:
47                start_pos = (-screen_width//2 + (j * 3 * side_length) + (1.5 * side_length), screen_height//2 - slsqr3 - (i * slsqr3))
48            hexagon(t, length=side_length, start_pos=start_pos, start_h=start_h)
49
50
51def main():
52    SCREEN_WIDTH = 810
53    SCREEN_HEIGHT = 610
54    SIDE_LENGTH = 50
55    START_H = 60
56
57
58    # Set up the turtle screen
59    s = turtle.Screen()
60    s.bgcolor("white")
61    s.title("hexagons")
62    s.setup(width=SCREEN_WIDTH, height=SCREEN_HEIGHT, startx=0, starty=0)
63    s.tracer(0, 0)
64
65    # Create a turtle object
66    t = turtle.Turtle()
67    t.speed(0) # Set the turtle's speed to the fastest
68    t.ht()
69
70    tes_hexagon(t, screen_width=SCREEN_WIDTH, screen_height=SCREEN_HEIGHT, side_length=SIDE_LENGTH, start_h=START_H)
71
72    s.update()
73    s.exitonclick()
74
75
76if __name__ == "__main__":
77    main()

Overlapping hexagons. The overlap_factor can be varied from 0.5 for tiangles to 1.0 for hexagons with triangular gaps.

hexagons_overlap_50

hexagons_overlap_50

hexagons_overlap_67

hexagons_overlap_67

hexagons_overlap_75

hexagons_overlap_75

hexagons_overlap_100

hexagons_overlap_100

Python code:
 1import turtle
 2
 3
 4def draw_hexagon(t, x, y, side_length, start_h=0):
 5    t.penup()
 6    t.goto(x,y)
 7    t.seth(start_h)
 8    t.pendown()
 9    for i in range(6):
10        t.forward(side_length)
11        t.right(60)
12
13def hexagonal_overlap(t, swidth, sheight, side_length, overlap_factor=0.75):
14    vert_overlap_factor = overlap_factor
15    hor_overlap_factor = overlap_factor * 2
16    side_height = side_length * 3**0.5
17    rows = int(sheight / (side_height * vert_overlap_factor))+2
18    cols = int(swidth / (side_length * vert_overlap_factor))+1
19    for i in range(rows):
20        y = sheight//2 + (1-i) * side_height * vert_overlap_factor
21        for j in range(cols):
22            x = -swidth//2  + (j-1) * side_length * hor_overlap_factor
23            if i % 2 == 1:
24                x += side_length * vert_overlap_factor
25            draw_hexagon(t, x, y, side_length)
26
27
28
29s = turtle.Screen()
30s.bgcolor("white")
31s.title("draw_centered_regular_polygon")
32s.setup(width=800, height=600, startx=None, starty=None)
33s.tracer(0, 0)
34
35t = turtle.Turtle()
36t.speed(0)
37t.ht()
38
39hexagonal_overlap(t, 800, 600, 50, overlap_factor=0.67)
40
41s.update()
42s.exitonclick()