Close

Sierpinski Triangle

A project log for Playing with MicroPython on the ESP

Instant gratification on the ESP8266 and ESP-32

hari-wigunaHari Wiguna 06/23/2019 at 03:590 Comments

Seeing Sierpinski Triangle on Facebook inspired me to try it on my tiny OLED.

import machine, ssd1306, math, time
from machine import Pin

def toInt(a):
    return [int(a[0]), int(a[1])]

def toMid(a, b):
    return [(b[0]+a[0])/2, (b[1]+a[1])/2]

class Sierpinski3:
    isWemosD1Mini = True
    xMax = 64 if isWemosD1Mini else 128
    yMax = 48 if isWemosD1Mini else 64
    sclPin = 5 if isWemosD1Mini else 18
    sdaPin = 4 if isWemosD1Mini else 21
    x0 = xMax / 2
    y0 = yMax / 2

    def oledSetup(self):
        i2c = machine.I2C(scl=Pin(self.sclPin), sda=Pin(self.sdaPin))
        return ssd1306.SSD1306_I2C(self.xMax, self.yMax, i2c)

    def plot(self, oled, a, b, c):
        p = toInt(a)
        q = toInt(b)
        r = toInt(c)
        oled.line(p[0], self.yMax-1-p[1], q[0], self.yMax-1-q[1], 1)
        oled.line(q[0], self.yMax-1-q[1], r[0], self.yMax-1-r[1], 1)
        oled.line(r[0], self.yMax-1-r[1], p[0], self.yMax-1-p[1], 1)

    def fillTriangle(self, oled, bottomLeft, width):
        if width>8:
            bottomRight = [bottomLeft[0] + width, bottomLeft[1]]
            half = width / 2
            y = bottomLeft[1] + math.sqrt(width**2 - half**2)
            top = [bottomLeft[0] + width/2, y]

            mid1 = toMid(bottomLeft, top)
            mid2 = toMid(bottomRight, top)
            mid3 = toMid(bottomLeft, bottomRight)
            self.plot(oled, mid1, mid2, mid3)

            self.fillTriangle(oled, bottomLeft, half)  # bottom left triangle
            self.fillTriangle(oled, mid3, half)  # bottom right triangle
            self.fillTriangle(oled, mid1, half)  # top triangle

    def drawFrame(self, oled, half):
        oled.fill(0)

        width = half * 2
        bottomLeft = [self.x0 - half, self.y0 - half]
        bottomRight = [self.x0 + half, bottomLeft[1]]
        top = [self.x0, bottomLeft[1] + math.sqrt(width ** 2 - half ** 2)]

        # Draw the first one special
        self.plot(oled, bottomLeft, bottomRight, top)

        # Draw the remaining recursively
        self.fillTriangle(oled, bottomLeft, width)
        oled.show()

    def main(self):
        oled = self.oledSetup()
        while True:
            slop = 5
            for half in range(0, self.y0+slop, 3):
                self.drawFrame(oled, half)
            time.sleep(0.2)
            for half in range(self.y0+slop-3,0,-3):
                self.drawFrame(oled, half)

instance = Sierpinski3()
instance.main()

Discussions