python画国旗-五星红旗

如何用python绘制一面国旗

前言

了解一些国旗的一些基本知识:

旗帜图案

1、五星红旗制作标准是:先将旗面划分为4个等分长方形,再将左上方长方形划分长宽15×10个方格。大五角星的中心位于该长方形上5下5、左5右10之处。大五角星外接圆的直径为6单位长度。

2、四颗小五角星的中心点,第一颗位于上2下8、左10右5,第二颗位于上4下6、左12右3,第三颗位于上7下3、左12右3,第四颗位于上9下1、左10右5之处。

3、每颗小五角星外接圆的直径均为2单位长度。四颗小五角星均有一角尖正对大五角星的中心点。

4、根据《中华人民共和国国旗法》第四条规定,制作国旗的企业由省、自治区和直辖市的人民政府指定。国旗的长宽之比为3:2。

尺寸规格

根据1949年9月28日中国人民政治协商会议第一届全体会议主席团公布的《国旗制法说明》,中华人民共和国国旗之通用尺度定为如下五种,各界酌情选用:

甲、长288公分,高192公分。

乙、长240公分,高160公分。

丙、长192公分,高128公分。

丁、长144公分,高96公分。

戊、长96公分,高64公分

可以根据墨线法绘制国旗,如下图:

具体实现

1.生成一个空白窗口

利用tkintermath库实现,tkinter实现可视化界面,math主要用于计算坐标点;定义窗口的长跟宽,并生成一个窗口

1
2
3
4
5
6
7
8
9
10
import tkinter as tk
import math

width = 660
height = 440

window = tk.Tk()
canvas = tk.Canvas(width=width, height=height)
canvas.pack()
window.title("五星红旗")

2.画出红旗底面

生成一个红色背景的矩形,宽、高与窗口相同是为了便于后续计算中心点坐标

1
2
3
4
5
6
7
8
9
def draw_rectangle(width,height):
"""根据传入的长、宽画出旗面"""
# 确定中心点坐标
x = width / 2
y = height / 2
# 画出红旗的矩形
canvas.create_rectangle(x-(width/2),y-(height/2),x+(width/2),y+(height/2),outline='red',fill='red')

draw_rectangle(width,height)

3.计算五角星中心点坐标

五星红旗制作标准是:先将旗面划分为4个等分长方形,再将左上方长方形划分长宽15×10个方格。大五角星的中心位于该长方形上5下5、左5右10之处。大五角星外接圆的直径为6单位长度。

四颗小五角星的中心点,第一颗位于上2下8、左10右5,第二颗位于上4下6、左12右3,第三颗位于上7下3、左12右3,第四颗位于上9下1、左10右5之处。

通过下面的函数可以,根据输入的宽、高值返回指定五角星的中心点及外接圆半径值。star_type中的0-4分别表示大五角星及从上到到下的4颗小五角星;将宽平均分为30份、高平均分为20份,完成五角星坐标中心坐标计算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def get_coordinates(width,height,star_type=0):
"""根据传入的宽、高,返回一组坐标
star_type中的0表示返回的为大五角星的中心点坐标,
1-4分别为从上到下的4颗小五角星坐标
"""
# 反回中心点坐标及半径
if star_type == 0:
center_x = width/2 - (width/30*10)
center_y = height/2 - (height/20*5)
r = (width / 30) *3
return center_x, center_y, r
elif star_type == 1:
center_x = width/2 - (width/30*5)
center_y = height/2 - (height/20*8)
r = (width / 30) *1
return center_x, center_y, r
elif star_type == 2:
center_x = width/2 - (width/30*3)
center_y = height/2 - (height/20*6)
r = (width / 30) *1
return center_x, center_y, r
elif star_type == 3:
center_x = width/2 - (width/30*3)
center_y = height/2 - (height/20*3)
r = (width / 30) *1
return center_x, center_y, r
elif star_type == 4:
center_x = width/2 - (width/30*5)
center_y = height/2 - (height/20*1)
r = (width / 30) *1
return center_x, center_y, r

4.计算五角星的5个顶点坐标

根据正五角星的数学特性,∠OEL=18°,∠GEL=36°,∠EOL=72°,OE为外切圆半径就是radius,那么根据数学公式:

