1 """OpenGL-based 3d surface plot"""
2
3 from OpenGL.GL import *
4 from OpenGL.GLUT import *
5 from OpenGL.Tk import *
6
7 import numpy as N
8 import tkFileDialog
9
10 Colors = N.array([[201.0, 172.0,86.0],[201.0, 115.0,86.0],[201.0,86.0,89.0],
11 [201.0, 86.0,172.0],[172.0, 86.0,201.0],[115.0, 86.0,201.0],
12 [86.0,115.0,201.0],[86.0, 172.0,201.0],[86.0, 201.0,172.0],
13 [86.0,201.0,115.0],[115.0, 201.0,86.0],[172.0, 201.0,86.0]])/256
14
15 glutInit(sys.argv)
16
17 class figure :
18
19 def __init__(self):
20 return
21
22 def PutText3d(self,x,y,z,text) :
23 """ Draws text (using GLUT package) at given x,y,z coordinates"""
24 glRasterPos3f(x,y,z)
25 for i in range(len(text)) :
26 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, ord(text[i]));
27
28 def SetColor(self,height) :
29 """ Sets the colour from the colour index according to the plot height"""
30 color_index = int(round((height)*11))
31 glColor3f(self.Colors[color_index,0],self.Colors[color_index,1],
32 self.Colors[color_index,2])
33
34 def Rescale(self,X,Y,Z) :
35 """Scales values from 0 to 1"""
36
37 X,Y,Z = map(N.asarray,(X,Y,Z))
38
39 self.xmin = X.min()
40 self.xmax = X.max()
41 self.ymin = Y.min()
42 self.ymax = Y.max()
43 self.zmin = Z.min()
44 self.zmax = Z.max()
45
46
47 if self.xmax==self.xmin :
48 xdif = 0.01
49 else:
50 xdif = abs(self.xmax-self.xmin)
51
52 if self.ymax==self.ymin :
53 ydif = 0.01
54 else:
55 ydif = abs(self.ymax-self.ymin)
56
57 if self.zmax==self.zmin :
58 zdif = 0.01
59 else:
60 zdif = abs(self.zmax-self.zmin)
61
62 self.X = (X-self.xmin)/xdif
63 self.Y = (Y-self.ymin)/ydif
64 self.Z = (Z-self.zmin)/zdif
65
66
67 def InitGfx(self) :
68 glShadeModel(GL_SMOOTH)
69 glClearColor(1, 1, 1, 1)
70 glClearDepth(1.0)
71 for option in [GL_DEPTH_TEST,GL_LINE_SMOOTH,GL_POINT_SMOOTH, \
72 GL_POLYGON_SMOOTH,GL_BLEND]:
73 glEnable(option)
74
75 glDepthFunc(GL_LEQUAL);
76 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
77
78 for hint in [GL_PERSPECTIVE_CORRECTION_HINT,GL_LINE_SMOOTH_HINT, \
79 GL_POLYGON_SMOOTH_HINT]:
80 glHint(hint,GL_NICEST)
81
82 glClearColor(1, 1, 1, 0)
83 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
84 glColor3f(1.0, 0.0, 1.0)
85 glMatrixMode(GL_MODELVIEW)
86
87 def DrawPlotBox(self) :
88 """ Draws 3 faces of a box that will contain our plot"""
89 modelview = glGetDoublev(GL_MODELVIEW_MATRIX)
90 modelview = N.array(modelview)
91 t_model = modelview.transpose()
92 inv_modelview = N.linalg.inv(t_model)
93 self.inv_mv = inv_modelview
94 eye = N.array([0,0,-1,1])
95 view = N.dot(inv_modelview,eye)
96 view = view/float(view[3])
97 view = view[0:3]
98 self.view = view
99 init_x = N.array([1,0,0,1])
100 new_x = N.dot(inv_modelview,init_x)
101 new_x = new_x/float(new_x[3])
102 new_x= new_x[0:3]
103 self.new_x = new_x
104 init_y = N.array([0,1,0,1])
105 new_y = N.dot(inv_modelview,init_y)
106 new_y = new_y/float(new_y[3])
107 new_y= new_y[0:3]
108 self.new_y = new_y
109
110 offset = self.offset
111
112 glColor3f(0.98, 0.98, 0.98)
113 glDisable(GL_LIGHTING)
114 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
115 glBegin(GL_QUADS)
116
117 if N.dot(view,[1,0,0]) < 0 :
118 glVertex3f(0-0.5-offset ,0-0.5-offset ,0-0.5-offset )
119 glVertex3f(0-0.5-offset ,1-0.5+offset,0-0.5-offset )
120 glVertex3f(0-0.5-offset ,1-0.5+offset,1-0.5+offset )
121 glVertex3f(0-0.5-offset ,0-0.5-offset ,1-0.5+offset )
122 self.sides = [1]
123 else :
124 glVertex3f(1-0.5+offset ,0-0.5-offset ,0-0.5-offset )
125 glVertex3f(1-0.5+offset ,0-0.5-offset ,1-0.5+offset )
126 glVertex3f(1-0.5+offset,1-0.5+offset ,1-0.5+offset )
127 glVertex3f(1-0.5+offset ,1-0.5+offset ,0-0.5-offset )
128 self.sides = [2]
129
130 if N.dot(view,[0,1,0]) < 0 :
131
132 glVertex3f(0-0.5-offset,0-0.5-offset,0-0.5-offset)
133 glVertex3f(0-0.5-offset,0-0.5-offset,1-0.5+offset)
134 glVertex3f(1-0.5+offset ,0-0.5-offset,1-0.5+offset)
135 glVertex3f(1-0.5+offset,0-0.5-offset ,0-0.5-offset )
136 self.sides.append(3)
137 else :
138 glVertex3f(0-0.5-offset ,1-0.5+offset ,0-0.5-offset )
139 glVertex3f(1-0.5+offset ,1-0.5+offset ,0-0.5-offset )
140 glVertex3f(1-0.5+offset,1-0.5+offset ,1-0.5+offset )
141 glVertex3f(0-0.5-offset ,1-0.5+offset,1-0.5+offset)
142 self.sides.append(4)
143
144 if N.dot(view,[0,0,1]) > 0 :
145 glVertex3f(0-0.5-offset ,0-0.5-offset ,1-0.5+offset)
146 glVertex3f(0-0.5-offset ,1-0.5+offset,1-0.5+offset )
147 glVertex3f(1-0.5+offset,1-0.5+offset,1-0.5+offset)
148 glVertex3f(1-0.5+offset,0-0.5-offset ,1-0.5+offset)
149 self.sides.append(6)
150 else :
151 glVertex3f(0-0.5-offset,0-0.5-offset ,0-0.5-offset )
152 glVertex3f(1-0.5+offset,0-0.5-offset ,0-0.5-offset )
153 glVertex3f(1-0.5+offset,1-0.5+offset,0-0.5-offset )
154 glVertex3f(0-0.5-offset ,1-0.5+offset,0-0.5-offset )
155 self.sides.append(5)
156 glEnd()
157 glEnable(GL_LIGHTING)
158
159 def DrawPlotBoxLines(self):
160 """ Draws lines on the plot box"""
161 glDisable(GL_LIGHTING)
162
163
164 glColor3f(0.9,0.9,0.9)
165 offset = self.offset
166 glBegin(GL_LINES)
167 for a in range(1,4):
168
169 if self.sides[0] == 2:
170 glVertex3f(1-0.5+offset,0-0.5+0.25*a,1-0.5+offset )
171 glVertex3f(1-0.5+offset,0-0.5+0.25*a,0-0.5-offset )
172
173 glVertex3f(1-0.5+offset,1-0.5+offset,0-0.5+0.25*a)
174 glVertex3f(1-0.5+offset,0-0.5-offset,0-0.5+0.25*a)
175 else :
176 glVertex3f(0-0.5-offset,0-0.5+0.25*a,1-0.5+offset)
177 glVertex3f(0-0.5-offset,0-0.5+0.25*a,0-0.5-offset)
178
179 glVertex3f(0-0.5-offset,1-0.5+offset,0-0.5+0.25*a)
180 glVertex3f(0-0.5-offset,0-0.5-offset,0-0.5+0.25*a)
181
182 if self.sides[1] == 3:
183 glVertex3f(0-0.5+0.25*a,0-0.5-offset,1-0.5+offset)
184 glVertex3f(0-0.5+0.25*a,0-0.5-offset,0-0.5-offset)
185
186 glVertex3f(1-0.5+offset,0-0.5-offset,0-0.5+0.25*a)
187 glVertex3f(0-0.5-offset,0-0.5-offset,0-0.5+0.25*a)
188 else :
189 glVertex3f(0-0.5+0.25*a,1-0.5+offset,1-0.5+offset)
190 glVertex3f(0-0.5+0.25*a,1-0.5+offset,0-0.5-offset)
191
192 glVertex3f(1-0.5+offset,1-0.5+offset,0-0.5+0.25*a)
193 glVertex3f(0-0.5-offset,1-0.5+offset,0-0.5+0.25*a)
194
195 if self.sides[2] == 5:
196 glVertex3f(1-0.5+offset,0-0.5+0.25*a,0-0.5-offset)
197 glVertex3f(0-0.5-offset,0-0.5+0.25*a,0-0.5-offset)
198
199 glVertex3f(0-0.5+0.25*a,1-0.5+offset,0-0.5-offset)
200 glVertex3f(0-0.5+0.25*a,0-0.5-offset,0-0.5-offset)
201 else :
202 glVertex3f(1-0.5+offset,0-0.5+0.25*a,1-0.5+offset)
203 glVertex3f(0-0.5-offset,0-0.5+0.25*a,1-0.5+offset)
204
205 glVertex3f(0-0.5+0.25*a,1-0.5+offset,1-0.5+offset)
206 glVertex3f(0-0.5+0.25*a,0-0.5-offset,1-0.5+offset)
207 glEnd()
208
209 glColor3f(0,0,0)
210 glEnable(GL_LIGHTING)
211
212 def GetFormatMaxTextLength(self) :
213 import decimal as D
214 D.getcontext().prec = self.precision
215 ticks = []
216 xticks = []
217 yticks = []
218 zticks = []
219
220 for a in range(self.num_ticks):
221 numberx = self.xmin +a*0.25*(self.xmax-self.xmin)
222 numbery = self.ymin +a*0.25*(self.ymax-self.ymin)
223 numberz = self.zmin +a*0.25*(self.zmax-self.zmin)
224 strnumberx = str(D.Decimal(str(numberx))+0)
225 strnumbery = str(D.Decimal(str(numbery))+0)
226 strnumberz = str(D.Decimal(str(numberz))+0)
227 if ((strnumberx[0:3]=='0.0') or (strnumberx[0:4]=='-0.0')) and float(strnumberx)!=0:
228 strnumberx = '%.*e' % (self.precision-1,float(strnumberx))
229 if ((strnumbery[0:3]=='0.0') or (strnumbery[0:4]=='-0.0'))and float(strnumbery)!=0:
230 strnumbery = '%.*e' % (self.precision-1,float(strnumbery))
231 if ((strnumberz[0:3]=='0.0') or (strnumberz[0:4]=='-0.0'))and float(strnumberz)!=0:
232 strnumberz = '%.*e' % (self.precision-1,float(strnumberz))
233 xticks.append(strnumberx)
234 yticks.append(strnumbery)
235 zticks.append(strnumberz)
236 ticks.append(len(strnumberx))
237 ticks.append(len(strnumbery))
238 ticks.append(len(strnumberz))
239
240 return max(ticks), xticks,yticks,zticks
241
242
243 def InsertAxesText(self) :
244 """ Identifies on which sides axis should be drawn, establishes the orientation
245 of the text in relation to the plot area and draws the text accordingly. """
246 glDisable(GL_LIGHTING)
247 glMatrixMode(GL_MODELVIEW);
248 glLineWidth(2.0)
249 textlength,xticks,yticks,zticks = self.textlength,self.xticks,self.yticks,self.zticks
250 base_left_offset = 0.03
251 ax_base_left_offset =0.08
252 top_up_offset = -0.025
253 bottom_up_offset = 0.05
254 ax_top_up_offset = -0.075
255 ax_bottom_up_offset = 0.1
256 textoffset = 0.025
257 ticksoffset = 1/float(self.num_ticks-1)
258 if abs(N.dot([1,0,0],self.view)) < abs(N.dot([0,1,0],self.view)):
259 point = N.array([self.sides[0]-1.5,3.5-self.sides[1],0])
260 line = N.array([0,0,1])
261 if abs(self.new_x[0]) > abs(self.new_x[1]) :
262 if point[0]*self.new_x[0] > 0 :
263
264 left_offset = -base_left_offset
265 ax_left_offset = -ax_base_left_offset-textlength*textoffset
266 else :
267
268 left_offset = base_left_offset +textlength*textoffset
269 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
270 else :
271 if point[1]*self.new_x[1] > 0 :
272
273 left_offset = -base_left_offset
274 ax_left_offset = -ax_base_left_offset-textlength*textoffset
275 else :
276
277 left_offset = base_left_offset +textlength*textoffset
278 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
279 if abs(self.new_y[0]) > abs(self.new_y[1]) :
280 if point[0]*self.new_y[0] > 0 :
281
282 up_offset = top_up_offset
283 ax_up_offset = ax_top_up_offset
284 else :
285
286 up_offset = bottom_up_offset
287 ax_up_offset = ax_bottom_up_offset
288 else :
289 if point[1]*self.new_y[1] > 0 :
290
291 up_offset = top_up_offset
292 ax_up_offset = ax_top_up_offset
293 else :
294
295 up_offset = bottom_up_offset
296 ax_up_offset = ax_bottom_up_offset
297 if (abs(N.dot(line,self.new_x)) > 0.4) and(abs(N.dot(line,self.new_y)) > 0.21) :
298 factor = 1
299 else :
300 factor = 1.2*(1-abs(N.dot(line,self.new_x)))
301 factor2 = 1.2*(1-abs(N.dot(line,self.new_y)))
302 offset = left_offset*factor*self.new_x + up_offset*factor2*self.new_y
303 ax_offset = ax_left_offset*factor*self.new_x+ax_up_offset*factor2*self.new_y
304
305 for a in range(self.num_ticks):
306 self.PutText3d(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0)-offset[0],3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0)-offset[1],-0.5 + a*ticksoffset-offset[2],yticks[a])
307 self.PutText3d(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0)-ax_offset[0],3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0)-ax_offset[1],0-ax_offset[2],'Y')
308
309 glBegin(GL_LINES)
310 glVertex3f(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0),3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0),-0.5-self.offset)
311 glVertex3f(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0),3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0),0.5+self.offset)
312 for a in range(self.num_ticks):
313 glVertex3f(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0),3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0)+0.025*cmp(3.5-self.sides[1],0),-0.5+a*ticksoffset)
314 glVertex3f(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0),3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0),-0.5+a*ticksoffset)
315
316 else :
317 point = N.array([1.5-self.sides[0],self.sides[1]-3.5,0])
318 if abs(self.new_x[0]) > abs(self.new_x[1]) :
319 if point[0]*self.new_x[0] > 0 :
320
321 left_offset = -base_left_offset
322 ax_left_offset = -ax_base_left_offset-textlength*textoffset
323 else :
324
325 left_offset = base_left_offset +textlength*textoffset
326 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
327 else :
328 if point[1]*self.new_x[1] > 0 :
329
330 left_offset = -base_left_offset
331 ax_left_offset = -ax_base_left_offset-textlength*textoffset
332 else :
333
334 left_offset = base_left_offset +textlength*textoffset
335 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
336 if abs(self.new_y[0]) > abs(self.new_y[1]) :
337 if point[0]*self.new_y[0] > 0 :
338
339 up_offset = top_up_offset
340 ax_up_offset = ax_top_up_offset
341 else :
342
343 up_offset = bottom_up_offset
344 ax_up_offset = ax_bottom_up_offset
345 else :
346 if point[1]*self.new_y[1] > 0 :
347
348 up_offset = top_up_offset
349 ax_up_offset = ax_top_up_offset
350 else :
351
352 up_offset = bottom_up_offset
353 ax_up_offset = ax_bottom_up_offset
354 line = N.array([0,0,1])
355 if (abs(N.dot(line,self.new_x)) > 0.4) and (abs(N.dot(line,self.new_y)) > 0.21) :
356 factor = 1
357 else :
358 factor = 1.2*(1-abs(N.dot(line,self.new_x)))
359 factor2 = 1.2*(1-abs(N.dot(line,self.new_y)))
360 offset = left_offset*factor*self.new_x
361 offset = offset + up_offset*factor2*self.new_y
362 ax_offset = ax_left_offset*factor*self.new_x+ax_up_offset*factor2*self.new_y
363 for a in range(self.num_ticks) :
364 self.PutText3d(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0)-offset[0],self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0)-offset[1],-0.5+a*ticksoffset-offset[2],yticks[a])
365 self.PutText3d(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0)-ax_offset[0],self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0)-ax_offset[1],0-ax_offset[2],'Y')
366
367 glBegin(GL_LINES)
368 glVertex3f(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0),self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0),-0.5-self.offset)
369 glVertex3f(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0),self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0),0.5+self.offset)
370 for a in range(self.num_ticks):
371 glVertex3f(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0)+0.025*cmp(1.5-self.sides[0],0),self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0),-0.5+ticksoffset*a)
372 glVertex3f(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0),self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0),-0.5+ticksoffset*a)
373 glEnd()
374
375
376 if abs(N.dot([1,0,0],self.view)) < abs(N.dot([0,0,1],self.view)):
377 glBegin(GL_LINES)
378 glVertex3f(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0),-0.5-self.offset,5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0))
379 glVertex3f(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0),0.5+self.offset,5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0))
380 for a in range(self.num_ticks):
381 glVertex3f(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0),-0.5+ticksoffset*a,5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0)+0.025*cmp(5.5-self.sides[2],0))
382 glVertex3f(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0),-0.5+ticksoffset*a,5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0))
383 glEnd()
384 point = N.array([self.sides[0]-1.5,0,5.5-self.sides[2]])
385 if abs(self.new_x[0]) > abs(self.new_x[2]) :
386 if point[0]*self.new_x[0] > 0 :
387
388 left_offset = -base_left_offset
389 ax_left_offset = -ax_base_left_offset-textlength*textoffset
390 else :
391
392 left_offset = base_left_offset +textlength*textoffset
393 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
394 else :
395 if point[2]*self.new_x[2] > 0 :
396
397 left_offset = -base_left_offset
398 ax_left_offset = -ax_base_left_offset-textlength*textoffset
399 else :
400
401 left_offset = base_left_offset +textlength*textoffset
402 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
403 if abs(self.new_y[0]) > abs(self.new_y[2]) :
404 if point[0]*self.new_y[0] > 0 :
405
406 up_offset = top_up_offset
407 ax_up_offset = ax_top_up_offset
408 else :
409
410 up_offset = bottom_up_offset
411 ax_up_offset = ax_bottom_up_offset
412 else :
413 if point[2]*self.new_y[2] > 0 :
414
415 up_offset = top_up_offset
416 ax_up_offset = ax_top_up_offset
417 else :
418
419 up_offset = bottom_up_offset
420 ax_up_offset = ax_bottom_up_offset
421 line = N.array([0,1,0])
422 if (abs(N.dot(line ,self.new_x)) > 0.4) and (abs(N.dot(line ,self.new_y)) > 0.21) :
423 factor = 1
424 else :
425 factor = 1.2*(1-abs(N.dot(line ,self.new_x)))
426 factor2 = 1.2*(1-abs(N.dot(line ,self.new_y)))
427 offset = left_offset*factor*self.new_x
428 offset = offset + up_offset*factor2*self.new_y
429 ax_offset = ax_left_offset*factor*self.new_x+ax_up_offset*factor2*self.new_y
430 for a in range(self.num_ticks):
431 self.PutText3d(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0)-offset[0],-0.5+ticksoffset*a-offset[1],5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0)-offset[2],zticks[a])
432 self.PutText3d(self.sides[0]-1.5+self.offset*cmp(self.sides[0]-1.5,0)-ax_offset[0],0-ax_offset[1],5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0)-ax_offset[2],'Z')
433
434 else :
435 glBegin(GL_LINES)
436 glVertex3f(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0),-0.5-self.offset,self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0))
437 glVertex3f(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0),0.5+self.offset,self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0))
438 for a in range(self.num_ticks):
439 glVertex3f(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0)+0.025*cmp(1.5-self.sides[0],0),-0.5+ticksoffset*a,self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0))
440 glVertex3f(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0),-0.5+ticksoffset*a,self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0))
441 glEnd()
442 point = N.array([1.5-self.sides[0],0,self.sides[2]-5.5])
443 if abs(self.new_x[0]) > abs(self.new_x[2]) :
444 if point[0]*self.new_x[0] > 0 :
445
446 left_offset = -base_left_offset
447 ax_left_offset = -ax_base_left_offset-textlength*textoffset
448 else :
449
450 left_offset = base_left_offset +textlength*textoffset
451 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
452 else :
453 if point[2]*self.new_x[2] > 0 :
454
455 left_offset = -base_left_offset
456 ax_left_offset = -ax_base_left_offset-textlength*textoffset
457 else :
458
459 left_offset = base_left_offset +textlength*textoffset
460 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
461 if abs(self.new_y[0]) > abs(self.new_y[2]) :
462 if point[0]*self.new_y[0] > 0 :
463
464 up_offset = top_up_offset
465 ax_up_offset = ax_top_up_offset
466 else :
467
468 up_offset = bottom_up_offset
469 ax_up_offset = ax_bottom_up_offset
470 else :
471 if point[2]*self.new_y[2] > 0 :
472
473 up_offset = top_up_offset
474 ax_up_offset = ax_top_up_offset
475 else :
476
477 up_offset = bottom_up_offset
478 ax_up_offset = ax_bottom_up_offset
479 line = N.array([0,1,0])
480 if (abs(N.dot(line,self.new_x)) > 0.4) and (abs(N.dot(line,self.new_y)) > 0.21) :
481 factor = 1
482 else :
483 factor = 1.2*(1-abs(N.dot(line,self.new_x)))
484 factor2 = 1.2*(1-abs(N.dot(line,self.new_y)))
485 offset = left_offset*factor*self.new_x
486 offset = offset + up_offset*factor2*self.new_y
487 ax_offset = ax_left_offset*factor*self.new_x+ax_up_offset*factor2*self.new_y
488 for a in range(self.num_ticks):
489 self.PutText3d(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0)-offset[0],-0.5+ticksoffset*a-offset[1],self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0)-offset[2],zticks[a])
490 self.PutText3d(1.5-self.sides[0]+self.offset*cmp(1.5-self.sides[0],0)-ax_offset[0],0-ax_offset[1],self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0)-ax_offset[2],'Z')
491
492
493 if abs(N.dot([0,1,0],self.view)) < abs(N.dot([0,0,1],self.view)):
494 glBegin(GL_LINES)
495 glVertex3f(-0.5-self.offset,self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0),5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0))
496 glVertex3f(0.5+self.offset,self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0),5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0))
497 for a in range(self.num_ticks):
498 glVertex3f(-0.5+ticksoffset*a,self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0),5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0)+0.025*cmp(5.5-self.sides[2],0))
499 glVertex3f(-0.5+ticksoffset*a,self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0),5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0))
500 glEnd()
501 point = N.array([0,self.sides[1]-3.5,5.5-self.sides[2]])
502 if abs(self.new_x[1]) > abs(self.new_x[2]) :
503 if point[1]*self.new_x[1] > 0 :
504
505 left_offset = -base_left_offset
506 ax_left_offset = -ax_base_left_offset-textlength*textoffset
507 else :
508
509 left_offset = base_left_offset +textlength*textoffset
510 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
511 else :
512 if point[2]*self.new_x[2] > 0 :
513
514 left_offset = -base_left_offset
515 ax_left_offset = -ax_base_left_offset-textlength*textoffset
516 else :
517
518 left_offset = base_left_offset +textlength*textoffset
519 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
520 if abs(self.new_y[1]) > abs(self.new_y[2]) :
521 if point[1]*self.new_y[1] > 0 :
522
523 up_offset = top_up_offset
524 ax_up_offset = ax_top_up_offset
525 else :
526
527 up_offset = bottom_up_offset
528 ax_up_offset = ax_bottom_up_offset
529 else :
530 if point[2]*self.new_y[2] > 0 :
531
532 up_offset = top_up_offset
533 ax_up_offset = ax_top_up_offset
534 else :
535
536 up_offset = bottom_up_offset
537 ax_up_offset = ax_bottom_up_offset
538 line = N.array([1,0,0])
539 if (abs(N.dot(line,self.new_x)) > 0.4) and (abs(N.dot(line,self.new_y)) > 0.21) :
540 factor = 1
541 else :
542 factor = 1.2*(1-abs(N.dot(line,self.new_x)))
543 factor2 = 1.2*(1-abs(N.dot(line,self.new_y)))
544 offset = left_offset*factor*self.new_x
545 offset = offset + up_offset*factor2*self.new_y
546 ax_offset = ax_left_offset*factor*self.new_x+ax_up_offset*factor2*self.new_y
547 for a in range(self.num_ticks):
548 self.PutText3d(-0.5+ticksoffset*a-offset[0],self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0)-offset[1],5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0)-offset[2],xticks[a])
549 self.PutText3d(0-ax_offset[0],self.sides[1]-3.5+self.offset*cmp(self.sides[1]-3.5,0)-ax_offset[1],5.5-self.sides[2]+self.offset*cmp(5.5-self.sides[2],0)-ax_offset[2],'X')
550
551 else :
552 glBegin(GL_LINES)
553 glVertex3f(-0.5-self.offset,3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0),self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0))
554 glVertex3f(0.5+self.offset,3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0),self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0))
555 for a in range(self.num_ticks):
556 glVertex3f(-0.5+ticksoffset*a,3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0)+0.025*cmp(3.5-self.sides[1],0),self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0))
557 glVertex3f(-0.5+ticksoffset*a,3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0),self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0))
558 glEnd()
559 point = N.array([0,3.5-self.sides[1],self.sides[2]-5.5])
560 if abs(self.new_x[1]) > abs(self.new_x[2]) :
561 if point[1]*self.new_x[1] > 0 :
562
563 left_offset = -base_left_offset
564 ax_left_offset = -ax_base_left_offset-textlength*textoffset
565 else :
566
567 left_offset = base_left_offset +textlength*textoffset
568 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
569 else :
570 if point[2]*self.new_x[2] > 0 :
571
572 left_offset = -base_left_offset
573 ax_left_offset = -ax_base_left_offset-textlength*textoffset
574 else :
575
576 left_offset = base_left_offset +textlength*textoffset
577 ax_left_offset = ax_base_left_offset+(textlength+1)*textoffset
578 if abs(self.new_y[1]) > abs(self.new_y[2]) :
579 if point[1]*self.new_y[1] > 0 :
580
581 up_offset = top_up_offset
582 ax_up_offset = ax_top_up_offset
583 else :
584
585 up_offset = bottom_up_offset
586 ax_up_offset = ax_bottom_up_offset
587 else :
588 if point[2]*self.new_y[2] > 0 :
589
590 up_offset = top_up_offset
591 ax_up_offset = ax_top_up_offset
592 else :
593
594 up_offset = bottom_up_offset
595 ax_up_offset = ax_bottom_up_offset
596 line = N.array([1,0,0])
597 if (abs(N.dot(line,self.new_x)) > 0.4) and (abs(N.dot(line,self.new_y)) > 0.21) :
598 factor = 1
599 else :
600 factor = 1.2*(1-abs(N.dot(line,self.new_x)))
601 factor2 = 1.2*(1-abs(N.dot(line,self.new_y)))
602 offset = left_offset*factor*self.new_x
603 offset = offset + up_offset*factor2*self.new_y
604 ax_offset = ax_left_offset*factor*self.new_x+ax_up_offset*factor2*self.new_y
605 for a in range(self.num_ticks):
606 self.PutText3d(-0.5+ticksoffset*a-offset[0],3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0)-offset[1],self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0)-offset[2],xticks[a])
607 self.PutText3d(0-ax_offset[0],3.5-self.sides[1]+self.offset*cmp(3.5-self.sides[1],0)-ax_offset[1],self.sides[2]-5.5+self.offset*cmp(self.sides[2]-5.5,0)-ax_offset[2],'X')
608
609 glLineWidth(self.linewidth)
610 glColor3f(0.0,0.0,0.0)
611 glEnable(GL_LIGHTING)
612
613 def redraw(self,o):
614 self.InitGfx()
615 self.DrawPlotBox()
616 self.DrawPlotBoxLines()
617
618 glLineWidth(self.linewidth)
619 self.InsertAxesText()
620 self.drawplot()
621 glLineWidth(0.1)
622
623 def save(self):
624 myFormats = [
625 ('Windows Bitmap','*.bmp'),
626 ('Enhanced Windows Metafile','*.emf'),
627 ('Encapsulated PostScript','*.eps'),
628 ('CompuServe GIF','*.gif'),
629 ('JPEG / JPG','*.jpg'),
630 ('Zsoft Paintbrush','*.pcx'),
631 ('Portable Network Graphics','*.png'),
632 ('Portable Pixelmap','*.ppm'),
633 ('Tagged Image File Format','*.tif'),
634 ]
635 fileName = tkFileDialog.asksaveasfilename(filetypes=myFormats ,title="Save the image as...")
636 if fileName :
637 self.SaveTo(fileName)
638
639 def SaveTo(self,filename):
640 """Save current buffer to filename in format"""
641 import Image
642 viewport = glGetIntegerv(GL_VIEWPORT)
643 width, height = viewport[2],viewport[3]
644 glPixelStorei(GL_PACK_ALIGNMENT, 1)
645 data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE)
646 image = Image.fromstring( "RGB", (width, height), data )
647 image = image.transpose( Image.FLIP_TOP_BOTTOM)
648 image.save( filename)
649 print 'Saved image to %s'% (os.path.abspath( filename))
650 return image
651
652 def make_plot(self,colors = Colors):
653 """Draw a plot in a Tk OpenGL render window."""
654
655
656
657 ESCAPE = '\033'
658
659
660 window = 0
661
662
663 f = Frame()
664 f.pack(side = 'top')
665 self.offset = 0.05
666 self.textlength,self.xticks,self.yticks,self.zticks =self.GetFormatMaxTextLength()
667 o = Opengl(width = 640, height = 480, double = 1, depth = 1)
668 o.redraw = self.redraw
669 quit = Button(f, text = 'Quit', command = sys.exit)
670 quit.pack({'side':'top', 'side':'left'})
671 help = Button(f, text = 'Help', command = o.help)
672 help.pack({'side':'top', 'side':'left'})
673 save = Button(f, text = 'Save', command = self.save)
674 save.pack({'side':'top', 'side':'left'})
675 reset = Button(f, text = 'Reset', command = o.reset)
676 reset.pack({'side':'top', 'side':'left'})
677 o.pack(side = 'top', expand = 1, fill = 'both')
678 o.set_background(1,1,1)
679 o.set_centerpoint(0.0, 0.0, 0.0)
680 o.set_eyepoint(3)
681 o.autospin = 1
682 o.mainloop()
683
684
685 class mesh(figure) :
686 """class for surface meshes"""
687 def __init__(self,X,Y,Z,colors = Colors,linewidth = 0.1,fill_mesh = 0,precision=3,num_ticks=5):
688 self.Colors = colors
689 self.linewidth= linewidth
690 self.fill_mesh = fill_mesh
691 self.precision = precision
692 self.num_ticks = num_ticks
693 self.Rescale(X,Y,Z)
694 self.make_plot(colors)
695 return
696
697 def drawplot(self) :
698 glDisable(GL_LIGHTING)
699
700 X_shift = self.X-0.5
701 Y_shift = self.Y-0.5
702 Z_shift = self.Z-0.5
703
704 plotsizex,plotsizey = N.shape(self.X)
705
706 if self.fill_mesh :
707 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
708 glEnable(GL_POLYGON_OFFSET_FILL);
709 glPolygonOffset(1.0, 1.0);
710 glColor3f(0.98, 0.98, 0.98)
711 glBegin(GL_TRIANGLES)
712 for i in range(plotsizex-1):
713 for j in range(plotsizey-1):
714 self.SetColor(self.Z[i,j])
715 glVertex3f( X_shift[i,j],Z_shift[i,j],Y_shift[i,j])
716 self.SetColor(self.Z[i,j])
717 glVertex3f( X_shift[i+1,j],Z_shift[i+1,j],Y_shift[i+1,j])
718 self.SetColor(self.Z[i,j])
719 glVertex3f( X_shift[i,j+1], Z_shift[i,j+1],Y_shift[i,j+1] )
720 self.SetColor(self.Z[i+1,j])
721 glVertex3f( X_shift[i+1,j], Z_shift[i+1,j],Y_shift[i+1,j] )
722 self.SetColor(self.Z[i,j+1])
723 glVertex3f( X_shift[i,j+1], Z_shift[i,j+1],Y_shift[i,j+1])
724 self.SetColor(self.Z[i+1,j+1])
725 glVertex3f( X_shift[i+1,j+1], Z_shift[i+1,j+1],Y_shift[i+1,j+1] )
726 glEnd()
727 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
728 glColor3f(0.0, 0.0, 0.0)
729 glBegin(GL_TRIANGLES)
730 for i in range(plotsizex-1):
731 for j in range(plotsizey-1):
732 glVertex3f( X_shift[i,j],Z_shift[i,j],Y_shift[i,j])
733 glVertex3f( X_shift[i+1,j],Z_shift[i+1,j],Y_shift[i+1,j])
734 glVertex3f( X_shift[i,j+1], Z_shift[i,j+1],Y_shift[i,j+1] )
735 glVertex3f( X_shift[i+1,j], Z_shift[i+1,j],Y_shift[i+1,j] )
736 glVertex3f( X_shift[i,j+1], Z_shift[i,j+1],Y_shift[i,j+1])
737 glVertex3f( X_shift[i+1,j+1], Z_shift[i+1,j+1],Y_shift[i+1,j+1] )
738 glEnd()
739 else :
740
741 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
742 glColor3f(0.0, 0.0, 0.0)
743 glBegin(GL_TRIANGLES)
744 for i in range(plotsizex-1):
745 for j in range(plotsizey-1):
746 self.SetColor(self.Z[i,j])
747 glVertex3f( X_shift[i,j],Z_shift[i,j],Y_shift[i,j])
748 self.SetColor(self.Z[i+1,j])
749 glVertex3f( X_shift[i+1,j],Z_shift[i+1,j],Y_shift[i+1,j])
750 self.SetColor(self.Z[i,j+1])
751 glVertex3f( X_shift[i,j+1], Z_shift[i,j+1],Y_shift[i,j+1] )
752 self.SetColor(self.Z[i+1,j])
753 glVertex3f( X_shift[i+1,j], Z_shift[i+1,j],Y_shift[i+1,j] )
754 self.SetColor(self.Z[i,j+1])
755 glVertex3f( X_shift[i,j+1], Z_shift[i,j+1],Y_shift[i,j+1])
756 self.SetColor(self.Z[i+1,j+1])
757 glVertex3f( X_shift[i+1,j+1], Z_shift[i+1,j+1],Y_shift[i+1,j+1] )
758 glEnd()
759
760 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
761 glEnable(GL_POLYGON_OFFSET_FILL);
762 glPolygonOffset(1.0, 1.0);
763 glColor3f(0.98, 0.98, 0.98)
764 glBegin(GL_TRIANGLES)
765 for i in range(plotsizex-1):
766 for j in range(plotsizey-1):
767 glVertex3f( X_shift[i,j],Z_shift[i,j],Y_shift[i,j])
768 glVertex3f( X_shift[i+1,j],Z_shift[i+1,j],Y_shift[i+1,j])
769 glVertex3f( X_shift[i,j+1], Z_shift[i,j+1],Y_shift[i,j+1] )
770 glVertex3f( X_shift[i+1,j], Z_shift[i+1,j],Y_shift[i+1,j] )
771 glVertex3f( X_shift[i,j+1], Z_shift[i,j+1],Y_shift[i,j+1])
772 glVertex3f( X_shift[i+1,j+1], Z_shift[i+1,j+1],Y_shift[i+1,j+1] )
773 glEnd()
774 glDisable(GL_POLYGON_OFFSET_FILL);
775
776
777 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
778 glEnable(GL_LIGHTING)
779
780 class plot3_points(figure) :
781 """ class for plotting points in 3d"""
782 def __init__(self,Points,colors = Colors,linewidth = 0.1,pointsize=5,precision=3,num_ticks=5):
783 self.Colors = colors
784 self.linewidth= linewidth
785 self.pointsize = pointsize
786 self.precision = precision
787 self.num_ticks = num_ticks
788 self.Rescale(Points)
789 self.make_plot(colors)
790 return
791
792 def Rescale(self,Points) :
793 self.xmin = min(Points[:,0])
794 self.xmax = max(Points[:,0])
795 self.ymin = min(Points[:,1])
796 self.ymax = max(Points[:,1])
797 self.zmin = min(Points[:,2])
798 self.zmax = max(Points[:,2])
799
800
801 self.Points = N.array(Points)
802 self.Points[:,0] = (self.Points[:,0]-self.xmin)/abs(self.xmax-self.xmin)
803 self.Points[:,1] = (self.Points[:,1]-self.ymin)/abs(self.ymax-self.ymin)
804 self.Points[:,2] = (self.Points[:,2]-self.zmin)/abs(self.zmax-self.zmin)
805
806 def drawplot(self) :
807 Points = self.Points - 0.5
808
809 glDisable(GL_LIGHTING)
810 glColor3f(0,0,1.0)
811 glPointSize(self.pointsize)
812 glBegin(GL_POINTS)
813 for i in range(Points.shape[0]) :
814 self.SetColor(Points[i,2])
815 glVertex3f(Points[i,0],Points[i,2],Points[i,1])
816 glEnd()
817 glEnable(GL_LIGHTING)
818
819 class plot3(figure) :
820 """ similar to matlab plot3 functionality"""
821 def __init__(self,X,Y,Z,colors = Colors,linewidth = 0.1,precision=3,num_ticks=5):
822 self.Colors = colors
823 self.linewidth= linewidth
824 self.precision = precision
825 self.num_ticks = num_ticks
826 self.Rescale(X,Y,Z)
827 self.make_plot(colors)
828 return
829
830 def drawplot(self) :
831 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE)
832 glDisable(GL_LIGHTING)
833
834 glBegin(GL_LINES)
835
836 glColor3f(self.Colors[0,0], self.Colors[0,1], self.Colors[0,2])
837
838 X_shift = self.X-0.5
839 Y_shift = self.Y-0.5
840 Z_shift = self.Z-0.5
841
842 plotsize = N.size(self.X)
843 plot_range = range(plotsize-1)
844
845 if len(self.X.shape) == 1 :
846 for i in plot_range:
847 glVertex3f( X_shift[i],Z_shift[i],Y_shift[i])
848 glVertex3f( X_shift[i+1],Z_shift[i+1],Y_shift[i+1])
849
850 else :
851 num_lines = self.X.shape[0]
852 num_points = self.X.shape[1]
853 for i in range(num_lines):
854 self.SetColor(i/(float)(num_lines))
855 for j in range(num_points-1):
856 glVertex3f( X_shift[i,j],Z_shift[i,j],Y_shift[i,j])
857 glVertex3f( X_shift[i,j+1],Z_shift[i,j+1],Y_shift[i,j+1])
858
859 glEnd()
860 glEnable(GL_LIGHTING)
861
862 class plotrbf(figure,mesh) :
863 """Class written to visualise some radial basis function interpolations """
864 def __init__(self,X,Y,Z,Points,colors = Colors,linewidth=0.1,fill_mesh = 0,pointsize=5,precision=3,num_ticks=5):
865 self.Colors = colors
866 self.linewidth= linewidth
867 self.fill_mesh = fill_mesh
868 self.pointsize = pointsize
869 self.precision = precision
870 self.num_ticks = num_ticks
871 self.Rescale(X,Y,Z,Points)
872 self.make_plot(colors)
873 return
874
875 def Rescale(self,X,Y,Z,Points) :
876 figure.Rescale(self,X,Y,Z)
877 self.Points = N.array(Points)
878
879 self.Points[:,0] = (self.Points[:,0]-self.xmin)/abs(self.xmax-self.xmin)
880 self.Points[:,1] = (self.Points[:,1]-self.ymin)/abs(self.ymax-self.ymin)
881 self.Points[:,2] = (self.Points[:,2]-self.zmin)/abs(self.zmax-self.zmin)
882
883
884 def drawplot(self) :
885 mesh.drawplot(self)
886
887
888 Points = self.Points - 0.5
889
890 glDisable(GL_LIGHTING)
891 glColor3f(0,0,0)
892 glPointSize(self.pointsize)
893 glBegin(GL_POINTS)
894 for i in range(len(Points[0])) :
895 glVertex3f(Points[i,0],Points[i,2],Points[i,1])
896 glEnd()
897 glEnable(GL_LIGHTING)
898
899