光栅图形学(2)配套Python画图代码

Note

本文为 从零学习软渲(2)-中点画线算法 数学插图的配图代码

虽然是配套代码,但是学到的东西还是很多。如,绘制坐标,绘制坐标网格,绘制基础图例,绘制散点图等

 

 

# -- coding: utf-8 --
import matplotlib.pyplot as plt
import numpy as np
import math

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号


# m >= 0 && m <= 1
def f1(x):
    return 0.3 * x + 1.4


def draw_line_point_f1(_from, _to, func):
    x = np.linspace(_from, _to, 5)
    y = func(x)
    plt.plot(x, y)

    count = _to - _from
    i = 0
    while i < count:
        mx = i + _from + 1
        my = math.floor(func(mx)) + 0.5
        pfloor = math.floor(my)
        pceil = math.ceil(my)
        if my > func(mx):
            dest_point, alternative_point = pfloor, pceil
        else:
            dest_point, alternative_point = pceil, pfloor
        plt.scatter(mx, my, color='b')
        plt.scatter(mx, dest_point, color='r')
        plt.scatter(mx, alternative_point, edgecolors='r', facecolors='none')  # 绘制可选择点
        i += 1
    # end while

    # 绘制起始点
    draw_piont_with_annotate(_from, func(_from), _from, func(_from) + 1, 'P1')
    # 绘制终止点
    draw_piont_with_annotate(_to, func(_to), _to - 1, func(_to - 4), 'P2')


# m > 1
def f2(y):
    return (y + 1.2) / 1.6  # y = 1.6 * x - 1.2, 即y=kx+b的反函数


def draw_line_point_f2(_from, _to, func):
    y = np.linspace(_from, _to, 5)
    x = func(y)
    plt.plot(x, y)

    count = _to - _from
    i = 0
    while i < count:
        my = i + _from + 1
        mx = math.floor(func(my)) + 0.5
        pfloor = math.floor(mx)
        pceil = math.ceil(mx)
        if mx > func(my):
            dest_point, alternative_point = pfloor, pceil
        else:
            dest_point, alternative_point = pceil, pfloor
        plt.scatter(mx, my, color='b')  # 绘制中点
        plt.scatter(dest_point, my, color='r')  # 绘制目标点
        plt.scatter(alternative_point, my, edgecolors='r', facecolors='none')  # 绘制可选择点
        i += 1
    # end while

    # 绘制起始点
    draw_piont_with_annotate(func(_from), _from, func(_from + 1.8), _from, 'P1')
    # 绘制终止点
    draw_piont_with_annotate(func(_to), _to, func(_to), _to - 1, 'P2')


def draw_piont_with_annotate(px, py, tx, ty, label):
    plt.scatter(px, py, color='g')
    plt.annotate(s='{0}({1},{2})'.format(label, px, py), xy=(px, py), xytext=(tx, ty), arrowprops={'arrowstyle': '->'})


def draw_line(pfrom, pto, func, draw_point_func):
    _from = pfrom
    _to = pto

    # 设置坐标轴
    plt.xlim(1.5, 7.5)
    plt.ylim(1.5, 7.5)
    plt.xlabel('x', fontsize=16)
    plt.ylabel('y', fontsize=16, rotation='horizontal')
    plt.xticks(np.arange(2, 8, 1))
    plt.yticks(np.arange(2, 8, 1))

    # 绘制理想直线
    # 绘制中点和目标点
    draw_point_func(_from, _to, func)

    # 绘制图例
    plt.legend(["理想直线", "中点", "目标点", "可选择点"])
    plt.grid(alpha=0.7)


def hidden_right_top_spine(ax):
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')


def set_gca_title(title):
    plt.gca().set_title(title)


def draw_by_subplot():
    plt.figure(figsize=(12, 5))
    plt.subplot(1, 2, 1)
    set_gca_title('0 <= m <= 1')
    draw_line(2, 7, f1, draw_line_point_f1)

    plt.subplot(1, 2, 2)
    set_gca_title('m > 1')
    draw_line(2, 6, f2, draw_line_point_f2)
    plt.show()


def draw_by_multi_figure():
    plt.figure(figsize=(6, 5))
    set_gca_title('0 <= m <= 1')
    draw_line(2, 7, f1, draw_line_point_f1)

    plt.figure(figsize=(6, 5))
    set_gca_title('m > 1')
    draw_line(2, 6, f2, draw_line_point_f2)
    plt.show()


def main():
    draw_by_multi_figure()
    # draw_by_subplot()


if __name__ == '__main__':
    main()
点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像