import Tkinter from Tkinter import* def mod(a,b): return ( a % b) def StandardKnot(): global m knot = [] L = len(points) - 2 if L <= m -2 : print 'make more points than m' return [] for i in range(m - 1): knot.append(0) for i in range(L - m + 3): knot.append(i) for i in range(m): knot.append(L - m + 3) return knot def Nopen(k,m,t,knot): if m <= 1: if t < knot[k] or t >= knot[k + 1]: Sum = 0.0 else: Sum = 1.0 else: d = knot[k+m-1]-knot[k] if d <> 0: Sum = (t-knot[k])*Nopen(k,m-1,t,knot)/d else: Sum = 0.0 d = knot[k+m] - knot[k+1] if d <> 0: Sum = Sum + (knot[k+m] - t)*Nopen(k + 1,m-1,t,knot)/d return Sum def Nclosed(k,m,t,knot): L = len(points) z = mod(t-k,L) if z <= 0: z += L return Nopen(0,m,z,knot) def P(t,knot,Ncycle): L = len(points) SumX = 0.0 SumY = 0.0 for k in range(L): n = Ncycle(k,m,t,knot) SumX = SumX + n * points[k][0] SumY = SumY + n * points[k][1] return [SumX,SumY] def plot(): global m global points if lOpen: knot = StandardKnot() if len(knot) == 0: return print knot print points x = points[0][0] y = points[0][1] t = 0.0 step = 0.1 L = len(points) while t <= L - m + 1: p = P(t,knot,Nopen) C.create_line(x, y, p[0], p[1]) x = p[0] y = p[1] t = t + step else: L = len(points) knot = range(L) print knot print points p = P(0.0,knot,Nclosed) x = p[0] y = p[1] step = 0.1 t = step L = len(points) while t <= L: p = P(t,knot,Nclosed) C.create_line(x, y, p[0], p[1]) x = p[0] y = p[1] t = t + step def Spaceout(): global points newpoints = [] L = len(points) if lOpen: newpoints.append(points[0]) knot = StandardKnot() if len(knot) == 0: return for t in range( 1, L - m + 2): p = P(t - 0.5,knot,Nopen) x = points[t][0] - p[0] y = points[t][1] - p[1] newpoints.append([points[t][0] + x,points[t][1] + y]) newpoints.append(points[-1]) else: knot = range(L) for t in range(L): p = P(mod(t + 1.5,L),knot,Nclosed) x = points[t][0] - p[0] y = points[t][1] - p[1] newpoints.append([points[t][0] + x,points[t][1] + y]) points = newpoints plot() def do_mouse(eventname): def mouse_binding(event): global points if eventname == "Button-1": x = event.x y = event.y print x, y if x > 50 and y > 50: points.append([x,y]) C.create_oval(x - 6,y - 6, x + 6, y + 6) C.create_text(x, y, text = '%d' %(len(points))) fram.bind_all( '<%s>' %eventname, mouse_binding) def wipe(): global points C.delete( ALL) points = [] def fetch(): global m m = mEntry.get() m = int(m) print 'm is now %d' %m def CycleClosed(i): global lOpen lOpen = i if lOpen: print 'Cycle is open' else: print 'Cycle is closed' def Blending(): global points L = len(points) if L <= m: print 'Make some more points first!' return if lOpen: knot = StandardKnot() if len(knot) == 0: return else: knot = range(L) print knot x0 = ScreenW * 0.2 y0 = ScreenH * 0.2 scaley = ScreenH * 0.7 scalex = ScreenW / L * 0.7 for k in knot: x1 = k * scalex + x0 y1 = ScreenH - y0 C.create_line(x1, y1, x1, y1 + 20) for k in range(L): t = 0.0 step = 0.1 x1 = x0 y1 = y0 if lOpen: z = L - m + 1 else: z = L while t <= z: if lOpen: p = Nopen(k,m,t,knot) else: p = Nopen(0,m,mod(t-k,L),knot) x2 = t * scalex + x0 y2 = ScreenH - p * scaley - y0 C.create_line(x1, y1, x2, y2) x1 = x2 y1 = y2 t = t + step m = 3 lOpen = True ScreenH = 600 ScreenW = 800 root = Tk() root.title('Left click to add some points, then click [Plot] to draw the b-spline.') fram = Frame(root) rad1 = Radiobutton(fram, text = 'Open',value=1,command=(lambda : CycleClosed(True))) rad1.pack(side = LEFT) rad2 = Radiobutton(fram, text = 'Closed',value=0,command=(lambda : CycleClosed(False))) rad2.pack(side = LEFT) rad1.select() Label(fram, text = 'M:').pack(side = LEFT,padx = 20) mEntry = Entry(fram) mEntry.insert(0,m) mEntry.focus() mEntry.bind('<Return>', (lambda event: fetch())) mEntry.pack(side = LEFT) butt1 = Button(fram, text = ' Plot ',command = plot) butt1.pack(side = LEFT) butt3 = Button(fram, text = ' Wipe ',command = wipe) butt3.pack(side = LEFT) butt4 = Button(fram, text = 'Blending',command = Blending) butt4.pack(side = LEFT) butt5 = Button(fram, text = 'Spaceout',command = Spaceout) butt5.pack(side = LEFT) fram.pack(side = TOP) C = Canvas(root, width = ScreenW, height = ScreenH) C.pack() do_mouse('Button-1') do_mouse('Button-3') points = [] root.mainloop()