Draw Bing DwenDwen and Shuey RhonRhon with Python

With the convening of the 2022 Beijing Winter Olympics, Bing DwenDwen and Shuey RhonRhon instantly jumped to “top traffic”. What if we can’t get it? Let’s write the code to create them!

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Ellipse
from matplotlib.patches import Rectangle

plt.rcParams['font.sans-serif']=['Comic Sans MS'] 

The basic idea of ​​the code is actually very simple, that is to keep drawing ellipses. In order to simplify the code, we write a function to draw ellipses.

def ellipse(el, edgecolor='black', facecolor='w', n=0, alpha=1):

    axs[n].add_patch(el)
    el.set_facecolor(facecolor)
    el.set_alpha(alpha)
    el.set_edgecolor(edgecolor)

Bing DwenDwen 🐼

def BingDwenDwen():

    # Ice shell
    ellipse(Ellipse((0, -0.3), 6+0.3, 6.6+0.3, 0)) # Body
    ellipse(Ellipse((1.7, 2.4), 1.2+0.3, 1.25+0.3, 0)) # Ear
    ellipse(Ellipse((-1.7, 2.4), 1.2+0.3, 1.25+0.3, 0))

    ellipse(Ellipse((-3, -0.9), 2.8+0.3, 1.2+0.3, 30)) # Left arm
    ellipse(Ellipse((-3.7, -1.3), 1.16+0.3, 1.16+0.3, 0))
    ellipse(Ellipse((-3, -0.9), 2.8+0.2, 1.2+0.2, 30),'w','w')
    ellipse(Ellipse((3, 0.7), 2.8+0.3, 1.2+0.3, 45)) # Right arm
    ellipse(Ellipse((3.6, 1.2), 1.16+0.3, 1.16+0.3, 0))
    ellipse(Ellipse((3, 0.7), 2.8+0.2, 1.2+0.2, 45),'w','w')

    ellipse(Ellipse((1.2, -3.2), 1.6+0.3, 2.4+0.3, 0)) # Right leg
    ellipse(Ellipse((1.15, -4), 1.4+0.3, 1+0.3, 0))
    ellipse(Ellipse((1.2, -3.2), 1.6+0.2, 2.4+0.2, 0), 'w', 'w')
    ellipse(Ellipse((-1.2, -3.2), 1.6+0.3, 2.4+0.3, 0)) # Left leg
    ellipse(Ellipse((-1.15, -4), 1.4+0.3, 1+0.3, 0))
    ellipse(Ellipse((-1.2, -3.2), 1.6+0.2, 2.4+0.2, 0), 'w', 'w')

    ellipse(Ellipse((0, -0.3), 6+0.2, 6.6+0.2, 0), 'w', 'w') # Body

    # Ears
    ellipse(Ellipse((1.7, 2.4), 1.2, 1.25, 0), 'black','black')
    ellipse(Ellipse((-1.7, 2.4), 1.2, 1.25, 0), 'black','black')

    # Arms
    ellipse(Ellipse((-3, -0.9), 2.8, 1.2, 30), 'black','black') # Left
    ellipse(Ellipse((-3.7, -1.3), 1.16, 1.16, 0), 'black','black')
    ellipse(Ellipse((3, 0.7), 2.8, 1.2, 45), 'black','black') # Right
    ellipse(Ellipse((3.6, 1.2), 1.16, 1.16, 0), 'black','black')

    # Legs
    ellipse(Ellipse((1.2, -3.2), 1.6, 2.4, 0), 'black','black')
    ellipse(Ellipse((1.15, -4), 1.4, 1, 0), 'black','black')
    ellipse(Ellipse((-1.2, -3.2), 1.6, 2.4, 0), 'black','black')
    ellipse(Ellipse((-1.15, -4), 1.4, 1, 0), 'black','black')

    # Body
    ellipse(Ellipse((0, -0.3), 6, 6.6, 0), 'black')

    # Rings around the face
    for i in range(5):
        width = 0.06
        tt = np.linspace(0, np.pi, 100)
        x1 = (2.45-width*i) * np.cos(tt)
        y1 = (2.4-width*i) * np.sin(tt)
        x2 = (2.45-width*i) * np.cos(tt)
        y2 = -(1.7-width*i) * np.sin(tt)
        axs[0].plot(x1,y1,color=colorList[i],linewidth=1)
        axs[0].plot(x2,y2,color=colorList[i],linewidth=1)

    # Eyes
    ellipse(Ellipse((1.1, 1), 1, 1.4, 55), 'black','black') # Right
    ellipse(Ellipse((0.9, 1), 0.5, 0.5, 0), 'w','black')
    ellipse(Ellipse((1, 1), 0.05, 0.05, 0), 'w')
    ellipse(Ellipse((-1.1, 1), 1, 1.4, -55), 'black','black') # Left
    ellipse(Ellipse((-0.9, 1), 0.5, 0.5, 0), 'w','black')
    ellipse(Ellipse((-0.8, 1), 0.05, 0.05, 0), 'w')

    # Mouth
    ellipse(Ellipse((0, -0.1), 1.2, 1, 20), 'black','black')
    ellipse(Ellipse((0, 0.4), 0.8, 0.5, 10), 'w')
    ellipse(Ellipse((0, -0.28), 0.85, 0.6, 10),'black', (180/255,39/255,45/255))

    # Nose
    ellipse(Ellipse((0, 0.5), 0.4, 0.2, 0), 'black','black')

    # Olympic Rings
    tt = np.linspace(0, 2*np.pi, 100)
    x = 0.2*np.sin(tt)
    y = 0.2*np.cos(tt) - 3.2
    axs[0].plot(x-0.5,y+0.15,color=colorList[0],linewidth=0.65)
    axs[0].plot(x-0.25,y,color=colorList[1],linewidth=0.65)
    axs[0].plot(x,y+0.15,color=colorList[2],linewidth=0.65)
    axs[0].plot(x+0.25,y,color=colorList[3],linewidth=0.65)
    axs[0].plot(x+0.5,y+0.15,color=colorList[4],linewidth=0.65)
    
    # Heart❤️ in the left hand
    tt=np.linspace(-2.9,2.9,1000)
    x=0.3*(np.sin(tt))**3
    y=0.2*(1.3*np.cos(tt)-.5*np.cos(2*tt)-.2*np.cos(3*tt)-.1*np.cos(4*tt))
    axs[0].fill(x+3.6, y+1.2, color=(180/255,39/255,45/255))

    # LOGO
    axs[0].text(0, -2.75, 'BEIJING 2022', ha='center', fontsize=5) 

