#! /usr/bin/env python3 #------------------------------------------------------------------------------ # Curve di Bezier animate - by C.Fin - Python2&3 #------------------------------------------------------------------------------ import random try: import Tkinter as tk except ImportError: import tkinter as tk #------------------------------------------------------------------------------ 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 PUNTI = 30 # numero di punti in ogni curva INK = "cyan" # colore linee PAPER = "black" # colore fondo #------------------------------------------------------------------------------ class GUI: def __init__(self): self.form = tk.Tk() self.form.resizable(False, False) self.form.title("Bezier Curves by C.Fin") self.canvas = tk.Canvas( self.form, highlightthickness=0, width=WSC, height=HSC, bg=PAPER) self.canvas.pack() #------------------------------------------------------------------------------ class Tensore: def __init__ (self): self.x0 = randxpos() # coordinata x primo vertice Tensore self.y0 = randypos() # coordinata y primo vertice Tensore self.x1 = randxpos() # coordinata x secondo vertice Tensore self.y1 = randypos() # coordinata y secondo vertice Tensore 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 Tensore self.my = 0 # coordinata y centro Tensore #------------------------------------------------------------------------------ class Bez: def __init__ (self): self.r = [ Tensore() for i in range(RETTE) ] # lista di rette (tensori) self.s = [ [] for i in range(RETTE) ] # lista di curve self.g = [] # lsta globale anelli self.itemsList = [] # lista item canvas self.itemsPointer = 0 self.itemsListComplete = False def calcola(self): for i in range(RETTE): # aggiorna posizione x0 Tensore 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 Tensore 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 Tensore 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 Tensore 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 Tensore 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) s = [] # lista coordinate for i in range(RETTE): # se i e' dispari if (i & 1): p0x = self.r[i].mx p0y = self.r[i].my p1x = self.r[i].x1 p1y = self.r[i].y1 j = i + 1 if j == RETTE: j = 0 p2x = self.r[j].x1 p2y = self.r[j].y1 p3x = self.r[j].mx p3y = self.r[j].my # se i e' pari else: p0x = self.r[i].mx p0y = self.r[i].my p1x = self.r[i].x0 p1y = self.r[i].y0 j = i + 1 if j == RETTE: j = 0 if j: p2x = self.r[j].x0 p2y = self.r[j].y0 else: p2x = self.r[j].x1 p2y = self.r[j].y1 p3x = self.r[j].mx p3y = self.r[j].my # calcolo singola curva bezier for h in range(PUNTI): t = h / (PUNTI - 1.0) # interpolazione Casteljau singolo punto a0 = p0x + t * (p1x - p0x) a1 = p1x + t * (p2x - p1x) a2 = p2x + t * (p3x - p2x) b0 = a0 + t * (a1 - a0) b1 = a1 + t * (a2 - a1) x = b0 + t * (b1 - b0) a0 = p0y + t * (p1y - p0y) a1 = p1y + t * (p2y - p1y) a2 = p2y + t * (p3y - p2y) b0 = a0 + t * (a1 - a0) b1 = a1 + t * (a2 - a1) y = b0 + t * (b1 - b0) s.extend( [round(x), round(y)] ) self.g.append(s[:]) if len(self.g) > ANELLI: del self.g[0] #------------------------------------------------------------------------------ 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 #------------------------------------------------------------------------------ def disegna(bez, canvas): if bez.itemsListComplete: canvas.coords(bez.itemsList[bez.itemsPointer], *bez.g[ANELLI-1]) bez.itemsPointer = (bez.itemsPointer + 1) % ANELLI else: if len(bez.g) < ANELLI: bez.itemsList.append( canvas.create_line(bez.g[-1:][0], fill=INK) ) else: bez.itemsList.append( canvas.create_line(bez.g[-1:][0], fill=INK) ) bez.itemsListComplete = True #------------------------------------------------------------------------------ def animazione(bez, gui): bez.calcola() disegna(bez, gui.canvas) gui.form.update_idletasks() gui.form.after(40, lambda: animazione(bez, gui)) #------------------------------------------------------------------------------ def main(): bez = Bez() gui = GUI() animazione(bez, gui) gui.form.mainloop() #------------------------------------------------------------------------------ main()