source: inundation/pmesh/pmesh.py @ 2544

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

adding functionality to pmesh.mesh for momentum sink.

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