matplotlib 极轴动画

2admgd59  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(99)

我有这个任务:使用极坐标创建一个心脏动画。从绘制心脏开始,然后添加动画作为下一步;使用渲染Angular 的可变增加。然后我需要以同样的方式在极坐标中构建其他图形。我还需要将绘图功能与图形分开,以便可以以最小的代码更改更改图形
我试着运行这个,把输出看起来真的很奇怪,其他数字看起来不像预期当我改变theta和r.我不知道是否有可能完成这个任务使用tkinter或pygame或类似的东西.我会很高兴,如果你能想出任何想法来完成这个.

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

fig = plt.figure()
ax = fig.add_subplot(111, polar=True)

theta = np.linspace(0, 2*np.pi, 100)
r = 1 - (np.abs(theta) - 1) ** 2

line, = ax.plot([], [], color='red')

def init():
    line.set_data([], [])
    return line,

def animate(i):
    current_theta = theta[:i]
    current_r = r[:i]
    x_polar = current_r * np.cos(current_theta)
    y_polar = current_r * np.sin(current_theta)
    line.set_data(x_polar, y_polar)
    return line,

ani = animation.FuncAnimation(fig, animate, init_func=init, frames=len(theta), interval=50, blit=True)

plt.show()
ne5o7dgx

ne5o7dgx1#

看起来你使用了错误的半径表达式。你的半径与θ的平方成正比,并且随着θ的增加而变得非常负,这在极坐标图中无法表示。最有可能的是,你缺少正弦或余弦。玩了一会儿,我发现r = 1 - (np.abs(np.cos(theta)) - 1) ** 2产生了一个心形。
一般来说,我觉得计算theta和r很奇怪,这是一个极坐标图的坐标,然后为你的图做一个类似于笛卡尔坐标(x_polar和y_polar)的变换。
关于分离问题,将半径的计算从animate函数中移出。animate函数应该只负责更新图:

def heart(theta):
    return 1 - (np.abs(np.cos(theta)) - 1) ** 2

def cardiod(theta):
    return 0.5 * (1 - np.sin(theta))

theta = np.linspace(0, 2*np.pi, 100)
r = heart(theta)

# transformation needed for your example
theta, r = r * np.cos(theta), r * np.sin(theta)

# test of the cardiod function; this function does not need any transformation afterwards
# r = cardiod(theta)

def animate(i):
    current_theta = theta[:i]
    current_r = r[:i]
    line.set_data(current_theta, current_r)
    return line,

我为Cardioid on Wikipedia添加了一个函数,即“心脏曲线”,作为准备多个函数的示例。

zbdgwd5y

zbdgwd5y2#

我又写了一段代码:

# Import modules
import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib.animation import FuncAnimation
# ------------------------------------------ #
  
# Define the figure
fig = plt.figure(figsize=(16,16))
# Setting the axes projection as polar 
ax = fig.add_subplot(111, projection='polar')

# Define the heart equation from https://pavpanchekha.com/blog/heart-polar-coordinates.html
t = np.linspace(0.0, 2.0*np.pi, 200, endpoint=True)
r = np.sin(t)*np.sqrt(np.abs(np.cos(t))) / (np.sin(t) + 7/5) - 2*np.sin(t) + 2

# Define a list that stores temporary data points
# [[theta], [radius]]
data_points = [[], []]

# Define the index of the last data point that needs to be plotted
# For example, if index = 5, data_points[0][-1] = t[5] and data_points[1][-1] = r[5]
index = 0

def animate(i):
     # Global variables
     global data_points, index

     # Clear the plot
     ax.clear()

     # Remove tick labels
     ax.set_xticklabels([])
     ax.set_yticklabels([])

     # Append a data point to the list
     data_points[0].append(t[index])
     data_points[1].append(r[index])

     # Update the index
     index += 1

     # Reset the index and points 
     # if index is out of range
     if (index == len(t)):
          index = 0
          data_points = [[], []]
          
     # Plot the "heart"
     plt.plot(data_points[0], data_points[1], color="red")

     # Define the limits
     ax.set_rlim(min(r), max(r))

     # Remove border
     #ax.axis("off")

# Calling the animation function
ani1 = FuncAnimation(fig, animate, interval=30)

# Display the plot
plt.show()

这将产生:(您必须增加theta数组中的点数以获得更平滑的线)

把你写代码的方式改成我写的..

x4shl7ld

x4shl7ld3#

如果你看Desmos(link)上的图,你会发现直到pi/2,图看起来都很好,但是pi/2之后的尾端不是你想要的。所以,你需要做的第一件事是绘制从0到pi/2的theta。
你还想绘制另一半在x轴上的反射。y=f(-x)在x轴上反射f(x)。我们可以通过像在循环中一样将极坐标转换为carnival来实现这一点,然后创建点的x向量作为x坐标和负x坐标。y向量只是y坐标的两倍。为了确保绘图平滑,你会想要反转第二组点(对于x和y),这样它就不会在原点重新开始。
下面的代码做了我所描述的,我已经把代码绘制成极坐标或笛卡尔坐标。

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

plt.close("all")

fig, ax = plt.subplots(subplot_kw=dict(projection="polar"))

theta = np.linspace(0, np.pi/2, 100)
r = 1 - (np.abs(theta) - 1) ** 2
x = r*np.cos(theta)
y = r*np.sin(theta)

x_data = np.concatenate((x, -x[::-1]))
y_data = np.concatenate((y, y[::-1]))

r_data = np.sqrt(x_data**2 + y_data**2)
theta_data = np.arctan2(y_data, x_data)

line, = ax.plot([], [], color='red')

def init():
    line.set_data([], [])
    return line,

def animate(i):
    # line.set_data(x_data[:i], y_data[:i])           # cartesian
    line.set_data(theta_data[:i], r_data[:i])       # polar
    return line,

ani = animation.FuncAnimation(fig, animate, init_func=init, frames=len(x_data), interval=10, blit=True)
plt.show()

极轴动画:

笛卡尔动画:

相关问题