associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

TkinterNdCanvas

Receita: TkinterNdCanvas

Outra brincadeira, upgrade do Tkinter3dCanvas... exibindo um cubo de N dimensões em Tkinter. Por padrão ele desenha um hipercubo (4 dimensões), mas aceita qualquer número como argumento.

Código

   1 #!/usr/bin/env python
   2 
   3 from __future__ import division
   4 
   5 import sys
   6 from Tkinter import *
   7 from math import *
   8 from numpy import matrix, eye, array
   9 import random
  10 
  11 
  12 class MainWindow(Tk):
  13     def __init__(self, dim):
  14         Tk.__init__(self)
  15 
  16         self.dim = dim
  17 
  18         self.width = width = 600
  19         self.height = height = 600
  20         
  21         self.canvas = Canvas(self, width=width, height=height, bg='white')
  22         self.canvas.grid(row=0, column=0)
  23 
  24         self.CAM = CAM = 800
  25         self.OFF = OFF = self.width/2
  26 
  27         self.canvas.create_line(0, OFF, width, OFF, fill='black',
  28                                 stipple='gray50')
  29         self.canvas.create_line(OFF, 0, OFF, height, fill='black',
  30                                 stipple='gray50')
  31         
  32         self.angles = []
  33         for i in range(self.dim):
  34             v = IntVar()
  35             v.set(0)
  36             self.angles.append(v)
  37             Scale(self, variable=v, from_=-360, to=360, resolution=1,
  38             orient=HORIZONTAL, command=self.rotate).grid(row=i+1,
  39             column=0, sticky=E+W)
  40             
  41         self.draw()
  42 
  43 
  44     def rotate(self, event=None):
  45         for i, pol in enumerate(self.get_coords()):
  46             c = []
  47             for x in pol:
  48                 c.extend(x)
  49             self.canvas.coords(self._canvas[i], *c)
  50 
  51     def dist(self, x, y):
  52         d = 0
  53         for i in range(len(x)):
  54             t = x[i]-y[i]
  55             d += t*t
  56         return sqrt(d)
  57 
  58     def draw(self):
  59         self.size = 300
  60         self.nv = nv = 2 ** self.dim
  61         
  62         self.verts = v = array(tuple(self.vert()))
  63 
  64         self.lines = []
  65 
  66         for i in range(nv):
  67             for j in range(i+1, nv):
  68                 if ((abs(self.dist(v[i], v[j]))/self.size) - 1) < 0.1:
  69                     self.lines.append((v[i], v[j]))
  70 
  71         self.lines = array(self.lines)
  72                      
  73         self._canvas = []
  74         
  75         for pol in self.get_coords():
  76             print pol
  77             self._canvas.append(self.canvas.create_polygon(pol, outline='black'))
  78 
  79 
  80     def get_coords(self):
  81         trans = self.get_trans(self.dim)
  82 
  83         n, i, d = self.lines.shape
  84         assert i == 2
  85 
  86         lines = array(self.lines.reshape(n*2, d)* trans + self.OFF)
  87         lines = lines.reshape(n, i, d)
  88 
  89         for line in lines:
  90             yield [(p[0], p[1]) for p in line]
  91                 
  92 
  93     def get_trans(self, d=3):
  94         angles = [radians(x.get()) for x in self.angles]
  95 
  96         rot = matrix(eye(d))
  97         
  98         for i in range(d):
  99             for j in range(i+1, d):
 100                 delta = matrix(eye(d))
 101                 a = angles[self.dim-i-j]
 102                 s = sin(a)
 103                 c = cos(a)
 104 
 105                 delta[i, i] = delta[j, j] = c
 106                 delta[j, i] = -s
 107                 delta[i, j] = s
 108 
 109                 rot *= delta
 110 
 111         return rot
 112         
 113     def vert(self):
 114         for i in range(self.nv):
 115             b = []
 116             for j in range(self.dim):
 117                 if (i>>j)&1 == 1:
 118                     b.append(self.size/2)
 119                 else:
 120                     b.append(-self.size/2)
 121             yield array(b)
 122 
 123 
 124 if __name__ == "__main__":
 125     try:
 126         root = MainWindow(int(sys.argv[1]))
 127     except IndexError:
 128         root = MainWindow(4)
 129     finally:
 130         root.mainloop()

Volta para CookBook.


PedroWerneck