Построение только в одном окне - PullRequest
0 голосов
/ 05 мая 2020

Я пишу код кривой Безье с Python, используя sympy и numpy. Я не могу знать, правильный ли код, потому что я не могу нарисовать все функции только в одном окне (рисунке) с помощью sympy. Решение кода - график буквы 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. Спасибо

1 Ответ

1 голос
/ 05 мая 2020

Чтобы построить несколько графиков вместе, sympy's 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, но график может легко использовать какой-либо фиксированный цвет.

bezier plot

Для работы с 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()

sympy's plot

...