动画移动点

时间:2016-02-26 17:51:03

标签: python python-3.x matplotlib

我需要为随机移动的点/绘图设置动画,直到它穿过圆圈,然后它会保持不变。理想情况下,将有几个点,当最终在圆上时,将均匀地分布在所述圆上。 我已经看过使用matplotlib和matplotlib.animate的代码,它们动画了一个函数的图形,但我无法完全理解它们。

谢谢你的时间!

编辑: This is what it would look like with one dot

And with several dots

1 个答案:

答案 0 :(得分:2)

我从来没有在Python中制作过任何动画,所以我虽然可以学到新的东西,并且编写了以下代码来动画点,所以它会随机移动。也许它会帮助你开始你的任务。该代码基于matplotlib-animation-tutorial

编辑:我有一段很长的火车旅行,我已经实施了你要求的东西。你这里有一堆随机移动的点。一旦他们进入蓝色圆圈,他们会尝试最大化它们之间的距离,所以过了一会儿它看起来像你想要的。

"""
Matplotlib Animation Example

author: Jake Vanderplas
email: vanderplas@astro.washington.edu
website: http://jakevdp.github.com
license: BSD
Please feel free to use and modify this, but keep the above information. Thanks!
"""
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import math

# Initializing number of dots
N = 25


# Creating dot class
class dot(object):
    def __init__(self):
        self.x = 10 * np.random.random_sample()
        self.y = 10 * np.random.random_sample()
        self.velx = self.generate_new_vel()
        self.vely = self.generate_new_vel()

    def generate_new_vel(self):
        return (np.random.random_sample() - 0.5) / 5

    def move(self):
        def distance(x1, y1, x2, y2):
            return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)

        def inside(x1, y1):
            if distance(x1, y1, 5, 5) <= 1:
                return True
            else:
                return False

        def calc_dist(d):
            ret = 0
            for x in dots:
                if inside(x.x, x.y) and x != d:                            
                    ret = ret + distance(x.x, x.y, d.x, d.y)
            return ret

        # if dot is inside the circle it tries to maximize the distances to
        # other dots inside circle
        if inside(self.x, self.y):
            dist = calc_dist(self)
            for i in xrange(1, 10):
                self.velx = self.generate_new_vel()
                self.vely = self.generate_new_vel()
                self.x = self.x + self.velx
                self.y = self.y + self.vely
                if calc_dist(self) <= dist or not inside(self.x, self.y):
                    self.x = self.x - self.velx
                    self.y = self.y - self.vely
        else:
            if np.random.random_sample() < 0.95:
                self.x = self.x + self.velx
                self.y = self.y + self.vely
            else:
                self.velx = self.generate_new_vel()
                self.vely = self.generate_new_vel()
                self.x = self.x + self.velx
                self.y = self.y + self.vely
            if self.x >= 10:
                self.x = 10
                self.velx = -1 * self.velx
            if self.x <= 0:
                self.x = 0
                self.velx = -1 * self.velx
            if self.y >= 10:
                self.y = 10
                self.vely = -1 * self.vely
            if self.y <= 0:
                self.y = 0
                self.vely = -1 * self.vely

# Initializing dots
dots = [dot() for i in xrange(N)]

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 10), ylim=(0, 10))
d, = ax.plot([dot.x for dot in dots],
             [dot.y for dot in dots], 'ro')
circle = plt.Circle((5, 5), 1, color='b', fill=False)
ax.add_artist(circle)


# animation function.  This is called sequentially
def animate(i):
    for dot in dots:
        dot.move()
    d.set_data([dot.x for dot in dots],
               [dot.y for dot in dots])
    return d,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, frames=200, interval=20)

plt.show()