Pookkalam by Fazil

Code

class CustomColor:
    def __init__(self, r, g, b, a=1):
        self.r = r
        self.g = g
        self.b = b
        self.a = a

    def copy(self):
        return CustomColor(self.r, self.g, self.b, self.a)

    def __call__(self):
        return color(self.r, self.g, self.b, self.a)

    def __add__(self, other_color):
        return CustomColor(self.r+other_color.r, self.g+other_color.g, self.b+other_color.b, 1)

    def __mul__(self, scalar: int):
        return CustomColor(self.r*scalar, self.g*scalar, self.b*scalar, 1)

    def __truediv__(self, scalar: int):
        return CustomColor(self.r/scalar, self.g/scalar, self.b/scalar, 1)


def lerp(starting_value, final_value, current_step, total_steps):
    """Linear Interpolation. ``current_step`` must start from 0."""
    return ((starting_value * (total_steps - current_step)
             ) + (final_value * current_step)) / total_steps


def spiral(radius, starting_alpha: int, final_alpha: int, starting_color: CustomColor, final_color: CustomColor, i: int = 0, repetitions: int = 10, rotate_angle: int = 36, delta_x: int = 9):
    if i < repetitions:
        x_coord = delta_x*i
        theta = rotate_angle*i
        current_color = lerp(starting_color, final_color, i, repetitions)
        current_color.a = lerp(starting_alpha, final_alpha, i, repetitions)
        shape = circle(r=radius, fill=current_color(), stroke="none",
                       x=x_coord) | rotate(theta) | scale(0.85**i)
        return shape + spiral(radius=radius, starting_alpha=starting_alpha, final_alpha=final_alpha,
                              starting_color=starting_color, final_color=final_color, i=i+1, repetitions=10, rotate_angle=rotate_angle, delta_x=delta_x)
    else:
        return circle(r=1, stroke="none")
         


def create_flower(petal_num, petal_color=None, petal_color_alternate=None, flower_center_color=None):
    theta = 360/petal_num
    alternate_petal = circle(fill=petal_color_alternate, r=35, stroke="none") | translate(
        x=50, y=0) | rotate(theta/2)
    alternate_petals = alternate_petal | repeat(petal_num, rotate(theta))
    flower = alternate_petals
    petal = ellipse(fill=petal_color, w=50, h=25,
                    stroke="none") | translate(x=25, y=0)
    petals = petal | repeat(petal_num, rotate(theta))
    flower += petals
    flower_center = circle(fill=flower_center_color, r=10, stroke="none")
    flower += flower_center
    return flower

tip_petal_color = color(255, 255, 100, 1)
tip_petal_color_alternate = color(255, 255, 255, 0)
tip_flower = create_flower(petal_num=8, petal_color=tip_petal_color,
                               petal_color_alternate=tip_petal_color_alternate)|scale(0.25)|translate(x=15.2, y=-11)

red = CustomColor(255, 120, 120)
white = CustomColor(255, 255, 255)
octo_arm = spiral(radius=36, starting_alpha=0.2, final_alpha=1,
              starting_color=red, final_color=white, repetitions=10) + tip_flower
octo_arm = octo_arm | rotate(-145) | translate(x=87)
octo_arms = octo_arm | repeat(8, rotate(45))

starting_background_color = CustomColor(255, 120, 120)
final_background_color = CustomColor(255, 222, 222)
background = spiral(radius=125, starting_alpha=1, final_alpha=0.5,
                    starting_color=starting_background_color, final_color=final_background_color, repetitions=10, rotate_angle=0, delta_x=0)

octo_head_color = CustomColor(255, 184, 184)
octo_head = spiral(radius=35, starting_alpha=0, final_alpha=0.5,
                    starting_color=white, final_color=octo_head_color, repetitions=10, rotate_angle=0, delta_x=0)

central_petal_color = color(255, 255, 100, 1)
central_petal_color_alternate = color(255, 100, 100, 0.5)
central_flower = create_flower(petal_num=8, petal_color=central_petal_color,
                               petal_color_alternate=central_petal_color_alternate) | scale(0.5)

show(background + octo_arms + octo_head + central_flower)