【Python学习】趣味工具-绘制八卦
一、实现目标
本文旨在使用 Python 语言绘制出包含太极图案和八卦图形的完整太极八卦图。通过编程,实现对传统太极八卦图案的可视化展示,帮助读者了解 Python 绘图在复杂图形绘制方面的应用。
二、技术路线
选用 Python 的turtle库进行绘图。turtle库提供了丰富的绘图函数,以一种直观的方式模拟在画布上使用画笔进行绘制,通过控制画笔的移动、颜色、填充等操作,能够绘制出各种复杂的图形。我们将利用这些特性,通过编写一系列的函数,逐步构建出太极八卦图。
三、实现步骤
1. 初始化绘图环境
设置绘图窗口的标题、大小,并关闭绘图动画以加快绘图速度。
from turtle import *
def init_turtle():
"""初始化turtle绘图环境"""
title('太极八卦图')
setup(0.5, 0.5)
tracer(0)
2. 重置画笔
将画笔的属性(如粗细、颜色)设置为初始状态,并将画笔移动到原点。
def reset_pen():
"""重置画笔属性并回到原点"""
pensize(1)
pencolor('black')
penup()
home()
pendown()
3. 设置画笔偏移
根据绘制对象(太极或八卦)的不同,计算并设置画笔的起始位置,确保图形在画布上居中显示。
def offset(off_set, angle=0, mode='taiji'):
"""设置画笔偏移,初始化八卦和太极的画笔起始点,保持整体居中"""
# off_set太极时为大圆半径,八卦时要大于半径,否则会与太极重合。
# angle默认为0,mode默认为‘taiji’,画太极的时候,不需要设置,默认即可;画卦的时候angle=angl,mode=‘bagua’。
penup()
home() # 回到原点,朝向东
if mode == 'taiji': # 太极
right(90)
fd(off_set)
seth(0) # 朝向东
else: # 八卦
left(angle) # 每画一卦旋转45度的倍数,开始下一卦。
fd(off_set)
left(90)
pendown()
4. 绘制太极图
绘制太极图的大圆和内部的 S 形曲线,并进行填充。
在太极图的上下部分别绘制两个代表阴阳鱼眼睛的小圆。
def draw_taiji(radius, pen_size=2, color='black'):
"""绘制太极图"""
reset_pen() # 初始化画笔
pensize(pen_size)
pencolor(color)
offset(radius) # 画笔偏移至起始点
fillcolor('black') # 填充颜色
begin_fill() # 开始填充
circle(radius, 180) # 画大圆的半圆
circle(radius / 2, 180) # 画s型
circle(-radius / 2, 180) # 画s型
end_fill() # 结束填充
circle(-radius, 180) # 画大圆的另一半圆
# 上面小圆
draw_small_circle(radius * 0.7, -radius * 0.2, 'white')
# 下面小圆
draw_small_circle(-radius * 0.7, radius * 0.2, 'black')
def draw_small_circle(y_offset, radius, fill_color):
"""绘制太极图中的小圆"""
begin_fill()
fillcolor(fill_color)
penup()
home() # 返回原点,默认朝东
left(90)
fd(y_offset) # 初始化小圆画笔起始点
right(90)
pendown()
circle(radius)
end_fill()
reset_pen()
5. 绘制八卦图
遍历八卦列表,根据每个卦象的角度偏移,设置画笔的起始位置。
针对每个卦象中的每一条线,根据其类型(阳爻或阴爻)进行绘制。如果是文字标识,则在合适的位置进行绘制。
绘制完一条线后,移动画笔到下一条线的起始位置,准备绘制下一爻。
def draw_bagua(off_set, side, gua_list):
"""绘制八卦图"""
pensize(side / 2)
for j, gua in enumerate(gua_list): # 枚举八卦列表,获取元素和下标,下标拿来判断旋转多少度
angl = j * 45 # 偏移角度:0,45,90,135,180,225,270,315,360
reset_pen() # 初始化到原点
offset(off_set, angle=angl, mode='bagua') # 偏移到八卦画笔,此时画笔位于线段中间点,下面3行代码初始到线段开头
pencolor('white')
pensize(5)
bk(side / 2)
for i in gua: # 遍历每一卦的集合,1为阳也就是完整线段,0为阴,带断点的线段
draw_gua_line(i, side, j)
move_to_next_line(side)
def draw_gua_line(line_type, side, j):
"""绘制八卦中的一条线"""
pencolor('black')
if line_type == 1:
fd(side)
elif line_type == 0:
fd(side * (1 / 3))
penup()
fd(side * (1 / 3))
pendown()
fd(side * (1 / 3))
elif isinstance(line_type, str):
draw_gua_text(line_type, side, j)
def draw_gua_text(text, side, j):
"""在八卦中绘制文字"""
penup()
fd(side / 2)
pendown()
if isinstance(text, str):
if j <= 4:
write(text, align='center', font=('楷体', 15, "bold"))
else:
right(90)
fd(15)
write(text, align='center', font=('楷体', 15, "bold"))
def move_to_next_line(side):
"""移动画笔到下一条线的起始位置"""
penup()
bk(side / 2)
right(90)
fd(side / 2)
left(90)
bk(side / 2)
pendown()
6. 完整代码
from turtle import *
def init_turtle():
"""初始化turtle绘图环境"""
title('太极八卦图')
setup(0.5, 0.5)
tracer(0)
def reset_pen():
"""重置画笔属性并回到原点"""
pensize(1)
pencolor('black')
penup()
home()
pendown()
def offset(off_set, angle=0, mode='taiji'):
"""设置画笔偏移,初始化八卦和太极的画笔起始点,保持整体居中"""
# off_set太极时为大圆半径,八卦时要大于半径,否则会与太极重合。
# angle默认为0,mode默认为‘taiji’,画太极的时候,不需要设置,默认即可;画卦的时候angle=angl,mode=‘bagua’。
penup()
home() # 回到原点,朝向东
if mode == 'taiji': # 太极
right(90)
fd(off_set)
seth(0) # 朝向东
else: # 八卦
left(angle) # 每画一卦旋转45度的倍数,开始下一卦。
fd(off_set)
left(90)
pendown()
def draw_taiji(radius, pen_size=2, color='black'):
"""绘制太极图"""
reset_pen() # 初始化画笔
pensize(pen_size)
pencolor(color)
offset(radius) # 画笔偏移至起始点
fillcolor('black') # 填充颜色
begin_fill() # 开始填充
circle(radius, 180) # 画大圆的半圆
circle(radius / 2, 180) # 画s型
circle(-radius / 2, 180) # 画s型
end_fill() # 结束填充
circle(-radius, 180) # 画大圆的另一半圆
# 上面小圆
draw_small_circle(radius * 0.7, -radius * 0.2, 'white')
# 下面小圆
draw_small_circle(-radius * 0.7, radius * 0.2, 'black')
def draw_small_circle(y_offset, radius, fill_color):
"""绘制太极图中的小圆"""
begin_fill()
fillcolor(fill_color)
penup()
home() # 返回原点,默认朝东
left(90)
fd(y_offset) # 初始化小圆画笔起始点
right(90)
pendown()
circle(radius)
end_fill()
reset_pen()
def draw_bagua(off_set, side, gua_list):
"""绘制八卦图"""
pensize(side / 2)
for j, gua in enumerate(gua_list): # 枚举八卦列表,获取元素和下标,下标拿来判断旋转多少度
angl = j * 45 # 偏移角度:0,45,90,135,180,225,270,315,360
reset_pen() # 初始化到原点
offset(off_set, angle=angl, mode='bagua') # 偏移到八卦画笔,此时画笔位于线段中间点,下面3行代码初始到线段开头
pencolor('white')
pensize(5)
bk(side / 2)
for i in gua: # 遍历每一卦的集合,1为阳也就是完整线段,0为阴,带断点的线段
draw_gua_line(i, side, j)
move_to_next_line(side)
def draw_gua_line(line_type, side, j):
"""绘制八卦中的一条线"""
pencolor('black')
if line_type == 1:
fd(side)
elif line_type == 0:
fd(side * (1 / 3))
penup()
fd(side * (1 / 3))
pendown()
fd(side * (1 / 3))
elif isinstance(line_type, str):
draw_gua_text(line_type, side, j)
def draw_gua_text(text, side, j):
"""在八卦中绘制文字"""
penup()
fd(side / 2)
pendown()
if isinstance(text, str):
if j <= 4:
write(text, align='center', font=('楷体', 15, "bold"))
else:
right(90)
fd(15)
write(text, align='center', font=('楷体', 15, "bold"))
def move_to_next_line(side):
"""移动画笔到下一条线的起始位置"""
penup()
bk(side / 2)
right(90)
fd(side / 2)
left(90)
bk(side / 2)
pendown()
if __name__ == "__main__":
init_turtle()
taiji_list = [(1, 1, 0, '兑'), (0, 0, 0, '坤'), (1, 0, 1, '离'), (0, 1, 1, '巽'), (1, 0, 0, '震'), (0, 0, 1, '艮'),
(0, 1, 0, '坎'), (1, 1, 1, '乾')]
draw_taiji(50)
draw_bagua(70, 30, taiji_list)
hideturtle()
done()
四、总结
通过本次实践,我们成功使用 Python 的turtle库绘制出了太极八卦图。这一过程不仅加深了对turtle库绘图函数的理解和运用,还锻炼了将复杂图形拆解为多个简单绘图步骤的能力。希望读者能够通过本文,掌握turtle库的基本绘图技巧,并在今后的编程实践中,运用这些知识绘制出更多有趣和复杂的图形。
作者:西攻城狮北