仅绘制一个 window

Plotting in only one window

我正在用 Python 使用 sympy 和 numpy 编写贝塞尔曲线代码。我不知道代码是否正确,因为我无法使用 sympy 在一个 window (图)中绘制所有函数。代码的解法是字母N的图形,这是代码:

#/usr/bin/env python3
# -*- coding: utf-8 -*-


import numpy as np
from sympy import symbols, lambdify
from sympy.plotting import plot_parametric


z = symbols('z')


def bezier(x, y, xx, yy, xxx, yyy):
    n = len(x)
    a_0 = np.empty(shape=n, dtype=float)
    a_1 = np.empty(shape=n, dtype=float)
    a_2 = np.empty(shape=n, dtype=float)
    a_3 = np.empty(shape=n, dtype=float)
    b_0 = np.empty(shape=n, dtype=float)
    b_1 = np.empty(shape=n, dtype=float)
    b_2 = np.empty(shape=n, dtype=float)
    b_3 = np.empty(shape=n, dtype=float)

    for i in np.arange(n - 1):
        a_0[i] = x[i]
        b_0[i] = y[i]
        a_1[i] = 3 * (xx[i] - x[i])
        b_1[i] = 3 * (yy[i] - y[i])
        a_2[i] = 3 * (x[i] + xxx[i + 1] - 2 * xx[i])
        b_2[i] = 3 * (y[i] + yyy[i + 1] - 2 * yy[i])
        a_3[i] = x[i + 1] - x[i] + 3 * xx[i] - 3 * xxx[i + 1]
        b_3[i] = y[i + 1] - y[i] + 3 * yy[i] - 3 * yyy[i + 1]
        P = a_0[i] + a_1[i] * z + a_2[i] * z ** 2 + a_3[i] * z ** 3
        Q = b_0[i] + b_1[i] * z + b_2[i] * z ** 2 + b_3[i] * z ** 3
        plot_parametric(P, Q, (z, 0, 1))

if __name__ == '__main__':
    x = np.array([3, 2, 6, 5, 6.5], dtype=float)
    y = np.array([6, 2, 6, 2, 3], dtype=float)
    xx = np.array([3.3, 2.8, 5.8, 5.5, np.nan], dtype=float)
    yy = np.array([6.5, 3, 5, 2, np.nan], dtype=float)
    xxx = np.array([np.nan, 2.5, 5, 4.5, 6.4], dtype=float)
    yyy = np.array([np.nan, 2.5, 5.8, 2.5, 2.8], dtype=float)
    bezier(x, y, xx, yy, xxx, yyy)

我使用的是 Numerycal Analysis-Burden & Faires-9th Edition 中的伪代码我不介意解决方案是否使用 Matplotlib。 谢谢

为了将多个地块绘制在一起,sympy 的 plotting 有一个使用 plot_parametric(..., show=False) 的机制。用您的代码测试它会产生空图。原因是 sympy 不会自动设置 x 和 y 轴的限制。它们可以显式添加:plot_parametric(P, Q, (z, 0, 1), xlim=(1,7), ylim=(1,7), show=False).

直接使用 numpy 和 matplotlib,您的代码会生成一些曲线,形成 'N':

import numpy as np
import matplotlib.pyplot as plt

def bezier(x, y, xx, yy, xxx, yyy):
    z = np.linspace(0, 1, 200)
    for i in range(len(x)-1):
        a_0 = x[i]
        b_0 = y[i]
        a_1 = 3 * (xx[i] - x[i])
        b_1 = 3 * (yy[i] - y[i])
        a_2 = 3 * (x[i] + xxx[i + 1] - 2 * xx[i])
        b_2 = 3 * (y[i] + yyy[i + 1] - 2 * yy[i])
        a_3 = x[i + 1] - x[i] + 3 * xx[i] - 3 * xxx[i + 1]
        b_3 = y[i + 1] - y[i] + 3 * yy[i] - 3 * yyy[i + 1]
        P = a_0  + a_1  * z + a_2  * z ** 2 + a_3  * z ** 3
        Q = b_0  + b_1  * z + b_2  * z ** 2 + b_3  * z ** 3
        plt.plot(P, Q)

if __name__ == '__main__':
    x = np.array([3, 2, 6, 5, 6.5], dtype=float)
    y = np.array([6, 2, 6, 2, 3], dtype=float)
    xx = np.array([3.3, 2.8, 5.8, 5.5, np.nan], dtype=float)
    yy = np.array([6.5, 3, 5, 2, np.nan], dtype=float)
    xxx = np.array([np.nan, 2.5, 5, 4.5, 6.4], dtype=float)
    yyy = np.array([np.nan, 2.5, 5.8, 2.5, 2.8], dtype=float)
    bezier(x, y, xx, yy, xxx, yyy)

颜色是默认的 matplotlib 颜色序列,但绘图可以轻松使用一些固定颜色。

要使用 sympy,show=False 可以合并为:

def bezier(x, y, xx, yy, xxx, yyy):
    z = symbols('z')
    for i in range(len(x)-1):
        a_0 = x[i]
        b_0 = y[i]
        a_1 = 3 * (xx[i] - x[i])
        b_1 = 3 * (yy[i] - y[i])
        a_2 = 3 * (x[i] + xxx[i + 1] - 2 * xx[i])
        b_2 = 3 * (y[i] + yyy[i + 1] - 2 * yy[i])
        a_3 = x[i + 1] - x[i] + 3 * xx[i] - 3 * xxx[i + 1]
        b_3 = y[i + 1] - y[i] + 3 * yy[i] - 3 * yyy[i + 1]
        P = a_0  + a_1  * z + a_2  * z ** 2 + a_3  * z ** 3
        Q = b_0  + b_1  * z + b_2  * z ** 2 + b_3  * z ** 3
        plot_i = plot_parametric(P, Q, (z, 0, 1), xlim=(1, 7), ylim=(1, 7), show=False)
        if i == 0:
            all_plots = plot_i
        else:
            all_plots.append(plot_i[0])
    all_plots.show()