#------------------------------------------------------------------------------ # Animazione curve di Bezier cubiche # By Claudio Fin novembre 2008 #------------------------------------------------------------------------------ import Image, ImageTk, Tkinter, ImageDraw, math, ImageFont, random WSC,HSC=400,400 # dimensioni area grafica RETTE=10 # numero di tensori colineari e curve 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 #------------------------------------------------------------------------------ def randxpos(): return random.randint(0,WSC) def randypos(): return random.randint(0,HSC) def randvelx(): d=round(WSC*0.016) v=0 while v==0: v=random.randint(-d,d) return v def randvely(): d=round(HSC*0.016) v=0 while v==0: v=random.randint(-d,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 #------------------------------------------------------------------------------ # r = lista di rette (oggetti Tretta) # s = lista di curve di bezier (ogni elemento e' una lista di coordinate) # p = lista di 4 punti (oggetti Tpunto) #------------------------------------------------------------------------------ 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)] # # 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=-self.r[i].vx0 if self.r[i].x0>WSC: self.r[i].x0=WSC self.r[i].vx0=-self.r[i].vx0 # 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=-self.r[i].vy0 if self.r[i].y0>HSC: self.r[i].y0=HSC self.r[i].vy0=-self.r[i].vy0 # 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=-self.r[i].vx1 if self.r[i].x1>WSC: self.r[i].x1=WSC self.r[i].vx1=-self.r[i].vx1 # 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=-self.r[i].vy1 if self.r[i].y1>HSC: self.r[i].y1=HSC self.r[i].vy1=-self.r[i].vy1 # 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)]) #------------------------------------------------------------------------------ class Tappl: global a_ret def __init__ (self): self.form1=Tkinter.Tk() self.canvas1=Tkinter.Canvas(self.form1,width=WSC,height=HSC,bg="white") self.canvas1.grid(column=0,row=0) im=ImageTk.PhotoImage(img) self.z=self.canvas1.create_image(2,2,image=im,anchor="nw") self.animazione() def animazione(self): bez.calcola() if PILD: drw.rectangle((0,0,WSC,HSC),fill="white") if TENSORI: self.drawtensoripil() for i in range(RETTE): drw.line(bez.s[i],fill="red") self.im=ImageTk.PhotoImage(img) self.canvas1.itemconfigure(self.z,image=self.im) else: self.canvas1.delete("all") if TENSORI: self.drawtensoritk() for i in range(RETTE): self.canvas1.create_line(bez.s[i],fill="red") self.form1.after(40,self.animazione) def drawtensoripil(self): 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 drawtensoritk(self): for i in range(RETTE): self.canvas1.create_line((bez.r[i].x0, bez.r[i].y0, \ bez.r[i].x1, bez.r[i].y1), \ fill="#CCCCCC") self.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") self.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") self.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") #------------------------------------------------------------------------------ img=Image.new("RGB",(WSC,HSC),"white") drw=ImageDraw.Draw(img) bez=Tbez() app=Tappl() app.form1.mainloop() if PILD: img.save("bezier2.png")