Sierpinski Triangle

Avi Gupta
hackerLog
Published in
4 min readOct 21, 2018

“I’m not crazy about reality, but it’s the only place to get a decent meal.”
— Groucho Marx

What is the Sierpinski triangle, also called the Sierpinski gasket?

The Sierpinski triangle after 10 iterations.

A Sierpinski triangle takes a triangle, divides it into quarters, removes the central quarter, and does the same for the remaining triangles. We end up with the fractal shown up above. For example, if you were to count the amount of upright triangles in a row, each row would have an amount of upright triangles that would be a certain power of 2. Also, the total number of upright triangles in the entire Sierpinski triangle will be 3^n , or 3 to the power of the amount of iterations (shown here as ‘n’). In the triangle up above, the amount of iterations are 10, so the number of upright triangles is 3¹⁰. Here’s the pattern of the number of upright triangles:

0 iterations: 1 tri

1 iter: 3 tris

2 iter: 9 tris

3 iter: 27 tris

4 iter: 81 tris

5 iter: 243 tris

6 iter: 729 tris

10 iter: 59049 tris (WHAT?!)

n iter: 3^n tris

One way to produce a fractal is to repeat the same function over and over again at different scales with relative placements. What we did is that we made 3 triangles over and over again, making them smaller each time by one half and placed them in the corner of the current triangle being “fractalized.”

Fractals have a property called “scale invariance.” That means that the fractal pattern will stay the same even if you change the zoom level. The Sierpinski triangle is a fractal in which you can zoom into it infinitely, and you will still get the same pattern of triangles. All fractals are like that. (See definition of a fractal here.)

This is what we did to make the Sierpinski triangle: we made objects called Point and Triangle. For explanations, see the comments below in the code.

class Point {  
float x, y;
Point (float x, float y) {
// makes the coordinates for the point
this.x = x;
this.y = y;
}
}
class Triangle {
Point[] vertices = new Point[3];
Triangle(Point p1, Point p2, Point p3) {
// makes the vertices for the triangle
vertices[0] = p1;
vertices[1] = p2;
vertices[2] = p3;
}
void draw() {
line(vertices[0].x, vertices[0].y, vertices[1].x, vertices[1].y);
line(vertices[2].x, vertices[2].y, vertices[1].x, vertices[1].y);
line(vertices[0].x, vertices[0].y, vertices[2].x, vertices[2].y);
// creates the lines for the triangle by manipulating the x and y coordinates from the vertices
}
}

(They are uppercase because an object or class is uppercase in code.) Each Point consisted of a set of x-y coordinates, and each Triangle consisted of an array of 3 lines.

In each iteration, we made 3 upright “Child” Triangles in the corners of the “Parent” Triangle so that the upright triangles would be operated on instead of the one downright triangle. Each Child Triangle was in the corner of the Parent triangle and each Child Triangle was scaled to half of the size of the Parent triangle. We did this by taking the x-y coordinates of each of the Parent Triangle’s vertices. We then took half of the X and Y of each pair of vertices, and made 3 new Child Triangles by using the vertices of the Parent Triangles along by making new Points using the center of the X and Y coordinates.

Triangle[] findChildren(Triangle s){  
Triangle[] c = {}; // specifies an array of triangles.
float x1 = s.vertices[0].x;
float y1 = s.vertices[0].y;
float x2 = s.vertices[1].x;
float y2 = s.vertices[1].y;
float x3 = s.vertices[2].x;
float y3 = s.vertices[2].y;
//calculates the x and y of each point on the triangle.
float xc1 = (x1 + x2) / 2.0;
float yc1 = (y1 + y2) /2.0;
float xc2 = (x2 + x3) /2.0;
float yc2 = (y2 + y3) /2.0;
float xc3 = (x3 + x1)/2.0;
float yc3 = (y3 + y1)/2.0;
//calculates the center of the X and Y of each pair of vertices.
c = (Triangle[])append(c,new Triangle(new Point (x1, y1), new Point (xc1, yc1), new Point(xc3, yc3)));
c = (Triangle[])append(c,new Triangle(new Point (xc1, yc1), new Point (x2, y2), new Point(xc2, yc2)));
c = (Triangle[])append(c,new Triangle(new Point (xc3, yc3), new Point (xc2, yc2), new Point(x3, y3)));
// uses the vertices and the centers to make 3 child triangles.
// append means to add to a specified array
return c;
}

In each iteration, we would take what would originally be a Child Triangle in the last iteration and make it a Parent Triangle in the current iteration.

We did the same with all of the child triangles for 10 iterations. To change the number of iterations, change the value of the variable count.

int count = 0;void setup(){
size(700, 700);
t = new Triangle (new Point (350, 50),
new Point (50,650),
new Point (650, 650));
//we use noLoop() so we can control number of iterations
noLoop();
}
void drawTriangles(Triangle[] tris) {
// declares an array of tris
while (count < 10) { //determines the amount of iterations
count++; //increases count
Triangle[] ctris = new Triangle[0]; //creates a fresh array
for(Triangle tri : tris) {
tri.draw();
Triangle[] cs = findChildren(tri);
for (Triangle increase : cs) {
ctris = (Triangle[])append(ctris, increase);
}
}
drawTriangles(ctris);
}
}

See full code using processing on GitHub.

Signing off ‘till next time,

Avi

--

--

Avi Gupta
hackerLog

Named after the first 2 games I got on my xBox, Forza and Minecraft. Also, i have a blog. Real name is Avi.