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

Last change on this file since 1395 was 1395, checked in by duncan, 19 years ago

load_mesh refactoring

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