Stylo Doodles

Christmas Tree

Details

Author:

Alex Carney

Github:

alcarney

Dimensions:

1080 x 1080

Stylo Version:

0.9.0
Show Source Show Notes Show Both

Source

from math import pi
import numpy as np

from stylo.domain.transform import translate, rotate
from stylo.color import FillColor
from stylo.shape import Rectangle, Triangle, Shape, Circle
from stylo.image import LayeredImage
darkgreen = FillColor("00aa00")
brown = FillColor("8b4513")
red = FillColor("dd0000")
yellow = FillColor("ffee00")
silver = FillColor("dddddd")
blue = FillColor("00ddff")
class Pot(Shape):
    
    def draw(self):
        
        def pot(x, y):
            y_bounds = np.logical_and(y < 0, y > -0.4)
            x_bounds = np.abs(x) < 0.23 + y/4
            
            return np.logical_and(y_bounds, x_bounds)
            
        return pot
    
class Star(Shape):
    
    def __init__(self, scale=1):
        self.scale = scale
    
    def draw(self):
        
        t1 = Triangle((0.5, 0), (-0.5, 0), (0, 0.75))
        t2 = Triangle((0.5, 0.5), (-0.5, 0.5), (0, -0.25))
        
        def star(x, y):
            
            x = x / self.scale
            y = y / self.scale
            
            shape = np.logical_or(t1(x=x, y=y), t2(x=x, y=y))
            base = np.abs(x) < 0.03 - y/4
            
            ys = y + 0.1
            
            base = np.logical_and(base, ys < 0)
            base = np.logical_and(base, ys  > -0.4)
            
            return np.logical_or(shape, base)
            
        return star
    
class Present(Shape):
    
    def __init__(self, invert=False, scale=1, ratio=1):
        self.invert = invert
        self.scale = scale
        self.ratio = ratio
    
    def draw(self):
        
        h = 0.25
        w = h * self.ratio
        
        shape = Rectangle(x=0, y=0, width=w, height=h)
        
        def present(x, y):
            
            x = x / self.scale
            y = y / self.scale
            
            box = shape(x=x, y=y)
            
            ribbon = np.logical_and(np.abs(x) > 0.02, np.abs(y) > 0.02)
            
            if self.invert:
                ribbon = np.logical_not(ribbon)
            
            return np.logical_and(box, ribbon)
            
        return present
tree_base = Triangle((-0.45, -0.1), (0.45, -0.1), (0, 0.75)) >> translate(0, -0.5)
tree_mid = Triangle((-0.35, -0.05), (0.35, -0.05), (0, 0.6)) >> translate(0, -0.1)
tree_top = Triangle((-0.2, 0), (0.2, 0), (0, 0.5)) >> translate(0, 0.3)

trunk = Rectangle(x=0, y=0, width=0.2, height=0.5) >> translate(0, -0.6)
pot_rim = Rectangle(x=0, y=0, width=0.5, height=0.1) >> translate(0, -0.8)
pot = Pot() >> translate(0, -0.75)

star = Star(scale=0.2) >> translate(0, 0.85)

bauble = Circle(x=0.25, y=-0.1, r=0.03, fill=True)
bauble1 = Circle(x=-0.1, y=0.35, r=0.03, fill=True)
bauble2 = Circle(x=-0.35, y=-0.5, r=0.03, fill=True)
bauble3 = Circle(x=0.3, y=-0.4, r=0.03, fill=True)
bauble4 = Circle(x=-0.2, y=-0.1, r=0.02, fill=True)
bauble5 = Circle(x=0.1, y=0.5, r=0.02, fill=True)
bauble6 = Circle(x=0, y=-0.5, r=0.02, fill=True)
bauble7 = Circle(x=0.1, y=0.15, r=0.02, fill=True)
bauble8 = Circle(x=-0.05, y=0.55, r=0.025, fill=True)
bauble9 = Circle(x=-0.1, y=0.1, r=0.025, fill=True)
bauble10 = Circle(x=0.04, y=-0.25, r=0.025, fill=True)
bauble11 = Circle(x=-0.15, y=-0.35, r=0.025, fill=True)
bauble12 = Circle(x=0.12, y=-0.14, r=0.015, fill=True)
bauble13 = Circle(x=0.08, y=0.34, r=0.015, fill=True)
bauble14 = Circle(x=0.28, y=-0.5, r=0.015, fill=True)
bauble15 = Circle(x=-0.06, y=0, r=0.015, fill=True)

present1 = Present() >> translate(-0.6, -1.05)
present1_r = Present(invert=True) >> translate(-0.6, -1.05)

present2 = Present(ratio=2) >> rotate(-pi/5) >> translate(-0.95, -0.95)
present2_r = Present(invert=True, ratio=2) >> rotate(-pi/5) >> translate(-0.95, -0.95)

present3 = Present(ratio=0.5, scale=1.25) >> translate(-0.32, -1.02)
present3_r = Present(ratio=0.5, invert=True, scale=1.25) >> translate(-0.32, -1.02)
image = LayeredImage(background="0000aa", scale=2.5)

image.add_layer(trunk, brown)

image.add_layer(tree_base, darkgreen)
image.add_layer(tree_mid, darkgreen)
image.add_layer(tree_top, darkgreen)

image.add_layer(pot_rim, red)
image.add_layer(pot, red)

image.add_layer(star, yellow)

image.add_layer(bauble, red)
image.add_layer(bauble1, red)
image.add_layer(bauble2, red)
image.add_layer(bauble3, red)

image.add_layer(bauble4, yellow)
image.add_layer(bauble5, yellow)
image.add_layer(bauble6, yellow)
image.add_layer(bauble7, yellow)

image.add_layer(bauble8, silver)
image.add_layer(bauble9, silver)
image.add_layer(bauble10, silver)
image.add_layer(bauble11, silver)

image.add_layer(bauble12, blue)
image.add_layer(bauble13, blue)
image.add_layer(bauble14, blue)
image.add_layer(bauble15, blue)

image.add_layer(present1, red)
image.add_layer(present1_r, yellow)

image.add_layer(present2, red)
image.add_layer(present2_r, yellow)

image.add_layer(present3, darkgreen)
image.add_layer(present3_r, red)

image(1080, 1080)