Shuey RhonRhon 🏮

def ShueyRhonRhon():
    
    gold = (255/255, 215/255, 0) # The main body of Shuey RhonRhon is composed of red and gold, and the commonly used RGB value of gold is (255, 215, 0)
    
    # Arms
    ellipse(Ellipse((-1.4, -2.5), 1.65, 0.65, -30), 'r', 'r', 1) 
    ellipse(Ellipse((1.45, -2.9), 1.6, 0.6, -40), 'r', 'r', 1) 

    # Head
    ellipse(Ellipse((0, 2), 4.3, 1.7, 0), 'r', 'r', 1)
    ellipse(Ellipse((0, 0), 6.2, 4.8, 0), 'r', 'r', 1)
    ellipse(Ellipse((0, 0), 4.6, 5, 0), gold, 'r', 1)
    ellipse(Ellipse((0, 0), 2.6, 5, 0), gold, 'r', 1)
    ellipse(Ellipse((0, 0), 0.01, 5, 0), gold, 'r', 1)
    ellipse(Ellipse((0, 0), 3.5, 1.8, 0), 'w', 'w', 1)
    ellipse(Ellipse((-1.2, -0.5), 1.4, 1, 0), 'w', 'w', 1)
    ellipse(Ellipse((-0.6, 0.6), 1.5, 1, 0), 'w', 'w', 1)
    ellipse(Ellipse((0, 0.8), 1.5, 1, 0), 'w', 'w', 1)
    ellipse(Ellipse((-1.35, -0.68), 0.65, 0.6, 0), 'w', 'w', 1)
    ellipse(Ellipse((1.4, -0.5), 1, 0.8, 160), 'w', 'w', 1)
    
    # Outline
    tt = np.linspace(np.pi/2, np.pi/2*3, 100)
    x = 3.25 * np.sin(tt)
    y = 2.5 * np.cos(tt) + 0.1
    axs[1].plot(x, y, color='w', linewidth=1)
    
    tt = np.linspace(-np.pi/3, np.pi/3, 100) 
    x = 3.3 * np.sin(tt)
    y = 2.5 * np.cos(tt) + 0.21
    axs[1].plot(x, y, color='w', linewidth=5)
    
    # Eyes and blush
    ellipse(Ellipse((1, 0), 0.2, 0.3, 0), 'black', 'black', 1)
    ellipse(Ellipse((-1, 0), 0.2, 0.3, 0), 'black', 'black', 1)
    ellipse(Ellipse((1, 0.1), 0.02, 0.02, 0), 'w', 'w', 1)
    ellipse(Ellipse((-1, 0.1), 0.02, 0.02, 0), 'w', 'w', 1)
    ellipse(Ellipse((1.4, -0.45), 0.5, 0.4, 0), 'w', 'r', 1, 0.4) 
    ellipse(Ellipse((-1.4, -0.45), 0.5, 0.4, 0), 'w', 'r', 1, 0.4) 
    
    # Legs
    ellipse(Ellipse((0.66, -4), 0.6, 0.8, 0), 'r', 'r', 1)
    ellipse(Ellipse((0.56, -4.2), 0.8, 0.6, 0), 'r', 'r', 1)
    ellipse(Ellipse((-0.66, -4), 0.6, 0.8, 0), 'r', 'r', 1)
    ellipse(Ellipse((-0.56, -4.2), 0.8, 0.6, 0), 'r', 'r', 1)
    
    # Body
    ellipse(Ellipse((0, -3.25), 2.6, 1.9, 0), 'r', 'r', 1)
    ellipse(Ellipse((0, -3.25), 1.15, 1.15, 0), 'w', 'w', 1)
    ellipse(Ellipse((0, -3.25), 1.25, 1.25, 0), gold, gold, 1, 0.5)
    ellipse(Ellipse((0, -3.25), 1, 1, 0), 'w', 'w', 1)
    
    # Scarf
    tt = np.linspace(np.pi-0.35, np.pi+0.36, 100)
    x = 3.25 * np.sin(tt)
    y = 2.55 * np.cos(tt) + 0.1
    axs[1].plot(x, y-0.02, color='black', linewidth=5)
    axs[1].plot(x, y, color=gold, linewidth=5)
    axs[1].add_patch(Rectangle((-1+0.02,-3.1-0.02),0.6,0.05,70,color='black'))
    axs[1].add_patch(Rectangle((-1.15+0.02,-3.045-0.02),0.25,0.05,70,color='black'))
    axs[1].add_patch(Rectangle((-1.3+0.02,-2.985-0.02),0.25,0.05,70,color='black'))
    axs[1].add_patch(Rectangle((-1.45+0.02,-2.925-0.02),0.25,0.05,70,color='black'))
    axs[1].add_patch(Rectangle((-0.91,-2.85),0.4,0.54,70,color=gold))
    axs[1].add_patch(Rectangle((-1,-3.1),0.25,0.05,70,color=gold))
    axs[1].add_patch(Rectangle((-1.15,-3.045),0.25,0.05,70,color=gold))
    axs[1].add_patch(Rectangle((-1.3,-2.985),0.25,0.05,70,color=gold))
    axs[1].add_patch(Rectangle((-1.45,-2.925),0.25,0.05,70,color=gold))
    
    # Pigeon🐦 motif on the headdress
    def pigeon(x, y, sign=1): 
        ellipse(Ellipse((x, y), 0.1, 0.2, sign*45), gold, gold, 1) 
        ellipse(Ellipse((x+sign*0.1, y), 0.1, 0.2, -sign*45), gold, gold, 1) 
        ellipse(Ellipse((x+sign*0.22, y+0.1), 0.2, 0.08, sign*20), gold, gold, 1) 
        ellipse(Ellipse((x-sign*0.1, y+0.1), 0.1, 0.01, 0), gold, gold, 1) 
        ellipse(Ellipse((x+sign*0.12, y-0.08), 0.05, 0.01, 0), gold, gold, 1) 
        ellipse(Ellipse((x+sign*0.17, y-0.03), 0.05, 0.01, 0), gold, gold, 1) 

    axs[1].add_patch(Rectangle((-2.2, 1.65), 4.4, 0.4, 0, color='r'))
    ellipse(Ellipse((-0.2, 2.4), 1.6, 0.8, 0), 'w', 'w', 1) 
    ellipse(Ellipse((-1.2, 2.35), 0.6, 1.6, 110), 'w', 'w', 1) 
    ellipse(Ellipse((1.2, 2.3), 0.7, 1.4, 80), 'w', 'w', 1) 
    pigeon(0.25, 1.76)
    pigeon(-0.25, 1.76, -1)
    pigeon(1.5, 1.76)
    pigeon(1.05, 1.76, -1)
    pigeon(-1.05, 1.76)
    pigeon(-1.5, 1.76, -1)

    # Overhead handles
    tt1 = np.linspace(-np.pi/3.2, np.pi/3.2, 100) 
    tt2 = np.linspace(0, np.pi, 100) 
    axs[1].plot(0.4*np.sin(tt1), 0.4*np.cos(tt1)+2.9, color=gold, linewidth=1)
    axs[1].plot(0.1*np.sin(tt2)+0.36, 0.1*np.cos(tt2)+3, color=gold, linewidth=1)
    axs[1].plot(-0.1*np.sin(tt2)-0.36, 0.1*np.cos(tt2)+3, color=gold, linewidth=1)
    
    # Tree-like decorations on the feet
    def tree(x, y): 
        ellipse(Ellipse((x, y-0.05), 0.05, 0.2, 0), gold, gold, 1) 
        ellipse(Ellipse((x, y+0.1), 0.05, 0.1, 0), gold, gold, 1) 
        ellipse(Ellipse((x+0.1, y+0.07), 0.1, 0.1, 0), gold, gold, 1) 
        ellipse(Ellipse((x-0.1, y+0.07), 0.1, 0.1, 0), gold, gold, 1) 
        ellipse(Ellipse((x+0.2, y+0.02), 0.06, 0.06, 0), gold, gold, 1) 
        ellipse(Ellipse((x-0.2, y+0.02), 0.06, 0.06, 0), gold, gold, 1) 
        ellipse(Ellipse((x, y-0.15), 0.1, 0.01, 0), gold, gold, 1) 
    tree(0.25,-4.2)
    tree(0.75,-4.2)
    tree(-0.25,-4.2)
    tree(-0.75,-4.2)
    
    # LOGO
    axs[1].text(0, -3.4, 'BEIJING 2022', ha='center', fontsize=2)
fig, axs = plt.subplots(1, 2, subplot_kw={"aspect": "equal"})
axs[0].axis([-5, 5, -5, 5])
axs[1].axis([-5, 5, -5, 5])
axs[0].axis('off')
axs[1].axis('off')
colorList=[(98/255,205/255,247/255),(251/255,184/255,77/255),'black',(132/255,199/255,114/255), (158/255,48/255,87/255),] # The colors of the Olympic Rings

BingDwenDwen()
ShueyRhonRhon()

plt.show()

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s