我有这个任务:使用极坐标创建一个心形动画。从画一颗心开始,然后添加动画作为下一步;使用渲染角度的可变增加。 然后我需要以同样的方式在极坐标中构建其他图形。 我还需要将绘图功能与图形分开,这样就可以用最少的代码更改来更改图形
我尝试运行这个,输出看起来很奇怪,当我改变 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()
您似乎使用了错误的半径表达式。您的半径与 theta 的平方成正比,并且随着 theta 的增加而变得非常负,这无法在极坐标图中表示。您很可能缺少正弦或余弦。玩了一下,我发现
r = 1 - (np.abs(np.cos(theta)) - 1) ** 2
可以产生心形。
一般来说,计算 theta 和 r(极坐标图的坐标),然后对图进行诸如笛卡尔坐标(x_极坐标和 y_极坐标)转换之类的操作,这对我来说似乎很奇怪。
关于分离问题,将半径的计算移出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添加了一个函数,即“心脏曲线”,作为准备多个函数的示例。
我又写了一个代码:
# 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 数组中的点数以获得更好的平滑线)
将您编写代码的方式更改为我的...我希望这会有所帮助!