Ripropongo un esercizio in Python simile a quello svolto in JavaScript in Simulazione sull’espansione del contagio da Coronavirus (COVID-19)
Questa volta utilizzeremo PyGame e OpenGL per costruire la simulazione, similmente a quanto fatto nel precedente articolo. Il programma è stato svolto in Python 3.9.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
import pygame as pg from pygame.locals import * from OpenGL.GL import * from OpenGL.GLU import * import math from copy import copy import random import matplotlib.pyplot as plt dati = [ {"infetto":False,"velocita":10,"numero":200}, {"infetto":False,"velocita":0,"numero":10}, {"infetto":True,"velocita":10,"numero":1} ] class Simulazione: def __init__(s, w = 1200, h = 800, dati = []): s.posizioni = [] s.ratio = w / h s.w = w s.h = h pg.init() schermo = (w,h) pg.display.set_mode(schermo, DOUBLEBUF|OPENGL) # in movimento for d in dati: for i in range(d["numero"]): x = random.randint(-w/2+10,w/2-10) y = random.randint(-h/2+10,h/2-10) a = 2*math.pi*random.random() s.posizioni.append(Punto(x,y,d["velocita"],a,infetto=d["infetto"])) infezioni = [] while True: for event in pg.event.get(): if event.type == pg.QUIT: pg.quit() quit() glClearColor(1.0, 1.0, 1.0, 1.0) glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) tot_infetti = 0 for p in s.posizioni: p.muovi() s.disegnaPunto(p.x,p.y,raggio=p.raggio,colore=p.colore) if p.infetto and not p.guarito: tot_infetti += 1 infezioni.append(tot_infetti) s.controllaUrti() pg.display.flip() pg.time.wait(10) if tot_infetti == 0: pg.quit() break plt.plot(range(len(infezioni)),infezioni) plt.title("curva contagi") plt.xlabel("periodo") plt.ylabel("contagi") plt.show() def controllaUrti(s): for p in s.posizioni: if copy(p) in s.posizioni: pass def disegnaPunto(s,x,y,lati=10,raggio=20,colore=(0.0, 0.0, 1.0)): raggio = 2 * raggio / s.w x = 2 * x / s.w y = 2 * y / s.h r,g,b = colore glColor3f(r,g,b) glBegin(GL_POLYGON) for v in range(lati): angolo = float(v) * 2.0 * math.pi / lati glVertex2f(math.cos(angolo)*raggio + x,math.sin(angolo)*raggio*s.ratio + y) glEnd() class Punto: def __init__(s,x,y,v=3,alfa=0,colore=(0.0, 0.0, 1.0),raggio=5,infetto=False): s.x = x s.y = y s.v = v s.alfa = alfa s.id = id(s) s.colore = colore s.raggio = raggio s.urtato = False s.guarito = False s.infetto = infetto s.durata_infezione = 120 # cicli def __eq__(s,o): if math.sqrt((s.x - o.x)**2+(s.y - o.y)**2) < s.raggio * 2 and s.id != o.id: salfa = s.alfa oalfa = o.alfa if (s.infetto and not s.guarito) or (o.infetto and not o.guarito): s.infetto = o.infetto = True if not s.urtato: s.urto(oalfa) if not o.urtato: o.urto(salfa) return True else: return False def muovi(s): s.urtato = False if s.infetto: s.durata_infezione -= 1 if s.durata_infezione < 0: s.guarito = True s.colore=(0.0, 1.0, 0.0) if s.infetto and not s.guarito: s.colore=(1.0, 0.0, 0.0) dx = s.v * math.cos(s.alfa) dy = s.v * math.sin(s.alfa) if s.x+dx >= 600 or s.x+dx <= -600: s.alfa = math.pi-s.alfa dx = s.v * math.cos(s.alfa) dy = s.v * math.sin(s.alfa) if s.y+dy >= 400 or s.y+dy <= -400: s.alfa = -s.alfa dx = s.v * math.cos(s.alfa) dy = s.v * math.sin(s.alfa) s.x += dx s.y += dy if s.x >= 600 or s.x <= -600 or s.y >= 400 or s.y <= -400: s.v = -s.v def urto(s,theta): s.alfa = s.alfa+theta s.urtato = True Simulazione(dati=dati) |
Il risultato produrrà qualcosa di simile a questo: