【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绘制八卦

四、总结

通过本次实践,我们成功使用 Python 的turtle库绘制出了太极八卦图。这一过程不仅加深了对turtle库绘图函数的理解和运用,还锻炼了将复杂图形拆解为多个简单绘图步骤的能力。希望读者能够通过本文,掌握turtle库的基本绘图技巧,并在今后的编程实践中,运用这些知识绘制出更多有趣和复杂的图形。

作者:西攻城狮北

物联沃分享整理
物联沃-IOTWORD物联网 » 【Python学习】趣味工具-绘制八卦

发表回复