马角乌白网

仿真鸟群-Python实现(Win11)

仿真鸟群-Python实现(Win11)

参考书籍《Python极客项目编程》。鸟群

运行环境

操作系统Win11。实现

Python 3.10.5。鸟群

电脑连接互联网。实现

安装相关包

在命令行窗口使用pip命令(我的鸟群电脑上,“pip.exe”文件所在目录是实现“D:\Programs\Python\Python310\Scripts”)安装numpy、matplotlib、鸟群scipy等相关包,实现命令如下:

pip install numpy

pip install matplotlib

pip install scipy

并根据提示使用如下命令升级:

D:\Programs\Python\Python310\python.exe -m pip install --upgrade pip

安装包相关信息的鸟群查看(以numpy为例)

启动python,进入python提示符,实现依次键入import numpy、鸟群print(numpy)、实现dir(numpy);或者help()、鸟群numpy,实现显示该模块的鸟群相关信息。(help(numpy)也可以)。

 

源代码

源代码网址: pp/boids.py at master · electronut/pp · GitHub 

源代码如下:

"""boids.pyImplementation of Craig Reynold's BOIDsAuthor: Mahesh Venkitachalam"""import sys, argparseimport mathimport numpy as npimport matplotlib.pyplot as pltimport matplotlib.animation as animationfrom scipy.spatial.distance import squareform, pdist, cdistfrom numpy.linalg import normwidth, height = 640, 480class Boids:    """Class that represents Boids simulation"""    def __init__(self, N):        """ initialize the Boid simulation"""        # init position & velocities        self.pos = [width/2.0, height/2.0] + 10*np.random.rand(2*N).reshape(N, 2)        # normalized random velocities        angles = 2*math.pi*np.random.rand(N)        self.vel = np.array(list(zip(np.sin(angles), np.cos(angles))))        self.N = N        # min dist of approach        self.minDist = 25.0        # max magnitude of velocities calculated by "rules"        self.maxRuleVel = 0.03        # max maginitude of final velocity        self.maxVel = 2.0    def tick(self, frameNum, pts, beak):        """Update the simulation by one time step."""        # get pairwise distances        self.distMatrix = squareform(pdist(self.pos))        # apply rules:        self.vel += self.applyRules()        self.limit(self.vel, self.maxVel)        self.pos += self.vel        self.applyBC()        # update data        pts.set_data(self.pos.reshape(2*self.N)[::2],                     self.pos.reshape(2*self.N)[1::2])        vec = self.pos + 10*self.vel/self.maxVel        beak.set_data(vec.reshape(2*self.N)[::2],                      vec.reshape(2*self.N)[1::2])    def limitVec(self, vec, maxVal):        """limit magnitide of 2D vector"""        mag = norm(vec)        if mag >maxVal:            vec[0], vec[1] = vec[0]*maxVal/mag, vec[1]*maxVal/mag        def limit(self, X, maxVal):        """limit magnitide of 2D vectors in array X to maxValue"""        for vec in X:            self.limitVec(vec, maxVal)                def applyBC(self):        """apply boundary conditions"""        deltaR = 2.0        for coord in self.pos:            if coord[0] >width + deltaR:                coord[0] = - deltaR            if coord[0] < - deltaR:                coord[0] = width + deltaR                if coord[1] >height + deltaR:                coord[1] = - deltaR            if coord[1] < - deltaR:                coord[1] = height + deltaR        def applyRules(self):        # apply rule #1 - Separation        D = self.distMatrix < 25.0        vel = self.pos*D.sum(axis=1).reshape(self.N, 1) - D.dot(self.pos)        self.limit(vel, self.maxRuleVel)        # different distance threshold        D = self.distMatrix < 50.0        # apply rule #2 - Alignment        vel2 = D.dot(self.vel)        self.limit(vel2, self.maxRuleVel)        vel += vel2;        # apply rule #1 - Cohesion        vel3 = D.dot(self.pos) - self.pos        self.limit(vel3, self.maxRuleVel)        vel += vel3        return vel    def buttonPress(self, event):        """event handler for matplotlib button presses"""        # left click - add a boid        if event.button is 1:            self.pos = np.concatenate((self.pos,                                       np.array([[event.xdata, event.ydata]])),                                      axis=0)            # random velocity            angles = 2*math.pi*np.random.rand(1)            v = np.array(list(zip(np.sin(angles), np.cos(angles))))            self.vel = np.concatenate((self.vel, v), axis=0)            self.N += 1        # right click - scatter        elif event.button is 3:            # add scattering velocity            self.vel += 0.1*(self.pos - np.array([[event.xdata, event.ydata]]))        def tick(frameNum, pts, beak, boids):    #print frameNum    """update function for animation"""    boids.tick(frameNum, pts, beak)    return pts, beak# main() functiondef main():  # use sys.argv if needed  print('starting boids...')  parser = argparse.ArgumentParser(description="Implementing Craig Reynold's Boids...")  # add arguments  parser.add_argument('--num-boids', dest='N', required=False)  args = parser.parse_args()  # number of boids  N = 100  if args.N:      N = int(args.N)  # create boids  boids = Boids(N)  # setup plot  fig = plt.figure()  ax = plt.axes(xlim=(0, width), ylim=(0, height))  pts, = ax.plot([], [], markersize=10,                  c='k', marker='o', ls='None')  beak, = ax.plot([], [], markersize=4,                  c='r', marker='o', ls='None')  anim = animation.FuncAnimation(fig, tick, fargs=(pts, beak, boids),                                 interval=50)  # add a "button press" event handler  cid = fig.canvas.mpl_connect('button_press_event', boids.buttonPress)  plt.show()# call mainif __name__ == '__main__':  main()

运行结果

将上述代码保存为文件“d:\temp\boids.py”。

在命令行窗口执行命令 “python d:\temp\boids.py”,运行结果如下:

 

 

 

未经允许不得转载:马角乌白网 » 仿真鸟群-Python实现(Win11)