#------------------------------------------------------------------------------ # Animazione curve di Bezier cubiche con scia # By Claudio Fin novembre 2008 #------------------------------------------------------------------------------ import Image, ImageTk, Tkinter, ImageDraw, random WSC,HSC=640,480 # dimensioni area grafica ANELLI=10 # numero di anelli visualizzati da 1 a N (scia) RETTE=10 # numero di tensori colineari e curve, da 2 a N TENSORI=0 # 1=visualizza i tensori e i punti di tangenza PUNTI=50 # numero di punti in ogni curva PILD=0 # 1=usa immagine PIL INK="cyan" # colore linee PAPER="black" # colore fondo def main(): global bez bez=Tbez() crea_grafica() animazione() form1.mainloop() PILD and img.save("bezier.png") def crea_grafica(): global canvas1, img, im, drw, form1 img=Image.new("RGB",(WSC,HSC),PAPER) # crea oggetto immagine PIL drw=ImageDraw.Draw(img) # crea oggetto tracciatore grafico PIL form1=Tkinter.Tk() canvas1=Tkinter.Canvas(form1,width=WSC,height=HSC,bg=PAPER) canvas1.grid(column=0,row=0) im=ImageTk.PhotoImage(img) canvas1.create_image(2,2,image=im,anchor="nw") def animazione(): global im form1.after(60,animazione) bez.calcola() if PILD: drw.rectangle((0,0,WSC,HSC),fill=PAPER) TENSORI and draw_tensori_pil() for j in range(len(bez.g)): for i in range(RETTE): drw.line(bez.g[j][i],fill=INK) im=ImageTk.PhotoImage(img) canvas1.create_image(2,2,image=im,anchor="nw") else: canvas1.delete("all") TENSORI and draw_tensori_tk() for j in range(len(bez.g)): for i in range(RETTE): canvas1.create_line(bez.g[j][i],fill=INK) def draw_tensori_pil(): for i in range(RETTE): drw.line((bez.r[i].x0, bez.r[i].y0, \ bez.r[i].x1, bez.r[i].y1), \ fill="#CCCCCC") drw.rectangle((bez.r[i].x0-2, bez.r[i].y0-2, \ bez.r[i].x0+2, bez.r[i].y0+2), \ fill="#CCCCCC",outline="black") drw.rectangle((bez.r[i].x1-2, bez.r[i].y1-2, \ bez.r[i].x1+2, bez.r[i].y1+2), \ fill="#CCCCCC",outline="black") drw.ellipse((bez.r[i].mx-2, bez.r[i].my-2, \ bez.r[i].mx+2, bez.r[i].my+2), \ fill="red",outline="black") def draw_tensori_tk(): for i in range(RETTE): canvas1.create_line((bez.r[i].x0, bez.r[i].y0, \ bez.r[i].x1, bez.r[i].y1), \ fill="#CCCCCC") canvas1.create_rectangle((bez.r[i].x0-2, bez.r[i].y0-2, \ bez.r[i].x0+2, bez.r[i].y0+2), \ fill="#CCCCCC") canvas1.create_rectangle((bez.r[i].x1-2, bez.r[i].y1-2, \ bez.r[i].x1+2, bez.r[i].y1+2), \ fill="#CCCCCC") canvas1.create_oval((bez.r[i].mx-2, bez.r[i].my-2, \ bez.r[i].mx+2, bez.r[i].my+2), \ fill="red") def randxpos(): return random.randint(0,WSC) def randypos(): return random.randint(0,HSC) def randvelx(): d=round(WSC*0.03) v=0 while v==0: v=random.randint(2,d) return v def randvely(): d=round(HSC*0.03) v=0 while v==0: v=random.randint(2,d) return v class Tretta: def __init__ (self): self.x0=randxpos() # coordinata x primo vertice retta self.y0=randypos() # coordinata y primo vertice retta self.x1=randxpos() # coordinata x secondo vertice retta self.y1=randypos() # coordinata y secondo vertice retta self.vx0=randvelx() # velocita' orizzontale x primo vertice self.vy0=randvely() # velocita' verticale y primo vertice self.vx1=randvelx() # velocita' orizzontale x secondo vertice self.vy1=randvely() # velocita' verticale y secondovertice self.mx=0 # coordinata x centro retta self.my=0 # coordinata y centro retta class Tpunto: def __init__ (self): self.x=0 self.y=0 class Tbez: def __init__ (self): self.r=[Tretta() for i in range(RETTE)] # lista di rette (tensori) self.s=[[] for i in range(RETTE)] # lista di curve self.p=[Tpunto() for i in range(4)] # punti per interpolazione self.g=[] # lsta globale anelli # interpolazione Casteljau singolo punto def calc_bez(self,t): a0 = self.p[0].x + t * (self.p[1].x - self.p[0].x) a1 = self.p[1].x + t * (self.p[2].x - self.p[1].x) a2 = self.p[2].x + t * (self.p[3].x - self.p[2].x) b0 = a0 + t * (a1 - a0) b1 = a1 + t * (a2 - a1) x = b0 + t * (b1 - b0) a0 = self.p[0].y + t * (self.p[1].y - self.p[0].y) a1 = self.p[1].y + t * (self.p[2].y - self.p[1].y) a2 = self.p[2].y + t * (self.p[3].y - self.p[2].y) b0 = a0 + t * (a1 - a0) b1 = a1 + t * (a2 - a1) y = b0 + t * (b1 - b0) return x,y def calcola(self): for i in range(RETTE): # aggiorna posizione x0 retta self.r[i].x0 += self.r[i].vx0 if self.r[i].x0<0: self.r[i].x0=0 self.r[i].vx0=randvelx() if self.r[i].x0>WSC: self.r[i].x0=WSC self.r[i].vx0=-randvelx() # aggiorna posizione y0 retta self.r[i].y0 += self.r[i].vy0 if self.r[i].y0<0: self.r[i].y0=0 self.r[i].vy0=randvely() if self.r[i].y0>HSC: self.r[i].y0=HSC self.r[i].vy0=-randvely() # aggiorna posizione x1 retta self.r[i].x1 += self.r[i].vx1 if self.r[i].x1<0: self.r[i].x1=0 self.r[i].vx1=randvelx() if self.r[i].x1>WSC: self.r[i].x1=WSC self.r[i].vx1=-randvelx() # aggiorna posizione y1 retta self.r[i].y1 += self.r[i].vy1 if self.r[i].y1<0: self.r[i].y1=0 self.r[i].vy1=randvely() if self.r[i].y1>HSC: self.r[i].y1=HSC self.r[i].vy1=-randvely() # calcola coordinate centro retta self.r[i].mx=round(self.r[i].x0 + \ (self.r[i].x1 - self.r[i].x0) / 2.0) self.r[i].my=round(self.r[i].y0 + \ (self.r[i].y1 - self.r[i].y0) / 2.0) for i in range(RETTE): # se i e' dispari if (i & 1): self.p[0].x=self.r[i].mx self.p[0].y=self.r[i].my self.p[1].x=self.r[i].x1 self.p[1].y=self.r[i].y1 j=i+1 if j==RETTE: j=0 self.p[2].x=self.r[j].x1 self.p[2].y=self.r[j].y1 self.p[3].x=self.r[j].mx self.p[3].y=self.r[j].my # se i e' pari else: self.p[0].x=self.r[i].mx self.p[0].y=self.r[i].my self.p[1].x=self.r[i].x0 self.p[1].y=self.r[i].y0 j=i+1 if j==RETTE: j=0 if j: self.p[2].x=self.r[j].x0 self.p[2].y=self.r[j].y0 else: self.p[2].x=self.r[j].x1 self.p[2].y=self.r[j].y1 self.p[3].x=self.r[j].mx self.p[3].y=self.r[j].my # calcolo singola curva bezier self.s[i]=[] for h in range(PUNTI): t=h/(PUNTI-1.0) x,y=self.calc_bez(t) self.s[i].extend([round(x),round(y)]) self.g.append(self.s[:]) if len(self.g)>ANELLI: del self.g[0] main()