Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/data/GSOC examples/Sierpinski - graphics
blob: f5d75ccf06c03fabf49339f9ce078b046349b27e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# This example draws what is called the Sierpinski triangle. 
# First, one black triangle is created. 
# After that it is removed and in its place three smaller black triangles are created, 
# which leaves a white hole (also shaped like a triangle, but upside down!) in the middle.
#
# This can continue for any number of steps - you can split the smaller
# triangles into even smaller ones and so on. 
# We have, however, limited it to 8 to keep our computers from freezing due to
# too much calculations! If you change it to a higher number, that will probably happen.
#
# This code is similar to the code in "Koch snowflake" example so you 
# could first go through that to understand this example better.

import pippy, pygame, sys
from pygame.locals import *
from math import sin, cos
from math import pi as Pi
import gtk

class Triangle(object):
    def __init__(self, first_vertex, length, displacement_angle = 0 ):
        # remember your first vertex
        self.A = first_vertex
        # calculate the other two
        self.B = self.A[0] + length * cos(Pi/3 + displacement_angle), \
                 self.A[1] - length * sin(Pi/3 + displacement_angle)
        self.C = self.A[0] + length * cos(displacement_angle), \
                 self.A[1] - length * sin(displacement_angle)
        # remember your length
        self.length = length
        # calculate the midpoints of each line
        # m1 for AB, m2 for BC, m3 for CA
        # m1 and m3 are calculated the same way as points B and C, but with
        # half the length.
        self.m1 = self.A[0] + length/2 * cos(Pi/3 + displacement_angle), \
                  self.A[1] - length/2 * sin(Pi/3 + displacement_angle)
        self.m3 = self.A[0] + length/2 * cos(displacement_angle), \
                  self.A[1] - length/2 * sin(displacement_angle)
        # m2 is 120 degrees (2*Pi/3) from C, half the length.
        # ... but we don't actually need it for anything.
        self.m2 = self.C[0] + length/2 * cos(2*Pi/3 + displacement_angle), \
                  self.C[1] - length/2 * sin(2*Pi/3 + displacement_angle)
        
    # create three new triangles from yourself.
    def split(self):
        new_triangles = []
        new_triangles.append(Triangle(self.A, self.length/2))
        new_triangles.append(Triangle(self.m1, self.length/2))
        new_triangles.append(Triangle(self.m3, self.length/2))
        return new_triangles

    # This is how a triangle draws itself.
    def draw(self, screen, color):
        points = [self.A, self.B, self.C]
        pygame.draw.polygon(screen, color, points)

# always need to init first thing before drawing
pygame.init()

# XO screen is 1200x900
size = width, height = gtk.gdk.screen_width(), gtk.gdk.screen_height()

# create the window and keep track of the surface
# for drawing into
screen = pygame.display.set_mode(size)

# The font we'll use to display the current depth.
font_size = 36
font = pygame.font.Font(None, font_size)

black = (0, 0, 0)
white = (255, 255, 255)

# Practice: Could you make this depend on the current resolution?
# (hint: variables "height" and "width" could help)
starting_point = (200, 750)
side_length = 800

t1 = Triangle(starting_point, side_length)

depth = 0

all_triangles = [t1]
new_triangles = []

recalculate = False

while pippy.pygame.next_frame():
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        # When R arrow is pressed, go one step further.
        # This means splitting the existing triangle(s) into new ones.
        # Note that all the triangles have to be recalculated before redrawn.
        elif event.type == KEYDOWN and event.key == K_RIGHT and depth < 8:
            depth += 1
            recalculate = True
        # When L arrow is pressed, go one step back, reducing the number of 
        # triangles.
        # Note that all the triangles have to be recalculated before redrawn.
        elif event.type == KEYDOWN and event.key == K_LEFT and depth > 0:
            depth -= 1
            recalculate = True
        elif event.type == KEYDOWN and event.key == K_q:
            sys.exit()    
    screen.fill(white)
    # Display the current step.
    msg = "Step: " + str(depth) + "/8"
    text = font.render(msg , True, black)
    text_box = text.get_rect()
    text_box.top = height / 10
    text_box.left = width / 20
    # Display the instructions
    text2 = font.render("Use left and right arrows.", True, black)
    text_box2 = text2.get_rect()
    text_box2.top = height / 10 - 30
    text_box2.left = width / 20
    # Write the instructions and the current step on the screen.
    screen.blit(text, text_box)
    screen.blit(text2, text_box2)
    
    # If the depth was changed (L or R pressed), recalculate everything so we can
    # draw the change.
    if recalculate == True:
        # Delete the existing triangles.
        all_triangles = [t1]    
        new_triangles = []
        # Keep splitting until the new value of "depth" variable is reached.    
        # (it can be one more (R key) or one less (L key) from the last value)
        for step in range(depth):
            for triangle in all_triangles:
                new_triangles += triangle.split()
            all_triangles = new_triangles
            new_triangles = []
    recalculate = False

    # Draw the triangle on the screen.
    for triangle in all_triangles:
        triangle.draw(screen, black)
    
    # Refresh the screen.
    pygame.display.flip()