sin18° = OL / OE => OL = sin18° * OE 或者 cos72° =OL/OE => OL=cos72° *OE
cos18° = EL / OE => EL = cos18° * OE 或者 sin72° = EL/OE => EL=sin72° *OE
tan36° = GL / EL => GL = tan36° * EL

所以各个点的坐标计算公式如下:

左上点

​ center_x-r*math.sin(2*math.pi/5),
​ center_y-r*math.cos(2*math.pi/5)

右上点

​ center_x+r*math.sin(2*math.pi/5),
​ center_y-r*math.cos(2*math.pi/5)

左下点

​ center_x-r*math.sin(math.pi/5),
​ center_y+r*math.cos(math.pi/5)

顶点

​ center_x,
​ center_y-r

右下点

​ center_x+r*math.sin(math.pi/5),
​ center_y+r*math.cos(math.pi/5)

完整的函数可以按如下定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def draw_star(x,y,star_type=0):
"""根据传入的长、宽及返回五角星的5个点坐标"""
# 确定中心点坐标及半径
tem = get_coordinates(x,y,star_type)
center_x = tem[0]
center_y = tem[1]
r = tem[2]

points=[
# 左上点
(center_x-r*math.sin(2*math.pi/5),
center_y-r*math.cos(2*math.pi/5)),

# 右上点
(center_x+r*math.sin(2*math.pi/5),
center_y-r*math.cos(2*math.pi/5)),

# 左下点
(center_x-r*math.sin(math.pi/5),
center_y+r*math.cos(math.pi/5)),

# 顶点
(center_x,
center_y-r),

# 右下点
(center_x+r*math.sin(math.pi/5),
center_y+r*math.cos(math.pi/5)),
]
#返回5个点的坐标组列表,中心点x、y坐标值及半径
return points,center_x,center_y,r

5.旋转小五角星

上面的四颗小五角星还没旋转角度,我们要计算出每个小五角星的旋转角度,首先算出大五角星外切圆圆心和每个小五角星外切圆圆心的角度,如下:

⭐︎第一颗:Math.atan(3 / 5) * 180 / Math.PI ≈ 30.96°
⭐︎第二颗:Math.atan(1 / 7) * 180 / Math.PI ≈ 8.13°
⭐︎第三颗:Math.atan(2 / 7) * 180 / Math.PI ≈ 15.94°
⭐︎第四颗:Math.atan(4 / 5) * 180 / Math.PI ≈ 38.66°

最后还要加减18°(18°为五角星外部角的一半值),得到-48.96°,-26.13°,-2.06,20.66这几个数据。代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
def rotate_point(points, center_x, center_y, angle):
"""对一组点进行旋转换算"""
vertices = []
#对小五角星进行旋转
angle_rad = math.radians(angle)
cos_theta = math.cos(angle_rad)
sin_theta = math.sin(angle_rad)
for point in points:
rotated_x = center_x + (point[0] - center_x) * cos_theta - (point[1] - center_y) * sin_theta
rotated_y = center_y + (point[0] - center_x) * sin_theta + (point[1] - center_y) * cos_theta
vertices.append((rotated_x,rotated_y))

return vertices

根据输入的一组坐标点,中心点X、Y及旋转角度,完成对坐标点的转换,返回一组新的坐标点。

6.完成国旗的绘制

根据前面定义的函数,完成完整国旗的绘制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#画出大五角星
star0 = draw_star(width,height,0)
canvas.create_polygon(star0[0],outline='yellow',fill='yellow')
#画出第一颗小五角星
star1 = draw_star(width,height,1)
canvas.create_polygon(rotate_point(star1[0],star1[1],star1[2],-48.96),
outline='yellow',fill='yellow')
#画出第二颗小五角星
star2 = draw_star(width,height,2)
canvas.create_polygon(rotate_point(star2[0],star2[1],star2[2],-26.13),
outline='yellow',fill='yellow')
#画出第三颗小五角星
star3 = draw_star(width,height,3)
canvas.create_polygon(rotate_point(star3[0],star3[1],star3[2],-2.06),
outline='yellow',fill='yellow')
#画出第四颗小五角星
star4 = draw_star(width,height,4)
canvas.create_polygon(rotate_point(star4[0],star4[1],star4[2],20.66),
outline='yellow',fill='yellow')

