Как обновить текст в каждом кадре в этом коде? - PullRequest
1 голос
/ 06 марта 2019

Я написал код на Python для анимации «Стереографической проекции» из Cicle на линию Real. Я определил три функции с именами update_plot(), update_texts() и create_animation(). (Как показано в коде ниже). Теперь для анимации я должен передать первые две функции в animation.FuncAnimation(). Поэтому я пытаюсь создать и очистить список с именами anim = [] и append() двумя объектами анимации к нему. Теперь анимация, соответствующая функции update_plot(), в порядке, но update_texts() работает не так, как я ожидал. На самом деле я хочу обновить координаты точек (R_x, R_y) (приведенные в определении update_text) в каждом кадре.

Я не могу понять, как решить эту проблему. Пожалуйста помоги. Спасибо.

Я также приложил изображение момента вывода следующего кода.

Мой код:

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation

W = 3
H = 1.2


mpl.rc('text', usetex=True)
mpl.rc('font', family='serif')

plt.style.use(['ggplot', 'dark_background'])


def create_circle(x, y):
    circle = plt.Circle((x, y), radius=1, fill=False,
                        edgecolor='skyblue', lw=2)
    return circle


def stereo_project(p):
    x = p[0]
    y = p[1]

    # transformation
    x1 = x / (1 - y)
    y1 = 0

    return x1, y1


def rotate(p, angle):
    vec = np.array([p[0], p[1]]).reshape(2, 1)

    theta = angle
    R = np.array([[np.cos(theta), -np.sin(theta)],
                  [np.sin(theta), np.cos(theta)]])

    point = R.dot(vec)

    return point[0][0], point[1][0]


def update_plot(angle, plot, plot1, plot2, plot3):
    p = (0, 1)
    R_x, R_y = rotate(p, angle)
    SR_x, SR_y = stereo_project((R_x, R_y))
    x = [p[0], R_x]
    y = [p[1], R_y]
    x1 = [R_x, SR_x]
    y1 = [R_y, SR_y]
    plot.set_data(x, y)
    plot1.set_data(x1, y1)
    plot2.set_data([R_x], [R_y])
    plot3.set_data([SR_x], [SR_y])

    return plot, plot1


def update_texts(angle):
    p = (0, 1)
    R_x, R_y = rotate(p, angle)
    plt.text(R_x, R_y, '$({0:.2f}, {1:.2f})$'.format(R_x, R_y),
             horizontalalignment='right',
             verticalalignment='center', fontsize=15, color='orange')



def create_animation():

    fig = plt.figure()
    ax = plt.axes(xlim=(-W, W), ylim=(-H, H))

    plot = plt.plot([], [], '-o', markersize=5, color='c')[0]
    plot1 = plt.plot([], [], '-o', markersize=5, color='c')[0]
    plot2 = plt.plot([], [], '-o', markersize=5, color='m')[0]
    plot3 = plt.plot([], [], '-o', markersize=5, color='lime')[0]


    ax.set_aspect('equal')
    circle = create_circle(0, 0)
    ax.add_patch(circle)

    l1 = [-3, 3]
    l2 = [0, 0]
    plt.plot(l1, l2)

    title = 'Stereographic Projection: $\mathbf{S^{1}} \setminus \{(0, 1)\}$ ' \
            'to $\mathbf{R}$'
    plt.title(title, color='orange', y=1.09)
    plt.grid(False)
    plt.gca().spines['left'].set_visible(False)
    plt.gca().spines['top'].set_visible(False)
    plt.gca().spines['right'].set_visible(False)
    plt.gca().spines['bottom'].set_visible(False)
    plt.gca().set_xticks([])
    plt.gca().set_yticks([])

    anim = []
    anim.append(animation.FuncAnimation(fig, update_plot,
                                        fargs=(plot, plot1, plot2, plot3),
                                        frames=np.arange(0, 2 * np.pi, 0.01),
                                        interval=50, repeat=True))

    anim.append(animation.FuncAnimation(fig, update_texts,
                                        frames=np.arange(0, 2 * np.pi, 0.01),
                                        interval=50, repeat=True))



    plt.show()


