source: inundation/ga/storm_surge/pmesh/pmesh.py @ 830

Last change on this file since 830 was 830, checked in by prow, 20 years ago

Making unvisualise redraw the mesh

File size: 64.1 KB
Line 
1import  Pmw, AppShell, math, time, string, marshal
2from toolbarbutton import ToolBarButton
3import tkFileDialog
4from   tkSimpleDialog import Dialog
5import mesh
6from Tkinter import  FALSE,TRUE, Frame,X, LEFT,YES,BOTH,ALL,Widget,CURRENT, Label,W, Entry, E, StringVar, END, Checkbutton, Radiobutton, IntVar
7#from cursornames import TLC,TRC, BLC, BRC, TS, RS, LS, BS
8from tkMessageBox import showerror, _show, QUESTION,YESNOCANCEL
9import types
10import visualmesh
11import os
12import profile
13
14
15# CONSTANTS
16VERT_SELECT_ADDING_SEG_COLOR = 'orange'
17SELECT_COLOR = 'red'
18SEG_COLOUR = 'blue'
19TRIANGLE_COLOUR = 'green'
20APPLICATION_NAME = 'Pmesh'
21SET_COLOUR = 'red'
22DEFAULT_ATTRIBUTE = 'elevation'
23
24NO_SELECTION = 0
25AUTO = 1
26SET_ALPHA = 2
27
28class Draw(AppShell.AppShell):
29    usecommandarea = 1
30    appname        = APPLICATION_NAME
31    frameWidth     = 840
32    frameHeight    = 600
33   
34   
35    def createButtons(self):
36        """
37        Add buttons to the bottom of the GUI
38        """
39        self.buttonAdd('Postscript',
40              helpMessage='Save current drawing (as PostScript)',
41              statusMessage='',
42              command=self.ipostscript)
43        self.buttonAdd('Clear', helpMessage='Delete the mesh',
44              statusMessage='', command=self.clearMesh)
45        self.buttonAdd('Close', helpMessage='Close Screen',
46              statusMessage='', command=self.close)
47       
48    def createBase(self):
49        """
50        Create the GUI framework.  Set up the GUI
51        """
52        self.toolbar = self.createcomponent('toolbar', (), None,
53                  Frame, (self.interior(),), background="gray90")
54        self.toolbar.pack(fill=X)
55
56        self.scrolledcanvas =  self.createcomponent('ScrolledCanvas', (), None,
57                                       Pmw.ScrolledCanvas, (self.interior(),)
58                                       ,borderframe = 1
59                                       ,labelpos = 'n'
60                                       )
61        self.scrolledcanvas.configure(hscrollmode = 'dynamic')
62        self.scrolledcanvas.configure(vscrollmode = 'dynamic')
63        self.scrolledcanvas.pack(side=LEFT, expand=YES, fill=BOTH)
64        self.canvas = self.scrolledcanvas.component('canvas')
65        self.canvas.configure( background="white" )
66       
67        self.canvas.pack(side=LEFT, expand=YES, fill=BOTH)
68
69        Widget.bind(self.canvas, "<Button-1>", self.mouseDown)
70        Widget.bind(self.canvas, "<Button3-ButtonRelease>", self.rightMouseUp)
71        Widget.bind(self.canvas, "<Button2-ButtonRelease>",self.DeleteSelectedMeshObject)
72        # "<Delete>" didn't work..
73        #Widget.bind(self.canvas, "<Delete>", self.DeleteSelectedMeshObject)
74
75        #self.root.bind("<KeyPress>", self.setRegular)
76        #self.root.bind("<KeyRelease>", self.setRegular)
77       
78        self.scrolledcanvas.resizescrollregion()
79
80#     def setRegular(self, event):
81#         if event.type == '2' and event.keysym == 'Shift_L':
82#             self.regular = TRUE
83#         else:
84#             self.regular = FALSE
85
86    def createMenus(self):
87        """
88        Add menus to the top of the GUI
89        """
90        self.menuBar.deletemenuitems('File',0)
91        self.menuBar.addmenuitem('File', 'command', 'New mesh',
92                                 label='New', command=self.clearMesh)
93        self.menuBar.addmenuitem('File', 'command', 'Open mesh',
94                                 label='Open...', command=self.importFile)
95        self.menuBar.addmenuitem('File', 'command', 'Save mesh',
96                                 label='Save', command=self.saveDrawing)
97        self.menuBar.addmenuitem('File', 'command', 'Save mesh',
98                                 label='SaveAs...', command=self.saveAsDrawing)
99       
100        self.menuBar.addmenuitem('File', 'separator')
101        self.menuBar.addmenuitem('File', 'command',
102                                 'Add ungenerated file from arcGIS',
103                                 label='Add ungenerated file...',
104                                 command=self.ImportUngenerate)
105       
106        self.menuBar.addmenuitem('File', 'command',
107                                 'Export ASCII obj',
108                                 label='Export ASCII obj',
109                                 command=self.exportObj)
110       
111        self.menuBar.addmenuitem('File', 'command',
112                                 'Export ASCII segment outline',
113                                 label='Export ASCII segment outline...',
114                                 command=self.exportASCIIsegmentoutlinefile)
115       
116        self.menuBar.addmenuitem('File', 'command',
117                                 'Export ASCII xya file',
118                                 label='Export ASCII xya file...',
119                                 command=self.exportxyafile)
120       
121        self.menuBar.addmenuitem('File', 'command',
122                                 'add Segments to connect all vertices'  ,
123                                 label='join vertices',
124                                 command=self.joinVertices)
125        self.menuBar.addmenuitem('File', 'command',
126                                 'add Segments to form alpha shape'  ,
127                                 label='Auto segment',
128                                 command=self.autoSegment)
129        self.menuBar.addmenuitem('File', 'command', 'Normalise mesh',
130                                 label='Normalise mesh', command=self.normaliseMesh)
131        self.menuBar.addmenuitem('File', 'command', 'Normalise mesh for glutobj',
132                                 label='Normalise mesh for glutobj', command=self.normalise4ObjMesh)
133        self.menuBar.addmenuitem('File', 'separator')
134        self.menuBar.addmenuitem('File', 'command', 'Exit program',
135                                 label='Exit', command=self.quit)
136
137    def createTools(self):
138        """
139        Add buttons to the top of the GUI
140        """
141        self.mouseDownFunc = {}
142        self.modeClass = {}
143        ToolBarButton(self, self.toolbar, 'sep', 'sep.gif',
144                      width=10, state='disabled')
145        for key, balloon, mouseDownFunc, Mode in [
146            ('pointer','Edit drawing eventually.  Right now this does nothing', self.drag, None)
147            ,('vertex',    'Vertex mode', self.drawVertex, mesh.Vertex)
148            ,('segment', 'Segment mode',self.selectSegmentPoint, mesh.Segment)
149            ,('hole', 'hole mode',self.drawHole, mesh.Hole)
150            ,('region', 'region mode',self.drawRegion, mesh.Region)
151            ]:
152            t = ToolBarButton(self, self.toolbar, key, '%s.gif' % key,
153                          command=self.selectFunc, balloonhelp=balloon,
154                               statushelp='')
155            t.cycle("DrawMode")
156            if key == 'pointer': #FIXME- this is specified in line 1062 as well
157                                 # self.selectFunc('pointer')
158                self.curFunc  = self.drawVertex
159                t.setInitialSunkenButton("DrawMode")
160            self.modeClass[key] = Mode
161            # for actions that occur when the mouse goes down
162            self.mouseDownFunc[key] = mouseDownFunc
163         
164    def createZooms(self):
165        """
166        Add zoom buttons to the top of the GUI
167        """
168        ToolBarButton(self, self.toolbar, 'sep', 'sep.gif', width=10,
169                      state='disabled')
170        zoom = '0.5'
171        ToolBarButton(self, self.toolbar, zoom, 'zoom%s.gif' %
172                      zoom, command=self.selectZoom,
173                      balloonhelp='*%s zoom' % zoom,
174                      statushelp='')
175           
176        ToolBarButton(self, self.toolbar,'1.0', 'zoomToMesh.gif',
177                      command=self.ResizeToFitWrapper,
178                      balloonhelp='Zooms to mesh size',
179                      statushelp='')
180        zoom = '2'
181        ToolBarButton(self, self.toolbar, zoom, 'zoom%s.gif' %
182                      zoom, command=self.selectZoom,
183                      balloonhelp='*%s zoom' % zoom,
184                      statushelp='')
185
186    def createEdits(self):
187        """
188        Add Edit buttons to the top of the GUI
189        """
190        ToolBarButton(self, self.toolbar, 'sep', 'sep.gif', width=10,
191                      state='disabled')
192        for key, func, balloon in [
193                ('addVertex', self.windowAddVertex, 'add Vertex'),
194                ('edit', self.windowEdit, 'edit selected object'),
195                ('default', self.windowDefault, 'set default value for selected mode'),
196                ('joinVer', self.joinVerticesButton, 'add Segments to connect all vertices'),     
197             #   ('autoSegHull', self.autoSegmentHullButton, 'add Segments to form alpha shape, using Hull'), 
198             #   ('autoSeg', self.autoSegmentButton, 'add Segments to form alpha shape'),
199                ('autoSegGiveAlpha', self.autoSegmentGiveAlphaButton, 'add Segments to form alpha shape, specify alpha'),
200                ('meshGen', self.windowMeshGen, 'Generate Mesh')]:
201            ToolBarButton(self, self.toolbar, key, '%s.gif' % key,
202                          command=func, balloonhelp=balloon,
203                               statushelp='' )
204
205
206
207    def createSetTools(self):
208        """
209        Add set tool buttons to the top of the GUI
210        """
211        ToolBarButton(self, self.toolbar, 'sep', 'sep.gif', width=10,
212                      state='disabled')
213        for key, func, balloon in [
214                ('threshold', self.threshold, 'threshold the set'),
215                ('Courant_threshold', self.Courant_threshold, 'Courant_threshold the set'),
216                ('gradient_threshold', self.gradient_threshold, 'gradient_threshold the set'),
217                ('polyset', self.triangles_to_polySet, 'make a poly set out of selected triangles')]:     
218                #('refineSet', self.refineSet, 'Refine the set')]:
219            ToolBarButton(self, self.toolbar, key, '%s.gif' %key,
220                          command=func, balloonhelp=balloon,
221                               statushelp='' )
222
223    def createSetIcons(self):
224        """
225        Add Edit buttons to the top of the GUI
226        """
227        ToolBarButton(self, self.toolbar, 'sep', 'sep.gif', width=10,
228                      state='disabled')
229        for key, func, balloon in [
230                ('selectAllTriangles', self.selectAllTriangles, 'select all'),
231                ('none', self.clearSelection, 'clear selection')]:
232            ToolBarButton(self, self.toolbar, key, '%s.gif' %key,
233                          command=func, balloonhelp=balloon,
234                               statushelp='' )
235
236    def createVisualiseIcons(self):
237        """
238        Add Edit buttons to the top of the GUI
239        """
240        ToolBarButton(self, self.toolbar, 'sep', 'sep.gif', width=10,
241                      state='disabled')
242        for key, func, balloon in [
243                ('visualise', self.visualise, 'Visualise mesh triangles'),
244                ('unvisualise', self.unvisualise, 'Do not visualise mesh triangles (for large meshes)')]:
245            ToolBarButton(self, self.toolbar, key, '%s.gif' %key,
246                          command=func, balloonhelp=balloon,
247                               statushelp='' )
248
249
250    def refineSet(self,parent):
251        self.mesh.refineSet(self.selSet)
252        self.visualiseMesh(self.mesh)
253
254
255    def setStructureNumber(self,parent):
256        dialog =  setStructureNumberDialog(self.canvas)
257        if dialog.numberOK:
258            self.structureSize = dialog.number
259
260    def erode(self, parent):
261#Not implimented
262        self.canvas.delete(ALL)
263        self.mesh.erode(self.selSet,structureSize=self.structureSize)
264        self.visualiseMesh(self.mesh)
265
266
267    def dilate(self, parent):
268#Not implimented
269        self.canvas.delete(ALL)
270        self.mesh.dilate(self.selSet,structureSize=self.structureSize)
271        self.visualiseMesh(self.mesh)
272
273    def general_threshold(self,parent,function,function_description):
274        """
275        add a vertex using a window and entering x y values.
276
277        the parent attribute isn't used by this function.
278        need to userstand toolbarbutton.py to know how to
279        get rid of it.
280        """
281        if self.selSet == 'None':
282            self.selectAllTriangles(parent)
283
284        dialog = GeneralThresholdDialog(self.canvas,self.mesh.attributeTitles,function_description)
285        if dialog.minmaxValuesOk:
286            self.canvas.delete(ALL)
287            min = dialog.min
288            max = dialog.max
289            attribute_name = dialog.attribute_name
290            self.mesh.general_threshold(self.selSet,min=min,max=max,attribute_name = attribute_name,function=function)
291            self.visualiseMesh(self.mesh)
292
293    def threshold(self, parent):
294        """
295        add a vertex using a window and entering x y values.
296
297        the parent attribute isn't used by this function.
298        need to userstand toolbarbutton.py to know how to
299        get rid of it.
300        """
301        function = self.mesh.av_att
302        function_description = 'average attribute of triangle'
303        self.general_threshold(parent,function,function_description)
304
305
306    def Courant_threshold(self, parent):
307        """
308        add a vertex using a window and entering x y values.
309
310        the parent attribute isn't used by this function.
311        need to userstand toolbarbutton.py to know how to
312        get rid of it.
313        """
314        function = self.mesh.Courant_ratio
315        function_description = 'average attribute/area of triangle'
316        self.general_threshold(parent,function,function_description)
317
318    def gradient_threshold(self, parent):
319        """
320        add a vertex using a window and entering x y values.
321
322        the parent attribute isn't used by this function.
323        need to userstand toolbarbutton.py to know how to
324        get rid of it.
325        """
326        function = self.mesh.Gradient
327        function_description = 'average gradient of triangle'
328        self.general_threshold(parent,function,function_description)
329
330    def triangles_to_polySet(self,parent):
331        vertices, segments = self.mesh.triangles_to_polySet(self.selSet)
332        event = None
333        for v in vertices.keys():
334            x = v.x*self.SCALE
335            y = v.y*self.SCALE
336            vertices[v]=self.drawVertex(x,y,event)
337        for s in segments:
338            v0 = vertices[s[0]]
339            v1 = vertices[s[1]]
340            self.drawSegment(v0,v1)
341
342    def selectTriangles(self,setName):
343        """
344        """
345        self.canvas.delete(ALL)
346        self.selSet = setName
347        self.visualiseMesh(self.mesh)
348
349    def selectAllTriangles(self,parent):
350        """
351        selected all triangles in the mesh
352        """
353        self.canvas.delete(ALL)
354        self.selSet = self.mesh.selectAllTriangles()
355        self.visualiseMesh(self.mesh)
356
357    def clearSelection(self,parent):
358    #FIXME looks like self.clearSelections - change name (Peter)
359        """
360        """
361        self.canvas.delete(ALL)
362        self.selSet = self.mesh.clearSelection()
363        self.visualiseMesh(self.mesh)
364
365    def visualise(self,parent):
366        self.canvas.delete(ALL)
367        self.Visualise = True
368        self.visualiseMesh(self.mesh)
369
370    def unvisualise(self,parent):
371        self.canvas.delete(ALL)
372        self.Visualise = False
373        self.visualiseMesh(self.mesh)
374
375    def createMesh(self):
376        """
377        Build the data structures for storing the mesh objects
378        """
379        self.mesh = mesh.Mesh()
380       
381        self.Vertices = visualmesh.vPoints(mesh.Vertex)
382        self.Segments = visualmesh.vSegments(mesh.Segment)
383        self.Holes = visualmesh.vPoints(mesh.Hole)
384        self.Regions = visualmesh.vRegions(mesh.Region)
385        self.UserMesh = visualmesh.vMesh([self.Vertices,self.Segments,self.Holes,self.Regions])
386       
387        self.Triangles = visualmesh.vTriangles(mesh.Triangle)
388        self.selSet='None'
389
390
391    def deleteMesh(self):
392        """
393        Delete the data structures for storing the mesh objects
394        """
395        self.mesh = None
396        self.Vertices = None
397        self.Segments = None
398        self.Triangles = None
399       
400    def addVertsAndSegs(self):
401        """
402        Automatically add some verts and segs to the mesh.Used in Debugging
403        """
404        v1 = self.drawVertex(0,0,None)
405        v2 = self.drawVertex(0,200,None)
406        v3 = self.drawVertex(200,0,None)
407        v3 = self.drawVertex(300,100,None)
408        self.drawSegment(v1,v2)
409        self.drawSegment(v1,v3)
410        self.drawSegment(v2,v3)
411        #Since the new vertex may be off screen
412        self.scrolledcanvas.resizescrollregion()
413       
414    def selectFunc(self, tag):
415        """
416        Change the current mode class
417        When changing from one mode to another
418        """
419        self.mouseDownCurFunc = self.mouseDownFunc[tag]
420        self.curModeClass = self.modeClass[tag]
421        self.clearSelections()
422        self.canvas.config(cursor='arrow')
423#        I can make it arrow, but it will change back to pointer, after
424#        adding an object
425#        if self.curFunc == self.func['pointer']:
426#            self.canvas.config(cursor='arrow')
427#         else:
428#             self.canvas.config(cursor='crosshair')
429
430    def clearSelections(self):
431        """
432        deselect objects that have been selected
433        """
434        if self.selMeshObject:
435            self.deselectMeshObject(self.selMeshObject, self.selMeshTag)       
436        if self.selVertex:
437            self.deselectVertex(self.selVertex, self.selVertexTag)
438         
439       
440    def selectZoom(self, tag):
441        """
442        Zoom in or out of the current mesh view
443        """
444        fraction = string.atof(tag)
445        self.SCALE *= fraction
446        self.scrolledcanvas.scale(ALL, 0, 0, fraction, fraction)
447
448        # Redraw all of the vertices, holes and regions,
449        #so the squares representing vertices
450        # don't get bigger
451        vertices = self.mesh.getUserVertices()
452        holes = self.mesh.getHoles()
453        regions = self.mesh.getRegions()
454        MeshObjects  = vertices + holes + regions
455
456        # make a list of tags to delete
457        guiIDs = [getattr(MeshObjects[i],'guiID') for i in xrange(len(MeshObjects))]
458        apply(self.canvas.delete, guiIDs)
459        for obj in MeshObjects:
460            if self.selVertex == obj:
461                obj.draw(self.canvas,obj.guiID,  scale =self.SCALE ,colour= VERT_SELECT_ADDING_SEG_COLOR)
462            elif self.selMeshObject == obj:
463                obj.draw(self.canvas,obj.guiID,  scale =self.SCALE ,colour= SELECT_COLOR)
464            else:
465                obj.draw(self.canvas,obj.guiID,  scale =self.SCALE ) 
466        top, bottom = self.scrolledcanvas.xview()
467        xcenter  = (top + bottom)/2
468        xdiff =  xcenter - top 
469        xcnew = xcenter - xdiff/fraction
470       
471        top, bottom = self.scrolledcanvas.yview()
472        ycenter = (top + bottom)/2
473        ydiff = ycenter - top
474        ycnew = ycenter - ydiff/fraction
475       
476        self.scrolledcanvas.resizescrollregion()
477        # update so the moveto calls will work...
478        self.scrolledcanvas.update()
479        # but calling update now does make things jerky
480        self.canvas.xview_moveto(xcnew)
481        self.canvas.yview_moveto(ycnew)
482       
483   
484    def windowAddVertex (self, parent):
485        """
486        add a vertex using a window and entering x y values.
487
488        the parent attribute isn't used by this function.
489        need to userstand toolbarbutton.py to know how to
490        get rid of it.
491        """
492       
493        dialog = AddVertexDialog(self.canvas)
494        if dialog.xyValuesOk:
495            print dialog.x
496            print dialog.y
497            self.drawVertex(dialog.x*self.SCALE,dialog.y*self.SCALE,None)
498            #Since the new vertex may be off screen
499            self.ResizeToFit()
500   
501    def windowDefault (self, parent):
502        """
503       
504        the parent attribute isn't used by this function.
505        need to userstand toolbarbutton.py to know how to
506        get rid of it.
507        """
508        # self.UserMesh is a vMesh instance
509        self.UserMesh.defaultWindow(self.canvas, self.curModeClass)
510   
511    def windowEdit (self, parent):
512        """
513
514        the parent attribute isn't used by this function.
515        need to userstand toolbarbutton.py to know how to
516        get rid of it.
517        """
518        if self.selMeshObject:   
519            self.UserMeshChanged = self.UserMesh.editWindow(self.canvas,
520                                     self.selMeshObject,
521                                     self.UserMeshChanged)
522   
523   
524    def autoSegmentHullButton (self, parent):
525        self.autoSegment()
526 
527    def autoSegmentHull (self):
528        """
529        add Segments to bound all vertices
530       
531        the parent attribute isn't used by this function.
532        need to userstand toolbarbutton.py to know how to
533        get rid of it.
534        """
535        if len(self.mesh.getUserVertices()) >= 3:
536            newsegs = self.mesh.autoSegment()
537            for segment in newsegs:
538                self.serial +=1
539                self.uniqueID = 'M*%d' % self.serial
540                self.Segments.visualise(segment,
541                                        self.uniqueID,
542                                        self.canvas,
543                                        self.SCALE)
544        else:
545            showerror('pMesh',
546                      'Three or more vetices are needed to be able to autosegment.')
547 
548    def autoSegmentButton (self, parent):
549        self.autoSegment()
550
551       
552    def autoSegmentGiveAlphaButton (self, parent):
553        dialog = AutoSegmentDialog(self.canvas, self.meshLastAlpha)
554        if dialog.var.get() == SET_ALPHA:
555            if dialog.alphaValueOk:
556                self.autoSegment(alpha = dialog.alpha)
557            else:
558                 showerror('pMesh',
559                      'Bad alpha value.')
560        else:
561            self.autoSegment()
562           
563       
564    def autoSegment (self, alpha = None):
565        """
566        add Segments to bound all vertices
567       
568        the parent attribute isn't used by this function.
569        need to userstand toolbarbutton.py to know how to
570        get rid of it.
571        """
572        if len(self.mesh.getUserVertices()) >= 3:
573            if alpha == None:
574                newsegs, ObjectsToVisuallyDelete, self.meshLastAlpha = self.mesh.autoSegment()
575            else:
576                newsegs, ObjectsToVisuallyDelete, self.meshLastAlpha = self.mesh.autoSegment(alpha)
577               
578            #print "newsegs",newsegs
579            #print "ObjectsToVisuallyDelete",ObjectsToVisuallyDelete
580           
581            for drawOb in ObjectsToVisuallyDelete:
582                    self.UserMesh.unvisualise(drawOb, self.canvas)
583               
584            for segment in newsegs:
585                self.serial +=1
586                self.uniqueID = 'M*%d' % self.serial
587                self.Segments.visualise(segment,
588                                        self.uniqueID,
589                                        self.canvas,
590                                        self.SCALE)
591           
592        else:
593            showerror('pMesh',
594                      'Three or more vetices are needed to be able to autosegment.')
595
596
597    def joinVerticesButton (self, parent):
598        self.joinVertices()
599       
600    def joinVertices (self):
601        """
602        add Segments to connect all vertices
603       
604        the parent attribute isn't used by this function.
605        need to userstand toolbarbutton.py to know how to
606        get rid of it.
607        """
608        if len(self.mesh.getUserVertices()) >= 3:
609            newsegs = self.mesh.joinVertices()
610            for segment in newsegs:
611                self.serial +=1
612                self.uniqueID = 'M*%d' % self.serial
613                self.Segments.visualise(segment,
614                                        self.uniqueID,
615                                        self.canvas,
616                                        self.SCALE)
617        else:
618            showerror('pMesh',
619                      'Three or more vetices are needed to be able to join vertices.')
620       
621    def windowMeshGen (self, parent):
622        """
623        The parent attribute isn't used by this function.
624        need to understand toolbarbutton.py to know how to
625        get rid of it.
626        """
627        # Put exceptions round things.
628        #catch failure in self.mesh.generateMesh
629        dialog = MeshGenDialog(self.canvas,
630                               self.MeshMinAngle,
631                               self.MeshMaxArea,
632                               self.MeshnumTriangles,
633                               self.MeshMaxAreaLast)
634       
635        if dialog.ValuesOk:
636            print dialog.minAngle
637            print dialog.maxArea
638           
639            self.clearSelections()
640            self.canvas.delete(ALL)
641            if dialog.goodMaxArea == True:
642                self.MeshMinAngle = dialog.minAngle
643                self.MeshMaxArea = dialog.maxArea
644                self.MeshMaxAreaLast = True
645               
646                self.mesh = self.MeshGenAreaAngle (dialog.minAngle,
647                                          dialog.maxArea,
648                                          self.mesh)
649            elif dialog.goodNumTriangles == True:
650                self.MeshMinAngle = dialog.minAngle
651                self.MeshnumTriangles  = dialog.numTriangles
652                self.MeshMaxAreaLast = False
653               
654                self.mesh = self.MeshGenAreaNumTriangles (dialog.minAngle,
655                                          dialog.numTriangles,
656                                          self.mesh)
657            else:
658                pass
659            print "userMeshChanged = False"
660            self.UserMeshChanged = False
661            self.visualiseMesh(self.mesh)
662            print "Mesh Generation finished"
663           
664    def MeshGenAreaAngle (self, minAngle, maxArea, mesh):
665        """
666        Generate a mesh, given a minAngle and max area
667        """
668        tempMesh = mesh
669        try:
670            tempMesh.generateMesh(mode = "pzq"+str(minAngle)
671                                  +"a"+str(maxArea)
672                                  +"a") #So areas for regions will be used
673        except AttributeError : # can't catch PyEval_RestoreThread
674            # This doesn't catch tempMesh.generateMesh failing
675            tempMesh = mesh
676        return tempMesh
677       
678
679    def MeshGenAreaNumTriangles (self, minAngle, numTriangles, mesh):
680        """
681        Generate a mesh, given a minAngle and rough # of triangles
682        """
683        #get big triangles
684        #calc area
685        #calc max triangle area
686        #
687        tempMesh = mesh
688        try:
689            tempMesh.generateMesh("pzq1")
690        except AttributeError : # can't catch PyEval_RestoreThread
691            # This doesn't catch tempMesh.generateMesh failing
692            pass
693        meshArea = 0
694        for triangle in tempMesh.getTriangulation():
695             meshArea += triangle.calcArea()
696        print "meshArea: ", meshArea
697
698        maxArea = meshArea/numTriangles
699
700       
701        return self.MeshGenAreaAngle (minAngle,
702                                      maxArea,
703                                      self.mesh)
704       
705    def mouseDown(self, event):
706        """
707        On a mouse down event, depending on the current state,
708        either add a vertex or a seg etc
709        """
710        self.curObject = None
711        self.lastx = self.startx = self.canvas.canvasx(event.x)
712        #The screen canvas has y 'flipped'.  -1* unflips it
713        self.lasty = self.starty = -1*self.canvas.canvasy(event.y)
714        print "----------------------"
715        self.mouseDownCurFunc( self.lastx,
716                               self.lasty,event) #!!! remove the event?
717                                                 # do last
718   
719    def rightMouseUp(self, event):
720        """
721        On a right mouse button up event select the nearest object.
722        """
723        found=False
724        if event.widget.find_withtag(CURRENT): # if there's a widget with a tag
725            [tag,string] = self.canvas.gettags(CURRENT) # get a list of them
726            print "tag",tag  #tags ('M*1008', 'current')
727            if tag[:2] == 'M*':   #!!! this can be removed when there are
728                #    only mesh objects on screen
729                #key, value = string.split(tag, '*')
730                objectID = tag
731                print "Found!! objectID:", objectID
732               
733                meshObjects = self.getAllUserMeshObjects()
734                # It may be a triangle, which is ignored
735                if meshObjects.hasKey(objectID):
736                    selMeshObject = meshObjects.getMeshObject(objectID)
737                    found = True
738                    print "Found! selMeshObject", selMeshObject
739                    #Only select one object at a time
740                    if self.selMeshObject:
741                        self.deselectMeshObject(self.selMeshObject, self.selMeshTag)
742                    self.selectMeshObject(selMeshObject,objectID)
743
744    def getAllUserMeshObjects(self):
745        return self.UserMesh
746       
747    def DeleteSelectedMeshObject(self, event):
748        """
749        if an object is selected, delete it.
750        """
751        if self.selMeshObject:
752            #an object is selected
753            #first deselect the vertex, for selecting a segment
754            if self.selVertex:
755                self.deselectVertex(self.selVertex, self.selVertexTag)
756            ObjectsToVisuallyDelete = self.mesh.deleteMeshObject (self.selMeshObject)
757            for drawOb in ObjectsToVisuallyDelete:
758                self.UserMesh.unvisualise(drawOb, self.canvas)
759               
760            self.selMeshObject = None
761            self.selMeshTag = None
762           
763    def selectMeshObject(self, meshObject, objectID):
764        """
765        selected a mesh object.
766        """
767        self.canvas.delete(objectID)
768        self.selMeshObject = meshObject
769        self.selMeshTag = objectID
770        meshObject.draw(self.canvas,objectID, scale =self.SCALE ,colour = SELECT_COLOR)
771   
772    def deselectMeshObject(self, meshObject, objectID):
773        """
774        deselected a mesh object.
775        """
776        self.canvas.delete(objectID)
777        self.selMeshObject = None
778        self.selMeshTag = None
779        if isinstance(meshObject, mesh.Segment):
780            meshObject.draw(self.canvas,objectID,
781                        scale =self.SCALE ,colour = SEG_COLOUR)
782        else:
783            meshObject.draw(self.canvas,objectID,
784                        scale =self.SCALE )
785           
786    def drag(self,x,y,event):
787        """
788        Hack function.  called when in select and left mouse goes down
789        """
790        pass
791   
792    def drawVertex(self,x,y,event):
793        """
794        draw a vertex object, plus add it to the mesh data structure
795
796        event isn't used
797        """
798        self.serial +=1
799        self.uniqueID = 'M*%d' % self.serial
800        vert = self.Vertices.draw(x,y,self.mesh,self.uniqueID,self.SCALE,self.canvas,event)
801        self.UserMeshChanged = True
802        return vert
803     
804    def drawHole(self,x,y,event):
805        """
806        draw a hole object, plus add it to the mesh data structure
807
808        event isn't used
809        """
810        self.serial +=1
811        self.uniqueID = 'M*%d' % self.serial
812        self.userMeshChanged = True
813        hole = self.Holes.draw(x,y,self.mesh,self.uniqueID,self.SCALE,self.canvas,event)
814        return hole   
815   
816    def drawRegion(self,x,y,event):
817        """
818        draw a region object, plus add it to the mesh data structure
819
820        event isn't used
821        """
822        self.serial +=1
823        self.uniqueID = 'M*%d' % self.serial
824        region = self.Regions.draw(x,y,self.mesh,self.uniqueID,self.SCALE,self.canvas,event)
825        return region
826   
827    def selectSegmentPoint(self,x,y, event):
828        """
829        logic when selecting a vertex object to add a segment
830        """
831        found=False
832        if event.widget.find_withtag(CURRENT): # if there's a widget with a tag
833            [tag,string] = self.canvas.gettags(CURRENT) # get a list of them
834            print "tag",tag  #tags ('M*1008', 'current')
835            objectID = tag
836            #print "Found!! objectID:", objectID
837            if self.Vertices.hasKey(objectID): #isinstance(self.meshObjects[objectID],mesh.Vertex):
838                vertex = self.Vertices.getMeshObject(objectID)
839                found = True
840                print "Found! vertex", vertex
841           
842        if found and self.selVertex == vertex:
843            print "The selected vertex has already been selected"
844            #The selected vertex has already been selected
845            # therefore deselect it
846            self.deselectVertex(self.selVertex, self.selVertexTag)
847            found = False
848                 
849        if found: 
850            #A vertex has been selected!
851            if self.selVertex:
852                if self.mesh.isUserSegmentNew(self.selVertex,vertex):
853                    #vertex is the 2nd vertex
854                    self.drawSegment(vertex,self.selVertex)
855                    self.deselectVertex(self.selVertex, self.selVertexTag)
856                    self.selectVertex(vertex,objectID)
857            else:
858                print "vertex is the 1st vertex" 
859                #vertex is the 1st vertex
860                self.selectVertex(vertex,objectID)
861        else:
862            print " There are no widgets.  This happen's too much"
863                   
864
865    def selectVertex(self, vertex,objectID):
866        """
867        select a vertex object when adding a segment
868        """
869        self.canvas.delete(objectID)
870        self.selVertex = vertex
871        self.selVertexTag = objectID
872        vertex.draw(self.canvas,objectID, scale =self.SCALE ,colour = VERT_SELECT_ADDING_SEG_COLOR)
873   
874    def deselectVertex(self, vertex,objectID):
875        """
876        deselect a vertex object when adding a segment
877        """
878        self.canvas.delete(objectID)
879        self.selVertex = None
880        self.selVertexTag = None
881        vertex.draw(self.canvas,objectID,  scale =self.SCALE )
882         
883    def drawSegment(self,v1,v2):
884        """
885        Create a seg object, draw it and add it to the mesh data structure
886        """
887        self.serial +=1
888        self.uniqueID = 'M*%d' % self.serial
889        self.userMeshChanged = True
890        seg = self.Segments.draw(v1,v2,self.mesh,self.uniqueID,self.SCALE,self.canvas,None)
891        return seg
892
893    def visualiseMesh(self,mesh):
894        """
895        visualise vertices, segments, triangulation, holes
896        """
897        if self.Visualise:
898            for triangle in mesh.getTriangulation():
899                self.serial +=1
900                self.uniqueID = 'M*%d' % self.serial
901                self.Triangles.visualise(triangle,
902                                        self.uniqueID,
903                                        self.canvas,
904                                        self.SCALE)
905
906        if self.Visualise:
907            Triangles = mesh.sets[mesh.setID[self.selSet]]
908            for triangle in Triangles:
909                triangle.draw(self.canvas,1,
910                              scale = self.SCALE,
911                              colour = SET_COLOUR)
912
913        for segment in mesh.getUserSegments():
914            self.serial +=1
915            self.uniqueID = 'M*%d' % self.serial
916            self.Segments.visualise(segment,
917                                    self.uniqueID,
918                                    self.canvas,
919                                    self.SCALE)
920        for vertex in mesh.getUserVertices():
921            self.serial +=1
922            self.uniqueID = 'M*%d' % self.serial
923            self.Vertices.visualise(vertex,
924                                    self.uniqueID,
925                                    self.canvas,
926                                    self.SCALE)
927           
928        for hole in mesh.getHoles():
929            self.serial +=1
930            self.uniqueID = 'M*%d' % self.serial
931            self.Holes.visualise(hole,
932                                    self.uniqueID,
933                                    self.canvas,
934                                    self.SCALE)   
935        for region in mesh.getRegions():
936            self.serial +=1
937            self.uniqueID = 'M*%d' % self.serial
938            self.Regions.visualise(region,
939                                    self.uniqueID,
940                                    self.canvas,
941                                    self.SCALE)
942    def normalise4ObjMesh(self):
943        if self.mesh:
944            self.clearSelections()
945            self.canvas.delete(ALL)
946            self.mesh.normaliseMesh(400,-200,20)
947            self.visualiseMesh(self.mesh)
948            self.ResizeToFit()
949            self.ResizeToFit()
950           
951    def normaliseMesh(self):
952        if self.mesh:
953            self.clearSelections()
954            self.canvas.delete(ALL)
955            self.mesh.normaliseMesh(1,0,1)
956            self.visualiseMesh(self.mesh)
957            self.ResizeToFit()
958            self.ResizeToFit()
959           
960       
961    def clearMesh(self):
962        """Clear the current mesh object, and the canvas """
963       
964        self.clearSelections()
965        self.canvas.delete(ALL)
966        self.deleteMesh()
967        self.initData()
968        self.createMesh()
969
970    def exportObj(self):
971        fileType = "obj"
972        fileTypeDesc = "obj mesh"
973       
974        ofile = tkFileDialog.asksaveasfilename(filetypes=[(fileTypeDesc, fileType),
975                                                ("All Files", "*")])
976        if ofile:
977            addOn = "." + fileType
978            jumpback = - len(addOn)
979            if ofile[jumpback:] != addOn: 
980                ofile = ofile + addOn
981            try:
982                self.mesh.exportASCIIobj(ofile)
983            except IOError:
984                showerror('Export ASCII file',
985                                   'Can not write to file.')
986            except RuntimeError:
987                showerror('Export ASCII file',
988                                   'No triangulation to export.')
989
990   
991
992    def ImportUngenerate(self):
993        ofile = tkFileDialog.askopenfilename(initialdir=self.currentPath,
994                                             filetypes=[ ("ungenerated polygon information", "txt"),
995                                           ("All Files", "*")])
996        if ofile == "":
997            # The user cancelled the loading action
998            return
999       
1000        try:
1001            self.clearSelections()
1002            self.canvas.delete(ALL)
1003            dict = mesh.importUngenerateFile(ofile)
1004            self.mesh.addVertsSegs(dict)
1005           
1006        except SyntaxError: 
1007            #this is assuming that the SyntaxError is thrown in
1008            #loadxyafile
1009            showerror('File error',
1010                      ofile + ' is not in the correct format.')
1011        except IOError: 
1012            #!!! this error type can not be thrown?
1013            showerror('File error',
1014                      'file ' + ofile + ' could not be found.')
1015        except RuntimeError: 
1016            showerror('File error',
1017                  'file ' + ofile + ' has an unknown file type.')
1018   
1019        self.visualiseMesh(self.mesh)
1020        self.ResizeToFit()
1021       
1022    def exportASCIIsegmentoutlinefile(self):
1023        fileType = "tsh"
1024        fileTypeDesc = "text mesh"
1025       
1026        ofile = tkFileDialog.asksaveasfilename(filetypes=[(fileTypeDesc, fileType),
1027                                                ("All Files", "*")])
1028        if ofile:
1029            addOn = "." + fileType
1030            jumpback = - len(addOn)
1031            if ofile[jumpback:] != addOn: 
1032                ofile = ofile + addOn
1033            try:
1034                self.mesh.exportASCIIsegmentoutlinefile(ofile)
1035            except IOError:
1036                showerror('Export ASCII file',
1037                                   'Can not write to file.')
1038
1039    def exportxyafile(self):
1040        fileType = "xya"
1041        fileTypeDesc = "text vertices"
1042       
1043        ofile = tkFileDialog.asksaveasfilename(filetypes=[(fileTypeDesc, fileType),
1044                                                ("All Files", "*")])
1045        if ofile:
1046            addOn = "." + fileType
1047            jumpback = - len(addOn)
1048            if ofile[jumpback:] != addOn: 
1049                ofile = ofile + addOn
1050            try:
1051                self.mesh.exportxyafile(ofile)
1052            except IOError:
1053                showerror('Export ASCII file',
1054                                   'Can not write to file.')
1055                               
1056    def exportTriangulation(self):
1057        """
1058        This function is not used?
1059        """
1060        fileType = "tsh"
1061        fileTypeDesc = "text mesh"
1062       
1063        ofile = tkFileDialog.asksaveasfilename(filetypes=[(fileTypeDesc, fileType),
1064                                                ("All Files", "*")])
1065        if ofile:
1066            addOn = "." + fileType
1067            jumpback = - len(addOn)
1068            if ofile[jumpback:] != addOn: 
1069                ofile = ofile + addOn
1070            try:
1071                self.mesh.exportASCIItrianglulationfile(ofile)
1072            except IOError:
1073                showerror('Export ASCII file',
1074                                   'Can not write to file.')
1075            except RuntimeError:
1076                showerror('Export ASCII file',
1077                                   'No triangulation to export.')
1078               
1079   
1080    def exportMesh(self):
1081        fileType = "tsh"
1082        fileTypeDesc = "text Mesh"
1083       
1084        ofile = tkFileDialog.asksaveasfilename(filetypes=[(fileTypeDesc, fileType),
1085                                                ("All Files", "*")])
1086        if ofile:
1087            addOn = "." + fileType
1088            jumpback = - len(addOn)
1089            if ofile[jumpback:] != addOn: 
1090                ofile = ofile + addOn
1091            try:
1092                self.mesh.exportASCIImeshfile(ofile)
1093            except IOError:
1094                showerror('Export ASCII file',
1095                                   'Can not write to file.')
1096            except RuntimeError:
1097                showerror('Export ASCII file',
1098                                   'No mesh to export.')
1099                   
1100    def importFile(self):
1101        """
1102        import mesh data from a variety of formats (currently 2!)
1103        """
1104        print "self.currentPath",self.currentPath
1105        ofile = tkFileDialog.askopenfilename(initialdir=self.currentPath,
1106                                             filetypes=[ ("text Mesh", "tsh"),
1107                                                         ("points", "xya"),
1108                                           ("All Files", "*")])
1109        if ofile == "":
1110            # The user cancelled the loading action
1111            return
1112       
1113        try:
1114            newmesh = mesh.importMeshFromFile(ofile)
1115            self.currentPath, dummy = os.path.split(ofile)
1116            #print "be good self.currentPath",self.currentPath
1117            self.currentFilePathName = ofile
1118            self.clearMesh()
1119            self.mesh = newmesh
1120            self.visualiseMesh(self.mesh)
1121            self.ResizeToFit()
1122       
1123        except SyntaxError: 
1124            #this is assuming that the SyntaxError is thrown in
1125            #loadxyafile
1126            showerror('File error',
1127                      ofile + ' is not in the correct format.')
1128        except IOError: 
1129            #!!! this error type can not be thrown?
1130            showerror('File error',
1131                      'file ' + ofile + ' could not be found.')
1132        except RuntimeError: 
1133            showerror('File error',
1134                  'file ' + ofile + ' has an unknown file type.')
1135        # Could not get the file name to showup in the title
1136        #appname =  ofile + " - " + APPLICATION_NAME
1137        #print "appname",appname
1138       
1139       
1140   
1141    def ResizeToFitWrapper(self, Parent):
1142        """
1143        The parent attribute isn't used by this function.
1144        need to understand toolbarbutton.py to know how to
1145        get rid of it.
1146        """
1147        self.ResizeToFit()
1148       
1149    def ResizeToFit(self):
1150        """Visualise the mesh so it fits in the window"""
1151        if self.mesh.getUserVertices() == []:
1152            return #There are no vertices!
1153        # Resize the window
1154        self.scrolledcanvas.resizescrollregion()
1155        # I need this so the xview values are correct
1156        self.scrolledcanvas.update()
1157       
1158        xtop, xbottom = self.scrolledcanvas.xview()
1159        ytop, ybottom = self.scrolledcanvas.yview()
1160        xdiff = xbottom-xtop
1161        ydiff = ybottom-ytop
1162        if xdiff == 1 and xdiff == 1:
1163            #The mesh might be too small.
1164            #Make it too large, then resize
1165            #!!! Recursive hack.  Should be a better way
1166            fraction = 50
1167            self.SCALE *= fraction
1168            self.scrolledcanvas.scale(ALL, 0, 0, fraction, fraction)
1169            self.ResizeToFit()
1170        else:
1171            # without 0.99 some of the mesh may be off screen
1172            fraction = 0.99*min(xdiff,ydiff) 
1173            self.selectZoom(fraction)
1174           
1175    def saveDrawing(self):
1176        """
1177        Save the current drawing
1178        """
1179        #print "dsg!!! self.currentFilePathName ",self.currentFilePathName
1180        if (self.currentFilePathName[-4:] != ".tsh"):
1181            # force user to choose a name
1182            self.saveAsDrawing()
1183        else:
1184            self.exportASCIItrianglulationfile(self.currentFilePathName)
1185
1186    def saveAsDrawing(self):
1187        """
1188        Save the current drawing, prompting for a file name
1189        """
1190        ofile = tkFileDialog.asksaveasfilename(initialdir=self.currentPath,
1191                                               filetypes=[("text mesh", "tsh"),
1192                                             ("All Files", "*")])
1193        print "aa"
1194        if ofile:
1195            if ofile[-4:] == ".tsh": 
1196                self.currentFilePathName = ofile
1197            else:
1198                self.currentFilePathName = ofile + ".tsh"
1199            self.exportASCIItrianglulationfile(self.currentFilePathName)
1200
1201    def exportASCIItrianglulationfile(self,currentFilePathName):
1202        """
1203        Have a warning prompt when saving a mesh where the generated mesh is
1204        different from the user mesh - eg boundary tags that aren't carried
1205        thru. Warning ~"Mesh not generated after changes.  Generate mesh?  "
1206        - cancel, don't gen, don't save.  Yes - generate mesh, go to save
1207        screen.  No - goto save screen.  To implement this need to know when
1208        the user has done a change, and the mesh hasn't been generated.  If
1209        there is no generated mesh do not prompt.
1210        """
1211        #print "self.UserMeshChanged",self.UserMeshChanged
1212        #print "self.mesh.isTriangulation()",self.mesh.isTriangulation()
1213        if (self.UserMeshChanged) and self.mesh.isTriangulation():
1214           
1215            m = _show("Warning",
1216                                   "A triangulation has not been generated, after mesh changes.  Generate triangulation before saving?",
1217                                   icon=QUESTION, 
1218                                   type=YESNOCANCEL)
1219            if m == "no":
1220                self.mesh.exportASCIItrianglulationfile(currentFilePathName)
1221                self.UserMeshChanged = False
1222            elif m == "cancel":
1223                pass
1224            elif m == "yes":
1225                self.windowMeshGen(None)
1226                self.mesh.exportASCIItrianglulationfile(currentFilePathName)
1227        else:
1228            self.mesh.exportASCIItrianglulationfile(currentFilePathName)
1229            self.UserMeshChanged = False
1230           
1231    def initData(self):
1232        """
1233        Initialise various lists and flags
1234        """
1235        self.serial      = 1000
1236        self.currentFilePathName = 'untitled'
1237
1238        # these are attributes I've added
1239        self.SCALE       = 1
1240        self.selVertex   = None     #The last vertex selected, in draw seg mode
1241        self.selVertexTag   = None     # The selected vertex drawn object tag
1242        self.mesh        = None
1243        self.MeshMinAngle = 20
1244        self.MeshMaxArea = 200
1245        self.MeshnumTriangles = 20
1246        self.MeshMaxAreaLast = False
1247        self.selMeshObject = None  # The mesh object selected in the current mode
1248        self.selMeshTag = None
1249        mesh.Segment.set_default_tag("")
1250        self.UserMeshChanged = False
1251        self.meshLastAlpha = None
1252   
1253    def ipostscript(self):
1254        """
1255        Print the canvas as a postscript file
1256        """
1257        ofile = tkFileDialog.asksaveasfilename(filetypes=[("postscript", "ps"),
1258                                             ("All Files", "*")]) 
1259        if ofile:
1260            if ofile[-3:] != ".ps": 
1261                ofile = ofile + ".ps"
1262            postscript = self.canvas.postscript()
1263            fd = open(ofile, 'w')
1264            fd.write(postscript)
1265            fd.close()
1266       
1267    def close(self):
1268        self.quit()
1269    def createInterface(self):
1270        """
1271        Call all functions that create the GUI interface
1272        """
1273        self.initData()
1274        self.createMesh()
1275        AppShell.AppShell.createInterface(self)
1276        self.createButtons()
1277        self.createMenus()
1278        self.createBase()
1279        self.createTools()
1280        self.createZooms()
1281        self.createEdits()
1282        self.createSetTools()
1283        self.createSetIcons()
1284        self.createVisualiseIcons()
1285        #self.addVertsAndSegs() # !!!DSG start pmesh with a triangle
1286        self.selectFunc('pointer')
1287        self.currentPath = os.getcwd() 
1288
1289        self.Visualise = True
1290
1291    def loadtestmesh(self,ofile):
1292        """
1293        debugging script to test loading a file
1294        """
1295        fd = open(ofile)
1296        a = mesh.Vertex (-10.0, 0.0)
1297        d = mesh.Vertex (0.0, 4.0)
1298        f = mesh.Vertex (4.0,0.0)
1299        g = mesh.Vertex (-5.0,5.0)
1300       
1301        s1 = mesh.Segment(a,d)
1302        s2 = mesh.Segment(d,f)
1303        s3 = mesh.Segment(a,f)
1304
1305        r1 = mesh.Region(0.3, 0.3)
1306       
1307        m = mesh.Mesh(userVertices=[a,d,f,g], userSegments=[s1,s2,s3], regions=[r1] )
1308       
1309        fd.close()
1310        print 'returning m'
1311        return oadtestmesh(ofile)
1312         
1313class  AddVertexDialog(Dialog):
1314    """
1315    Dialog box for adding a vertex by entering co-ordindates
1316    """
1317    def body(self, master):
1318        """
1319        GUI description
1320        """
1321        self.title("Add New Vertex")
1322       
1323        Label(master, text='X position:').grid(row=0, sticky=W)
1324        Label(master, text='Y position:').grid(row=1, sticky=W)
1325
1326        self.xstr   = Entry(master, width = 16, name ="entry")
1327        self.ystr  = Entry(master, width = 16)
1328       
1329        self.xstr.grid(row=0, column=1, sticky=W)
1330        self.ystr.grid(row=1, column=1, sticky=W)
1331        self.xstr.focus_force()
1332        self.= 0
1333        self.= 0
1334        self.xyValuesOk = False
1335       
1336
1337class  AutoSegmentDialog(Dialog):
1338    """
1339    Dialog box for adding segments
1340    """
1341    def __init__(self, parent, alpha):
1342        self.alpha = alpha
1343        Dialog.__init__(self, parent)
1344       
1345    def body(self, master):
1346        """
1347        GUI description
1348        """
1349        self.title("Automatically Add Segments")
1350
1351        self.var = IntVar()
1352        self.var.set(AUTO) # should initialise the radio buttons. It doesn't
1353        #self.var.set(NO_SELECTION)
1354        self.ck = Radiobutton(master, value = AUTO, variable=self.var) 
1355        self.ck.grid(row=1, column=0)
1356        Label(master, text='Use optimum alpha').grid(row=1, column=1, sticky=W)
1357
1358        self.ck2 = Radiobutton(master, value = SET_ALPHA, variable=self.var) 
1359        self.ck2.grid(row=2, column=0)
1360       
1361        Label(master, text='alpha:').grid(row=2, column=1, sticky=W)
1362        if (self.alpha):
1363            alphaVar = StringVar()
1364            alphaVar.set(self.alpha)
1365            self.alpha_str  = Entry(master,
1366                                     textvariable = alphaVar,
1367                                     width = 16, name ="entry") 
1368        else: 
1369            self.alpha_str = Entry(master, width = 16, name ="entry")
1370       
1371        self.alpha_str.grid(row=2, column=3, sticky=W)
1372
1373        self.alpha  = 0
1374        self.alphaValueOk = False
1375       
1376
1377    def apply(self):
1378        """
1379        check entered values
1380        """
1381        try:
1382            self.alpha = float(self.alpha_str.get())
1383            self.alphaValueOk = True
1384           
1385        except ValueError:
1386            pass
1387            #showerror('Bad Alpha value',
1388            #                       'Alpha is negative.')
1389
1390
1391class  MeshGenDialog(Dialog):
1392    """
1393    Dialog box for generating a mesh
1394    """
1395    # initial values, hard coded.
1396    # should be values associated with the current mesh
1397    lastMinAngle = 20
1398    lastMaxArea  = 100
1399
1400
1401    def __init__(self,
1402                 parent,
1403                 minAngle,
1404                 maxArea,
1405                 numTriangles,
1406                 MeshMaxAreaLast):
1407        self.minAngle = minAngle
1408        self.maxArea = maxArea
1409        self.numTriangles = numTriangles
1410        self.MeshMaxAreaLast = MeshMaxAreaLast
1411
1412        Dialog.__init__(self, parent)
1413
1414       
1415    def body(self, master):
1416        """
1417        GUI description
1418        """
1419        self.title("Generate Mesh")
1420       
1421        Label(master,
1422              text='Minimum Angle(0 - 40):').grid(row=0, sticky=W)
1423        Label(master,
1424              text='Angles>33 may not converge').grid(row=1, sticky=W)
1425        Label(master, text='Maximum Area:').grid(row=2, sticky=W)
1426        Label(master, text='OR # of triangles:').grid(row=3, sticky=W)
1427
1428
1429        minAngleVar = StringVar()
1430        minAngleVar.set(self.minAngle)
1431        self.minAnglestr   = Entry(master,
1432                                   width = 16,
1433                                   textvariable = minAngleVar,
1434                                   takefocus=1)
1435        if (self.MeshMaxAreaLast):
1436            maxAreaVar = StringVar()
1437            maxAreaVar.set(self.maxArea)
1438            self.maxAreastr  = Entry(master,
1439                                     textvariable = maxAreaVar,
1440                                     width = 16)   
1441            self.numTrianglesstr  = Entry(master,
1442                                          width = 16) 
1443        else: 
1444            self.maxAreastr  = Entry(master,
1445                                     width = 16)
1446            self.maxAreastr.focus_force()
1447            numTrianglesVar = StringVar()
1448            numTrianglesVar.set(self.numTriangles)   
1449            self.numTrianglesstr  = Entry(master,
1450                                          textvariable = numTrianglesVar,
1451                                          width = 16) 
1452
1453
1454        self.minAnglestr.grid(row=0, column=1, sticky=W)
1455        self.maxAreastr.grid(row=2, column=1, sticky=W)
1456        self.numTrianglesstr.grid(row=3, column=1, sticky=W)
1457
1458        self.numTriangles = 0
1459        self.minAngle  = 0
1460        self.maxArea  = 0
1461        self.ValuesOk = False
1462
1463
1464    def apply(self):
1465        """
1466        check entered values
1467        """
1468        self.goodMaxArea = self.goodNumTriangles = True
1469        self.ValuesOk = True
1470        try:
1471            self.minAngle = float(self.minAnglestr.get())
1472            MeshGenDialog.lastMinAngle =self.minAngle
1473        except ValueError:
1474            self.ValuesOk = False
1475            showerror('Bad mesh generation values',
1476                                   ' Values are not numbers.')
1477       
1478        try:   
1479            self.maxArea = float(self.maxAreastr.get())
1480            MeshGenDialog.lastMaxArea =self.maxArea
1481        except ValueError:
1482            self.goodMaxArea = False
1483         
1484        try:   
1485            self.numTriangles = int(self.numTrianglesstr.get())
1486            MeshGenDialog.lastNumTriangles =self.numTriangles
1487        except ValueError:
1488            self.goodNumTriangles= False
1489
1490        if self.goodMaxArea == False and self.goodNumTriangles == False:
1491            self.ValuesOk = False
1492            showerror('Bad mesh generation values',
1493                      'Values are not numbers.')
1494
1495        if self.goodMaxArea == True and self.goodNumTriangles == True:
1496            self.ValuesOk = False
1497            showerror('Bad mesh generation values',
1498                      'Give a maximum area OR number of triangles, not both.')
1499
1500        try: 
1501            # value checking
1502            if self.minAngle <0.0 or self.minAngle >40.0:
1503                raise IOError
1504            if self.goodMaxArea == True and self.maxArea <0.0:
1505                raise IOError
1506            if self.goodNumTriangles == True and self.numTriangles <=0:
1507                raise IOError
1508           
1509        except IOError:
1510            self.ValuesOk = False
1511            showerror('Bad mesh generation values',
1512                                   'Values are out of range.')
1513class  GeneralThresholdDialog(Dialog):
1514    """
1515    Dialog box for thresholding a set by entering minimum
1516    and maximum values
1517    """
1518    def __init__(self,
1519                 parent,
1520                 attribute_titles,
1521                 function_description):
1522        self.attribute_titles=attribute_titles
1523        self.function_description=function_description
1524
1525        Dialog.__init__(self, parent)
1526
1527
1528    def body(self, master):
1529        """
1530        GUI description
1531        """
1532        self.title("Threshold selected set")
1533        blurb1 = 'Threshold selected set between minimum'
1534        blurb2 = 'and maximum ' + self.function_description
1535
1536        Label(master,text=blurb1).grid(row=0, sticky=W)
1537        Label(master,text=blurb2).grid(row=1, sticky=W)
1538
1539        Label(master, text='minimum attribute:').grid(row=2, sticky=W)
1540        Label(master, text='maximum attribute:').grid(row=3, sticky=W)
1541        Label(master, text='attribute name').grid(row=4, sticky=W)
1542
1543
1544        nameVar = StringVar()
1545        nameVar.set('elevation')
1546
1547        self.minstr = Entry(master, width = 16, name ="entry")
1548        self.maxstr = Entry(master, width = 16)
1549        self.attstr = Entry(master, width = 16,textvariable = nameVar)
1550       
1551        self.minstr.grid(row=2, column=1, sticky=W)
1552        self.maxstr.grid(row=3, column=1, sticky=W)
1553        self.attstr.grid(row=4, column=1, sticky=W)
1554        self.minstr.focus_force()
1555        self.min  = 0
1556        self.max  = 0
1557        self.attribute_name = 'elevation'
1558        self.minmaxValuesOk = False
1559       
1560    def apply(self):
1561        self.minmaxValuesOk = True
1562        try:
1563            self.min = float(self.minstr.get())
1564            self.max = float(self.maxstr.get())
1565        except ValueError:
1566            self.minmaxValuesOk = False
1567            showerror('Bad mesh generation values',
1568                                   ' Values are not numbers.')
1569        try:
1570            self.attribute_titles.index(self.attstr.get())#dodgey.
1571            self.attribute_name = self.attstr.get()
1572        except ValueError:
1573            self.minmaxValuesOk = False
1574            showerror('Bad attribute name',
1575                                   ' Attribute not in mesh.')
1576
1577class  ThresholdDialog(Dialog):
1578    """
1579    Dialog box for thresholding a set by entering minimum
1580    and maximum values
1581    """
1582    def __init__(self,
1583                 parent,
1584                 attribute_titles):
1585        self.attribute_titles=attribute_titles
1586        Dialog.__init__(self, parent)
1587
1588
1589    def body(self, master):
1590        """
1591        GUI description
1592        """
1593        self.title("Threshold selected set")
1594       
1595        Label(master, text='minimum attribute:').grid(row=0, sticky=W)
1596        Label(master, text='maximum attribute:').grid(row=1, sticky=W)
1597        Label(master, text='attribute name').grid(row=2, sticky=W)
1598
1599
1600        nameVar = StringVar()
1601        nameVar.set('elevation')
1602
1603        self.minstr   = Entry(master, width = 16, name ="entry")
1604        self.maxstr   = Entry(master, width = 16)
1605        self.attstr   = Entry(master, width = 16,textvariable = nameVar)
1606       
1607        self.minstr.grid(row=0, column=1, sticky=W)
1608        self.maxstr.grid(row=1, column=1, sticky=W)
1609        self.attstr.grid(row=2, column=1, sticky=W)
1610        self.minstr.focus_force()
1611        self.min  = 0
1612        self.max  = 0
1613        self.attribute_name = 'elevation'
1614        self.minmaxValuesOk = False
1615       
1616    def apply(self):
1617        self.minmaxValuesOk = True
1618        try:
1619            self.min = float(self.minstr.get())
1620            self.max = float(self.maxstr.get())
1621        except ValueError:
1622            self.minmaxValuesOk = False
1623            showerror('Bad mesh generation values',
1624                                   ' Values are not numbers.')
1625        try:
1626            self.attribute_titles.index(self.attstr.get())#dodgey.
1627            self.attribute_name = self.attstr.get()
1628        except ValueError:
1629            self.minmaxValuesOk = False
1630            showerror('Bad attribute name',
1631                                   ' Attribute not in mesh.')
1632
1633
1634class  Courant_ThresholdDialog(Dialog):
1635    """
1636    Dialog box for thresholding a set by entering minimum
1637    and maximum values
1638    """
1639    def __init__(self,
1640                 parent,
1641                 attribute_titles):
1642        self.attribute_titles=attribute_titles
1643        Dialog.__init__(self, parent)
1644
1645
1646    def body(self, master):
1647        """
1648        GUI description
1649        """
1650        self.title("Courant_Threshold selected set")
1651       
1652        Label(master, text='minimum attribute:').grid(row=0, sticky=W)
1653        Label(master, text='maximum attribute:').grid(row=1, sticky=W)
1654        Label(master, text='attribute name').grid(row=2, sticky=W)
1655
1656
1657        nameVar = StringVar()
1658        nameVar.set('elevation')
1659
1660        self.minstr   = Entry(master, width = 16, name ="entry")
1661        self.maxstr   = Entry(master, width = 16)
1662        self.attstr   = Entry(master, width = 16,textvariable = nameVar)
1663       
1664        self.minstr.grid(row=0, column=1, sticky=W)
1665        self.maxstr.grid(row=1, column=1, sticky=W)
1666        self.attstr.grid(row=2, column=1, sticky=W)
1667        self.minstr.focus_force()
1668        self.min  = 0
1669        self.max  = 0
1670        self.attribute_name = 'elevation'
1671        self.minmaxValuesOk = False
1672       
1673    def apply(self):
1674        self.minmaxValuesOk = True
1675        try:
1676            self.min = float(self.minstr.get())
1677            self.max = float(self.maxstr.get())
1678        except ValueError:
1679            self.minmaxValuesOk = False
1680            showerror('Bad mesh generation values',
1681                                   ' Values are not numbers.')
1682        try:
1683            self.attribute_titles.index(self.attstr.get())#dodgey.
1684            self.attribute_name = self.attstr.get()
1685        except ValueError:
1686            self.minmaxValuesOk = False
1687            showerror('Bad attribute name',
1688                                   ' Attribute not in mesh.')
1689
1690
1691class  setStructureNumberDialog(Dialog):
1692    """
1693    Dialog box for setting the number of triangles
1694    used to make up dilation or erosion
1695    """
1696    def body(self, master):
1697        """
1698        GUI description
1699        """
1700        self.title("Set number of elements effected by morphing sets")
1701       
1702        Label(master, text='number:').grid(row=0, sticky=W)
1703
1704        self.number = Entry(master, width = 16, name ="entry")
1705       
1706        self.number.grid(row=0, column=1, sticky=W)
1707        self.number.focus_force()
1708        self.number = 0
1709        self.numberOk = False
1710       
1711    def apply(self):
1712        self.numberOk = True
1713        try:
1714            self.number = int(self.number.get())
1715        except ValueError:
1716            self.numberOK = False
1717            showerror('Bad mesh generation values',
1718                                   ' Values are not numbers.')
1719
1720
1721     
1722if __name__ == '__main__':
1723    draw = Draw()
1724    draw.run()
1725    #profile.run('draw.run()', 'pmeshprof')   
1726
Note: See TracBrowser for help on using the repository browser.