完整代码

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# 生成一面五星红旗,修改width跟height可以,画不同规格的红旗

import tkinter as tk
import math

width = 660
height = 440

window = tk.Tk()
canvas = tk.Canvas(width=width, height=height)
canvas.pack()
window.title("五星红旗")


def get_coordinates(width,height,star_type=0):
"""根据传入的宽、高,返回一组坐标
star_type中的0表示返回的为大五角星的中心点坐标,
1-4分别为从上到下的4颗小五角星坐标
"""
# 反回中心点坐标及半径
if star_type == 0:
center_x = width/2 - (width/30*10)
center_y = height/2 - (height/20*5)
r = (width / 30) *3
return center_x, center_y, r
elif star_type == 1:
center_x = width/2 - (width/30*5)
center_y = height/2 - (height/20*8)
r = (width / 30) *1
return center_x, center_y, r
elif star_type == 2:
center_x = width/2 - (width/30*3)
center_y = height/2 - (height/20*6)
r = (width / 30) *1
return center_x, center_y, r
elif star_type == 3:
center_x = width/2 - (width/30*3)
center_y = height/2 - (height/20*3)
r = (width / 30) *1
return center_x, center_y, r
elif star_type == 4:
center_x = width/2 - (width/30*5)
center_y = height/2 - (height/20*1)
r = (width / 30) *1
return center_x, center_y, r

def draw_rectangle(width,height):
"""根据传入的长、宽画出旗面"""
# 确定中心点坐标
x = width / 2
y = height / 2
# 画出红旗的矩形
canvas.create_rectangle(x-(width/2),y-(height/2),x+(width/2),y+(height/2),outline='red',fill='red')

draw_rectangle(width,height)

def draw_star(x,y,star_type=0):
"""根据传入的长、宽及返回五角星的5个点坐标"""
# 确定中心点坐标及半径
tem = get_coordinates(x,y,star_type)
center_x = tem[0]
center_y = tem[1]
r = tem[2]

points=[
# 左上点
(center_x-r*math.sin(2*math.pi/5),
center_y-r*math.cos(2*math.pi/5)),

# 右上点
(center_x+r*math.sin(2*math.pi/5),
center_y-r*math.cos(2*math.pi/5)),

# 左下点
(center_x-r*math.sin(math.pi/5),
center_y+r*math.cos(math.pi/5)),

# 顶点
(center_x,
center_y-r),

# 右下点
(center_x+r*math.sin(math.pi/5),
center_y+r*math.cos(math.pi/5)),
]
#返回5个点的坐标组列表,中心点x、y坐标值及半径
return points,center_x,center_y,r

def rotate_point(points, center_x, center_y, angle):
"""对一组点进行旋转换算"""
vertices = []
#对小五角星进行旋转
angle_rad = math.radians(angle)
cos_theta = math.cos(angle_rad)
sin_theta = math.sin(angle_rad)
for point in points:
rotated_x = center_x + (point[0] - center_x) * cos_theta - (point[1] - center_y) * sin_theta
rotated_y = center_y + (point[0] - center_x) * sin_theta + (point[1] - center_y) * cos_theta
vertices.append((rotated_x,rotated_y))

return vertices



#画出大五角星
star0 = draw_star(width,height,0)
canvas.create_polygon(star0[0],outline='yellow',fill='yellow')
#画出第一颗小五角星
star1 = draw_star(width,height,1)
canvas.create_polygon(rotate_point(star1[0],star1[1],star1[2],-48.96),
outline='yellow',fill='yellow')
#画出第二颗小五角星
star2 = draw_star(width,height,2)
canvas.create_polygon(rotate_point(star2[0],star2[1],star2[2],-26.13),
outline='yellow',fill='yellow')
#画出第三颗小五角星
star3 = draw_star(width,height,3)
canvas.create_polygon(rotate_point(star3[0],star3[1],star3[2],-2.06),
outline='yellow',fill='yellow')
#画出第四颗小五角星
star4 = draw_star(width,height,4)
canvas.create_polygon(rotate_point(star4[0],star4[1],star4[2],20.66),
outline='yellow',fill='yellow')

window.mainloop()

python画国旗-五星红旗
http://www.okko.tk/2023/06/12/python画国旗-五星红旗/
作者
ZhJy
发布于
2023年6月12日
许可协议