if __name__ == '__main__':

    create_animation()

Выход. Output

1 Ответ

1 голос
/ 06 марта 2019

Текст - это artist, поэтому вы можете анимировать его, как и любой другой artist.

Итак, так же, как в вашем коде вы получаете дескриптор объекта Line2D, возвращенного из plt.plot, а затем обновляете строки с помощью set_data, вы можете получить дескриптор экземпляра text, созданного plt.text и обновите свою позицию и текст с помощью text.set_text и text.set_position.

Я также изменил ваш код для обработки обновления текста и строк в одной функции.

С этим я получил

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation

W = 3
H = 1.2


mpl.rc('text', usetex=True)
mpl.rc('font', family='serif')

plt.style.use(['ggplot', 'dark_background'])


def create_circle(x, y):
    circle = plt.Circle((x, y), radius=1, fill=False,
                        edgecolor='skyblue', lw=2)
    return circle


def stereo_project(p):
    x = p[0]
    y = p[1]

    # transformation
    x1 = x / (1 - y)
    y1 = 0

    return x1, y1


def rotate(p, angle):
    vec = np.array([p[0], p[1]]).reshape(2, 1)

    theta = angle
    R = np.array([[np.cos(theta), -np.sin(theta)],
                  [np.sin(theta), np.cos(theta)]])

    point = R.dot(vec)

    return point[0][0], point[1][0]


def update_plot(angle, text, plot, plot1, plot2, plot3):
    p = (0, 1)
    R_x, R_y = rotate(p, angle)
    SR_x, SR_y = stereo_project((R_x, R_y))
    x = [p[0], R_x]
    y = [p[1], R_y]
    x1 = [R_x, SR_x]
    y1 = [R_y, SR_y]
    plot.set_data(x, y)
    plot1.set_data(x1, y1)
    plot2.set_data([R_x], [R_y])
    plot3.set_data([SR_x], [SR_y])

    R_x, R_y = rotate(p, angle)
    text.set_text('$({0:.2f}, {1:.2f})$'.format(R_x, R_y))
    text.set_position((R_x, R_y))

    return text, plot, plot1



def create_animation():

    fig = plt.figure()
    ax = plt.axes(xlim=(-W, W), ylim=(-H, H))

    plot = plt.plot([], [], '-o', markersize=5, color='c')[0]
    plot1 = plt.plot([], [], '-o', markersize=5, color='c')[0]
    plot2 = plt.plot([], [], '-o', markersize=5, color='m')[0]
    plot3 = plt.plot([], [], '-o', markersize=5, color='lime')[0]


    ax.set_aspect('equal')
    circle = create_circle(0, 0)
    ax.add_patch(circle)

    l1 = [-3, 3]
    l2 = [0, 0]
    plt.plot(l1, l2)

    p = (0, 1)
    R_x, R_y = rotate(p, 0)
    text = plt.text(R_x, R_y, '$({0:.2f}, {1:.2f})$'.format(R_x, R_y),
             horizontalalignment='right',
             verticalalignment='center', fontsize=15, color='orange')

    title = 'Stereographic Projection: $\mathbf{S^{1}} \setminus \{(0, 1)\}$ ' \
            'to $\mathbf{R}$'
    plt.title(title, color='orange', y=1.09)
    plt.grid(False)
    plt.gca().spines['left'].set_visible(False)
    plt.gca().spines['top'].set_visible(False)
    plt.gca().spines['right'].set_visible(False)
    plt.gca().spines['bottom'].set_visible(False)
    plt.gca().set_xticks([])
    plt.gca().set_yticks([])

    anim = []
    anim.append(animation.FuncAnimation(fig, update_plot,
                                        fargs=(text, plot, plot1, plot2, plot3),
                                        frames=np.arange(0, 2 * np.pi, 0.01),
                                        interval=50, repeat=True))




    plt.show()


if __name__ == '__main__':

    create_animation()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...