用Python turtle画出标准五星红旗,原来国旗绘制有这么多数学奥秘!
用代码向祖国致敬,用数学诠释庄严
一、从五角星到国旗:一个程序员的突发奇想
昨天深夜,在网上看到一个有趣的Python项目------用turtle模块绘制五角星。看着屏幕上逐渐成型的黄色星星,一个想法突然闪过:既然能画五角星,为什么不画一面完整的五星红旗呢?
然而,当我开始动手时,却发现这不仅仅是画几个星星那么简单。国旗的绘制有着严格的标准和比例,每一颗星星的位置、角度、大小都必须精确无误。这不禁让我思考:用代码绘制国旗,到底需要哪些数学知识?
二、五星红旗的数学密码
2.1 国旗的基本规格
根据《中华人民共和国国旗法》和国旗制作标准,五星红旗的规格如下:
- 长宽比:3:2
- 主色调:红色(RGB: 238, 28, 36)和黄色(RGB: 255, 215, 0)
- 五颗星的位置:精确的几何定位
- 星星的大小比例:大星外接圆直径是旗高的3/10,小星是1/10
2.2 星星定位的数学原理
五星红旗上五颗星的位置不是随意摆放的,而是基于黄金分割和几何学的精密计算:
大五角星中心点位置:
x坐标 = 旗面宽度 × 1/4
y坐标 = 旗面高度 × 3/4
四颗小五角星与大星的相对位置:
1号小星:与大星中心连线与水平线夹角 0°
2号小星:夹角 18°
3号小星:夹角 36°
4号小星:夹角 54°
三、代码实现:从零绘制五星红旗
3.1 基础工具:turtle模块快速入门
在开始绘制之前,让我们先熟悉一下turtle模块的几个核心功能:
python
import turtle
# 1. 画布设置
turtle.setup(900, 600) # 设置窗口大小
turtle.screensize(900, 600, "white") # 设置画布大小和背景
# 2. 画笔控制
turtle.pensize(3) # 设置画笔粗细
turtle.pencolor(1, 0, 0) # 设置画笔颜色(RGB格式)
turtle.fillcolor(1, 1, 0) # 设置填充颜色
# 3. 基本绘图命令
turtle.forward(100) # 向前移动100像素
turtle.right(72) # 向右转72度
turtle.penup() # 抬笔,移动时不画线
turtle.pendown() # 落笔,移动时画线
3.2 五角星绘制类:封装的艺术
为了让代码更加模块化和可复用,我设计了一个五角星绘制类:
python
import turtle
import math
class FivePointedStar:
"""五角星绘制类"""
def __init__(self, circumradius, center=(0, 0), rotation=0,
pen_color="yellow", fill_color="yellow"):
"""
初始化五角星
参数:
circumradius: 外接圆半径
center: 中心点坐标 (x, y)
rotation: 旋转角度(度),0表示一个角尖朝上
pen_color: 画笔颜色
fill_color: 填充颜色
"""
self.circumradius = circumradius
self.center = center
self.rotation = rotation
self.pen_color = pen_color
self.fill_color = fill_color
# 计算五角星边长(根据外接圆半径)
self.side_length = 2 * circumradius * math.sin(math.radians(36))
def draw_star(self):
"""绘制一个五角星"""
x, y = self.center
# 移动到起点
turtle.penup()
turtle.goto(x, y - self.circumradius)
turtle.setheading(90 + self.rotation) # 设置朝向
turtle.pendown()
# 设置颜色
turtle.color(self.pen_color, self.fill_color)
# 开始填充
turtle.begin_fill()
# 绘制五角星
for _ in range(5):
turtle.forward(self.side_length)
turtle.right(144) # 五角星内角为144度
turtle.forward(self.side_length)
turtle.left(72) # 转向下一个顶点
# 结束填充
turtle.end_fill()
def __call__(self):
"""使实例可调用"""
self.draw_star()
return self
3.3 完整五星红旗绘制实现
基于国旗标准和上面的五角星类,我们可以实现完整的国旗绘制:
python
import turtle
import math
class NationalFlag:
"""五星红旗绘制类"""
def __init__(self, width=900, height=600):
"""
初始化国旗
参数:
width: 旗面宽度
height: 旗面高度
"""
self.width = width
self.height = height
# 国旗颜色标准RGB值
self.RED = (0.93, 0.11, 0.14) # 红色
self.YELLOW = (1.0, 0.84, 0.0) # 黄色
# 计算基本尺寸
self.grid_width = width / 30 # 网格宽度(1/15旗宽)
self.grid_height = height / 20 # 网格高度(1/10旗高)
# 星星尺寸
self.big_star_radius = height * 0.15 # 大星半径 = 旗高 * 3/20
self.small_star_radius = height * 0.05 # 小星半径 = 旗高 * 1/20
# 星星位置(基于网格坐标)
self.star_positions = [
# 大五角星位置
{
"type": "big",
"grid_x": 5, # 第5格
"grid_y": 5, # 第5格
"center": (0, 0) # 临时占位
},
# 四颗小五角星位置
{
"type": "small",
"grid_x": 10, # 第10格
"grid_y": 2, # 第2格
"angle": 0, # 与大星连线角度
"center": (0, 0)
},
{
"type": "small",
"grid_x": 12,
"grid_y": 4,
"angle": 18,
"center": (0, 0)
},
{
"type": "small",
"grid_x": 12,
"grid_y": 7,
"angle": 36,
"center": (0, 0)
},
{
"type": "small",
"grid_x": 10,
"grid_y": 9,
"angle": 54,
"center": (0, 0)
}
]
# 初始化turtle
self.init_turtle()
def init_turtle(self):
"""初始化turtle设置"""
turtle.setup(self.width + 100, self.height + 100)
turtle.title("五星红旗 - 中华人民共和国国旗")
turtle.speed(0) # 最快速度
turtle.hideturtle() # 隐藏海龟箭头
def grid_to_pixel(self, grid_x, grid_y):
"""
将网格坐标转换为像素坐标
国旗左上角为原点(0,0),向右为x正方向,向下为y正方向
网格系统:横轴15格,纵轴10格
"""
pixel_x = grid_x * self.grid_width
pixel_y = grid_y * self.grid_height
# 转换为turtle坐标系(中心为原点)
turtle_x = pixel_x - self.width / 2
turtle_y = self.height / 2 - pixel_y
return turtle_x, turtle_y
def draw_background(self):
"""绘制红色背景"""
turtle.penup()
turtle.goto(-self.width/2, self.height/2) # 左上角
turtle.pendown()
turtle.fillcolor(self.RED)
turtle.begin_fill()
# 绘制矩形
for _ in range(2):
turtle.forward(self.width)
turtle.right(90)
turtle.forward(self.height)
turtle.right(90)
turtle.end_fill()
def calculate_star_centers(self):
"""计算所有星星的中心坐标"""
# 计算大星中心
big_star = self.star_positions[0]
big_star["center"] = self.grid_to_pixel(
big_star["grid_x"],
big_star["grid_y"]
)
# 计算小星中心
for i in range(1, 5):
star = self.star_positions[i]
star["center"] = self.grid_to_pixel(
star["grid_x"],
star["grid_y"]
)
# 计算小星需要旋转的角度(角尖指向大星中心)
dx = big_star["center"][0] - star["center"][0]
dy = big_star["center"][1] - star["center"][1]
angle_to_big = math.degrees(math.atan2(dy, dx))
# 五角星默认一个角尖朝上(-90度),需要调整
star["rotation"] = angle_to_big - 90
def draw_stars(self):
"""绘制所有五角星"""
# 绘制大五角星
big_star = self.star_positions[0]
star = FivePointedStar(
circumradius=self.big_star_radius,
center=big_star["center"],
rotation=0, # 大星一个角尖正朝上
pen_color=self.YELLOW,
fill_color=self.YELLOW
)
star()
# 绘制四颗小五角星
for i in range(1, 5):
small_star = self.star_positions[i]
star = FivePointedStar(
circumradius=self.small_star_radius,
center=small_star["center"],
rotation=small_star["rotation"], # 小星角尖指向大星
pen_color=self.YELLOW,
fill_color=self.YELLOW
)
star()
def draw_grid_lines(self, show_grid=False):
"""绘制辅助网格线(调试用)"""
if not show_grid:
return
turtle.penup()
turtle.pencolor(0.8, 0.8, 0.8) # 浅灰色
turtle.pensize(1)
# 绘制水平网格线
for i in range(11): # 0-10共11条线
y = self.height/2 - i * self.grid_height
turtle.goto(-self.width/2, y)
turtle.pendown()
turtle.goto(self.width/2, y)
turtle.penup()
# 绘制垂直网格线
for i in range(16): # 0-15共16条线
x = -self.width/2 + i * self.grid_width
turtle.goto(x, self.height/2)
turtle.pendown()
turtle.goto(x, -self.height/2)
turtle.penup()
def draw_flag(self, show_grid=False):
"""绘制完整的五星红旗"""
# 1. 计算星星位置
self.calculate_star_centers()
# 2. 绘制红色背景
self.draw_background()
# 3. 绘制辅助网格(可选)
self.draw_grid_lines(show_grid)
# 4. 绘制五角星
self.draw_stars()
# 5. 完成绘图
turtle.done()
def save_image(self, filename="national_flag.png"):
"""保存国旗图片"""
canvas = turtle.getcanvas()
canvas.postscript(file=filename.replace('.png', '.eps'))
# 如果需要PNG格式,可以使用PIL转换
try:
from PIL import Image
img = Image.open(filename.replace('.png', '.eps'))
img.save(filename, "PNG")
print(f"国旗已保存为: {filename}")
except ImportError:
print(f"EPS文件已保存,如需PNG格式请安装PIL库")
# 主程序
if __name__ == "__main__":
print("开始绘制五星红旗...")
print("国旗比例: 3:2")
print("大五角星半径: 旗高的3/20")
print("小五角星半径: 旗高的1/20")
print("-" * 40)
# 创建国旗对象
flag = NationalFlag(width=900, height=600)
# 绘制国旗(show_grid=True可以显示辅助网格)
flag.draw_flag(show_grid=False)
# 保存图片
# flag.save_image("china_flag.png")
print("五星红旗绘制完成!")
四、关键代码解析
4.1 坐标系统转换
这是整个项目的核心难点之一。我们需要在三种坐标系之间转换:
python
def grid_to_pixel(self, grid_x, grid_y):
"""
坐标转换三部曲:
1. 网格坐标 → 像素坐标(左上角原点)
2. 像素坐标 → 标准化坐标(0-1范围)
3. 标准化坐标 → turtle坐标(中心原点)
"""
# 步骤1:网格转像素
pixel_x = grid_x * self.grid_width
pixel_y = grid_y * self.grid_height
# 步骤2&3:转换为turtle坐标系
turtle_x = pixel_x - self.width / 2
turtle_y = self.height / 2 - pixel_y
return turtle_x, turtle_y
4.2 星星方向计算
小五角星的角尖需要精确指向大五角星中心,这涉及向量角度计算:
ini
# 计算从当前小星指向大星的向量
dx = big_star_x - small_star_x
dy = big_star_y - small_star_y
# 计算向量角度(弧度)
angle_rad = math.atan2(dy, dx)
# 转换为角度,并调整使得角尖指向大星
rotation_angle = math.degrees(angle_rad) - 90
4.3 五角星几何算法
绘制完美的正五角星需要精确的几何计算:
ini
# 五角星边长与外接圆半径的关系
# 公式:边长 = 2 * 半径 * sin(36°)
side_length = 2 * radius * math.sin(math.radians(36))
# 绘制时的旋转角度
# 内角:144°,外角:72°
for _ in range(5):
turtle.forward(side_length)
turtle.right(144) # 转向绘制下一个角
五、国旗绘制的数学之美
5.1 黄金分割的应用
五星红旗的设计中蕴含了黄金分割比例(φ ≈ 1.618):
ini
旗面长宽比 = 3:2 = 1.5(接近黄金比例)
大星中心位置:
距左 = 旗宽 × 1/4
距上 = 旗高 × 3/4
这些比例都接近或等于黄金分割比例
5.2 星星布局的几何学
四颗小星的布局形成了一个圆弧,这个大圆弧的圆心正是大五角星的中心,形成了和谐统一的视觉效果。
六、扩展应用与思考
6.1 代码优化方向
- 性能优化 :使用
turtle.tracer(0)关闭动画,最后调用turtle.update()一次性更新 - 交互功能:添加点击缩放、拖动查看细节等功能
- 参数化设计:允许自定义国旗尺寸、颜色等参数
6.2 数学教育的绝佳案例
这个项目不仅是编程实践,更是生动的数学教学案例:
- 几何学:正五角星的绘制
- 三角函数:角度计算、坐标转换
- 比例与缩放:国旗的标准比例
- 坐标系:不同坐标系统的转换
6.3 进阶挑战
如果你已经掌握了基本绘制,可以尝试这些进阶挑战:
- 动画绘制:让五角星一颗颗逐渐显示
- 3D国旗:使用三维图形库绘制飘扬的国旗
- 国旗知识问答:结合绘制过程,进行国旗知识科普
- 多种国旗绘制:实现世界各国国旗的绘制
七、总结
通过Python的turtle模块绘制五星红旗,不仅是一次编程实践,更是一次深刻的爱国主义教育和数学美学体验。每一行代码都蕴含着对国旗标准的尊重,每一个函数都体现了数学的精确与优雅。
国旗的绘制标准是严格的,但代码的实现可以是灵活的。在遵循国旗法规定的前提下,我们可以用编程语言表达对祖国的热爱,用数学公式诠释国旗的庄严。
代码不仅是工具,也可以是艺术的表达;数学不仅是公式,也可以是美的呈现。
注意事项:
- 本项目代码遵循《中华人民共和国国旗法》相关规定
- 国旗的绘制必须严格按照国家标准比例
- 本代码仅用于教育和学习目的
- 实际使用国旗时应遵守相关法律法规
用代码致敬祖国,用技术传承文化。每一次绘制,都是对国旗庄严的再认识;每一行代码,都是对祖国深情的再表达。