绘制奥林匹克标志——利用python turtle画奥运五环

奥运五环

先看实际例子。

北京奥运会会徽
北京奥运会会徽

  

北京冬奥会会徽
北京冬奥会会徽

https://olympics.com/ioc/olympic-rings

奥林匹克标志 (Olympic Logo /Symbole Olympique/Olympic Rings)是由皮埃尔·德·顾拜旦先生于1913年构思设计的,是由《奥林匹克宪章》确定的,也被称为奥运五环标志,它是世界范围内最为人们广泛认知的奥林匹克运动会标志。它由5个奥林匹克环套接组成,有蓝、黄、黑、绿、红5种颜色。环从左到右互相套接,上面是蓝、黑、红环,下面是是黄、绿环。整个造型为一个底部小的规则梯形。(from baidu百科)

五环的两个版本

在北京奥运会上看到的五环标志是国际奥委会1986年公布的版本,在环与环套接之处留有间隙。下图是本文程序的绘制效果。

2010年之后,五环标志的视觉样式变为“无缝交错”版本,也就是在今年(2021)东京2020奥运会看到的、以及将要在明年年初北京2022冬奥会上看到的五环。下图是本文程序的绘制效果。

程序说明

  • 利用pensize(),color(),circle()画出圆环。
  • 正确处理圆环之间的遮挡关系。采用分段法,除黄色环一次画出,其他四个环都分两次画出。在两环的交叠区域,后绘制的部分遮盖较早绘制的部分。
  • 每一段圆环的绘制分为三步:_move_to()移到起始位置,_jump_circle()根据需要跳过一段圆弧,_draw_ring()落笔绘制。在draw_5rings()中定义了p,c,r三个List,实际是查表,每一次循环从List读取需要的参数。数据之间是有关联的。例如c[0]跳过45度,r[0]落笔画出180度即半圆环,所以在后面的c[6]跳过45+180=225度之后,再画出r[6]的180度,即另一半,从而完成整个圆环。OlympicRings实例化时指定speed等于1到10 之间的数,可以观察动画过程。
  • draw_5rings(True)将输出带有套接间隙的奥运五环。_draw_ring()函数中的ex变量设置为5,这是为了多出一点余量,确保圆环完整。

源代码

# -* encoding: utf-8 *
# Turtle example: The Olympic rings
# Author: wanghuiict

from turtle import Turtle,Screen

U=28 # unit
R=2.75
class OlympicRings(Turtle):
    def __init__(self, speed=0):
        Turtle.__init__(self)
        self.hideturtle()
        self.speed(speed)

    ''' (w * steps) * (h * steps) '''
    def draw_recflag(self, step, color='red', w=30, h=20):
        self.pensize(1)
        self.penup()
        self.home()
        self.left(180)
        self.forward(w/2 * step)
        self.right(90)
        self.forward(h/2 * step - R * step)
        self.pendown()
        self.fill(True)
        self.color(color)
        self.begin_fill()
        for _ in range(2):
          self.right(90)
          self.forward(w * step)
          self.right(90)
          self.forward(h * step)
        self.end_fill()
        self.penup()

    def _move_to(self, distance, angle=90, distance2=0):
        self.penup()
        self.home()
        self.fd(distance)
        self.lt(angle)
        if distance2 != 0:
            self.fd(distance2)

    def __circle_part(self, radius, extent=360, show=True):
        if radius == 0:
            return
        if not show:
            self.penup()
        else:
            self.pendown()
        self.circle(radius, extent)
        
    def _jump_circle(self, radius, extent):
        return self.__circle_part(radius, extent, False)

    def _draw_ring(self, radius, extent, color, showspace=False):
        if showspace == True:
            self.color('white')
            self.pensize(0.7 * U)
            self.__circle_part(radius, extent)
        self.color(color)
        self.pensize(0.5 * U)
        if showspace == True:
            ex = 5 if extent > 0 else -5 
            self.__circle_part(radius, ex)
            self.__circle_part(radius, -extent-ex-ex)
        else:
            self.__circle_part(radius, extent)

    def draw_5rings(self, showspace=True):
        p = [(R*U, 90, 0), ((6.4+R)*U, 90, 0), (-(6.4+R)*U, 270, 0),
             (-(3.2+R)*U, 270, 3*U), ((3.2-R)*U, 270, 3*U), (-(6.4+R)*U, 270, 0),
             (R*U, 90, 0), ((3.2-R)*U, 270, 3*U), ((6.4+R)*U, 90, 0)]
        c = [(R*U, 45), (0, 0), (0, 0),
             (0, 0), (R*U, 135), (R*U, 135),
             (R*U, 225), (R*U, 315), (R*U, 225)]
        r = [(180, '#232223'), (225, '#EE324E'), (135, '#0081BC'),
             (360, '#FCB131'), (180, '#009D57'), (225, '#0081BC'),
             (180, '#232223'), (180, '#009D57'), (135, '#EE324E')]
        for i in range(9):
            self._move_to(p[i][0], p[i][1], p[i][2])
            self._jump_circle(c[i][0], c[i][1])
            self._draw_ring(R*U, r[i][0], r[i][1], showspace)

if __name__ == '__main__':
    W=60
    H=40
    wn = Screen()
    wn.bgcolor("lightgreen")
    wn.title("The Olympic rings")
    wn.screensize(W*10, H*10)
    
    a = OlympicRings(speed=0)
    a.draw_recflag(12, color='white', w=W, h=H)
    a.draw_5rings(False)
    wn.exitonclick()

  • 1
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值