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.