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

Last change on this file since 972 was 972, checked in by duncan, 20 years ago

removing prints

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