source: anuga_core/source/anuga/pmesh/graphical_mesh_generator.py @ 5188

Last change on this file since 5188 was 5188, checked in by duncan, 17 years ago

abstracting colour information

File size: 58.1 KB
Line 
1
2import  Pmw, AppShell, math, time, string, marshal
3from toolbarbutton import ToolBarButton
4import tkFileDialog
5from   tkSimpleDialog import Dialog
6import mesh
7from mesh import SEG_COLOUR
8from Tkinter import  FALSE,TRUE, Frame,X, LEFT,YES,BOTH,ALL,Widget,CURRENT, \
9     Label,W, Entry, E, StringVar, END, Checkbutton, Radiobutton, IntVar, \
10     DISABLED, NORMAL
11#from cursornames import TLC,TRC, BLC, BRC, TS, RS, LS, BS
12from tkMessageBox import showerror, _show, QUESTION,YESNOCANCEL
13import types
14import visualmesh
15import os
16import profile
17import load_mesh.loadASCII
18from anuga.alpha_shape.alpha_shape import AlphaError
19
20# CONSTANTS
21VERT_SELECT_ADDING_SEG_COLOR = 'orange'
22SELECT_COLOR = 'red'
23TRIANGLE_COLOUR = 'green'
24APPLICATION_NAME = 'Pmesh'
25
26#for alpha shapes
27NO_SELECTION = 0
28AUTO = 1
29SET_ALPHA = 2
30
31
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',
106                                 'Add ungenerated file from arcGIS',
107                                 label='Add ungenerated file...',
108                                 command=self.ImportUngenerate)
109       
110        #self.menuBar.addmenuitem('File', 'command',
111        #                         'Export ASCII obj',
112        #                         label='Export ASCII obj',
113        #                         command=self.exportObj)
114       
115        self.menuBar.addmenuitem('File', 'command',
116                                 'Export ASCII segment outline',
117                                 label='Export ASCII segment outline...',
118                                 command=self.exportASCIIsegmentoutlinefile)
119       
120        self.menuBar.addmenuitem('File', 'command',
121                                 'Export ASCII csv file',
122                                 label='Export ASCII csv file...',
123                                 command=self.exportPointsFile)
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.auto_segment)
133        self.menuBar.addmenuitem('File', 'command',
134                           'modify the alpha boundary by applying filters',
135                                 label='filter alpha boundary',
136                                 command=self.auto_segmentFilter)
137        #self.menuBar.addmenuitem('File', 'command', 'Normalise mesh',
138        #                         label='Normalise mesh', command=self.normaliseMesh)
139        #self.menuBar.addmenuitem('File', 'command', 'Normalise mesh for glutobj',
140         #                        label='Normalise mesh for glutobj', command=self.normalise4ObjMesh)
141        self.menuBar.addmenuitem('File', 'separator')
142        self.menuBar.addmenuitem('File', 'command', '',
143                                 label='Print geo reference', command=self.printGeoReference)
144        self.menuBar.addmenuitem('File', 'separator')
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")
167            if key == 'pointer': #FIXME- this is specified in line 1062 as well
168                                 # self.selectFunc('pointer')
169                self.curFunc  = self.drawVertex
170                t.setInitialSunkenButton("DrawMode")
171            self.modeClass[key] = Mode
172            # for actions that occur when the mouse goes down
173            self.mouseDownFunc[key] = mouseDownFunc
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'),     
208             #   ('autoSeg', self.auto_segmentButton, 'add Segments to form alpha shape'),
209                ('autoSegGiveAlpha', self.auto_segmentGiveAlphaButton, '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    def createVisualiseIcons(self):
217        """
218        Add Edit buttons to the top of the GUI
219        """
220        ToolBarButton(self, self.toolbar, 'sep', 'sep.gif', width=10,
221                      state='disabled')
222        for key, func, balloon in [
223                ('see', self.visualise, 'Visualise mesh triangles'),
224                ('no_see', self.unvisualise, 'Do not visualise mesh triangles (for large meshes)')]:
225            ToolBarButton(self, self.toolbar, key, '%s.gif' %key,
226                          command=func, balloonhelp=balloon,
227                               statushelp='' )
228
229
230    def clearSelection(self,parent):
231    #FIXME looks like self.clearSelections - change name (Peter)
232        """
233        """
234        self.canvas.delete(ALL)
235        self.selSet = self.mesh.clearSelection()
236        self.visualiseMesh(self.mesh)
237
238    def visualise(self,parent):
239        self.canvas.delete(ALL)
240        self.Visualise = True
241        self.visualiseMesh(self.mesh)
242
243    def unvisualise(self,parent):
244        self.canvas.delete(ALL)
245        self.Visualise = False
246        self.visualiseMesh(self.mesh)
247
248    def createMesh(self):
249        """
250        Build the data structures for storing the mesh objects
251        """
252        self.mesh = mesh.Mesh()
253       
254        self.Vertices = visualmesh.vPoints(mesh.Vertex)
255        self.Segments = visualmesh.vSegments(mesh.Segment)
256        self.Holes = visualmesh.vPoints(mesh.Hole)
257        self.Regions = visualmesh.vRegions(mesh.Region)
258        self.UserMesh = visualmesh.vMesh([self.Vertices,self.Segments,self.Holes,self.Regions])
259
260
261    def deleteMesh(self):
262        """
263        Delete the data structures for storing the mesh objects
264        """
265        self.mesh = None
266        self.Vertices = None
267        self.Segments = None
268
269    def addCylinders(self):
270        """
271        Automatically add some verts and segs to the mesh.Used in Debugging
272
273        center and radius
274       
275        """
276        from anuga.coordinate_transforms.geo_reference import Geo_reference, \
277             DEFAULT_ZONE
278        offset_x = 30
279        offset_y = 40
280
281        x_origin = 10-offset_x
282        y_origin = 20-offset_y
283        r = 10
284        pi = math.pi
285        num_of_cuts = 100
286        cuts = []
287        factor = 2* math.pi/num_of_cuts
288        for cut in range(num_of_cuts):
289             cuts.append(cut*factor)
290       
291        for radius in cuts:
292            x = x_origin + r * math.cos(radius)
293            y = y_origin + r * math.sin(radius)
294            v = self.drawVertex(x,y,None)
295            if not radius == 0.0:   # FIXME
296                self.drawSegment(v,v_old)
297            else:
298                v_first = v
299            v_old = v
300        self.drawSegment(v,v_first)
301        region = self.drawRegion(x_origin, y_origin, 0)
302        region.setTag("setheight5")
303       
304       
305        x_origin = 30-offset_x
306        y_origin = 30-offset_y
307        r = 5
308        pi = math.pi
309        num_of_cuts = 100
310        cuts = []
311        factor = 2* math.pi/num_of_cuts
312        for cut in range(num_of_cuts):
313             cuts.append(cut*factor)
314       
315        for radius in cuts:
316            x = x_origin + r * math.cos(radius)
317            y = y_origin + r * math.sin(radius)
318            v = self.drawVertex(x,y,None)
319            if not radius == 0.0:   # FIXME
320                self.drawSegment(v,v_old)
321            else:
322                v_first = v
323            v_old = v
324        self.drawSegment(v,v_first)
325        region = self.drawRegion(x_origin, y_origin, 0)
326        region.setTag("setheight10")
327        self.mesh.geo_reference = Geo_reference(zone=DEFAULT_ZONE,
328                                                xllcorner=offset_x,
329                                                yllcorner=offset_y)
330           
331        #Since the new vertex may be off screen
332        self.scrolledcanvas.resizescrollregion()
333           
334    def selectFunc(self, tag):
335        """
336        Change the current mode class
337        When changing from one mode to another
338        """
339        self.mouseDownCurFunc = self.mouseDownFunc[tag]
340        self.curModeClass = self.modeClass[tag]
341        self.clearSelections()
342        self.canvas.config(cursor='arrow')
343#        I can make it arrow, but it will change back to pointer, after
344#        adding an object
345#        if self.curFunc == self.func['pointer']:
346#            self.canvas.config(cursor='arrow')
347#         else:
348#             self.canvas.config(cursor='crosshair')
349
350    def clearSelections(self):
351        """
352        deselect objects that have been selected
353        """
354        if self.selMeshObject:
355            self.deselectMeshObject(self.selMeshObject, self.selMeshTag)       
356        if self.selVertex:
357            self.deselectVertex(self.selVertex, self.selVertexTag)
358         
359       
360    def selectZoom(self, tag):
361        """
362        Zoom in or out of the current mesh view
363        """
364        fraction = string.atof(tag)
365        self.SCALE *= fraction
366        self.scrolledcanvas.scale(ALL, 0, 0, fraction, fraction)
367
368        # Redraw all of the vertices, holes and regions,
369        #so the squares representing vertices
370        # don't get bigger
371        vertices = self.mesh.getUserVertices()
372        holes = self.mesh.getHoles()
373        regions = self.mesh.getRegions()
374        MeshObjects  = vertices + holes + regions
375
376        # make a list of tags to delete
377        guiIDs = [getattr(MeshObjects[i],'guiID') for i in xrange(len(MeshObjects))]
378        apply(self.canvas.delete, guiIDs)
379        for obj in MeshObjects:
380            if self.selVertex == obj:
381                obj.draw(self.canvas,obj.guiID,  scale =self.SCALE ,colour= VERT_SELECT_ADDING_SEG_COLOR)
382            elif self.selMeshObject == obj:
383                obj.draw(self.canvas,obj.guiID,  scale =self.SCALE ,colour= SELECT_COLOR)
384            else:
385                obj.draw(self.canvas,obj.guiID,  scale =self.SCALE ) 
386        top, bottom = self.scrolledcanvas.xview()
387        xcenter  = (top + bottom)/2
388        xdiff =  xcenter - top 
389        xcnew = xcenter - xdiff/fraction
390       
391        top, bottom = self.scrolledcanvas.yview()
392        ycenter = (top + bottom)/2
393        ydiff = ycenter - top
394        ycnew = ycenter - ydiff/fraction
395       
396        self.scrolledcanvas.resizescrollregion()
397        # update so the moveto calls will work...
398        self.scrolledcanvas.update()
399        # but calling update now does make things jerky
400        self.canvas.xview_moveto(xcnew)
401        self.canvas.yview_moveto(ycnew)
402       
403   
404    def windowAddVertex (self, parent):
405        """
406        add a vertex using a window and entering x y values.
407
408        the parent attribute isn't used by this function.
409        need to userstand toolbarbutton.py to know how to
410        get rid of it.
411        """
412       
413        dialog = AddVertexDialog(self.canvas)
414        if dialog.xyValuesOk:
415            print dialog.x
416            print dialog.y
417            self.drawVertex(dialog.x*self.SCALE,dialog.y*self.SCALE,None)
418            #Since the new vertex may be off screen
419            self.ResizeToFit()
420        else:
421            print "bad values"
422   
423    def windowDefault (self, parent):
424        """
425       
426        the parent attribute isn't used by this function.
427        need to userstand toolbarbutton.py to know how to
428        get rid of it.
429        """
430        # self.UserMesh is a vMesh instance
431        self.UserMesh.defaultWindow(self.canvas, self.curModeClass)
432   
433    def windowEdit (self, parent):
434        """
435
436        the parent attribute isn't used by this function.
437        need to userstand toolbarbutton.py to know how to
438        get rid of it.
439        """
440        if self.selMeshObject:   
441            self.UserMeshChanged = self.UserMesh.editWindow(self.canvas,
442                                     self.selMeshObject,
443                                     self.UserMeshChanged)
444   
445    def auto_segmentButton (self, parent):
446        self.auto_segment()
447
448       
449    def auto_segmentGiveAlphaButton (self, parent):
450        dialog = auto_segmentDialog(self.canvas, self.meshLastAlpha)
451        if dialog.use_optimum.get() == SET_ALPHA:
452            if dialog.alphaValueOk:
453                self.auto_segment(alpha = dialog.alpha,
454                                 raw_boundary=dialog.raw_boundary.get(),
455                                 remove_holes=dialog.remove_holes.get(),
456                                 smooth_indents=dialog.smooth_indents.get(),
457                                 expand_pinch=dialog.expand_pinch.get())
458            else:
459                 showerror('pMesh',
460                      'Bad alpha value.')
461        else:
462            self.auto_segment(raw_boundary=dialog.raw_boundary.get(),
463                             remove_holes=dialog.remove_holes.get(),
464                             smooth_indents=dialog.smooth_indents.get(),
465                             expand_pinch=dialog.expand_pinch.get())
466           
467       
468    def auto_segment (self, alpha = None,
469                                 raw_boundary=True,
470                                 remove_holes=False,
471                                 smooth_indents=False,
472                                 expand_pinch=False ):
473        """
474        add Segments to bound all vertices
475       
476        """
477        if len(self.mesh.getUserVertices()) >= 3:
478            try:
479                newsegs, ObjectsToVisuallyDelete, self.meshLastAlpha = \
480                     self.mesh.auto_segment(alpha=alpha,
481                                           remove_holes=remove_holes,
482                                           smooth_indents=smooth_indents,
483                                           expand_pinch=expand_pinch)
484            except AlphaError:
485                showerror('pMesh',
486                          'Unable to auto_segment.')
487            else:
488
489                for drawOb in ObjectsToVisuallyDelete:
490                    self.UserMesh.unvisualise(drawOb, self.canvas)
491               
492                for segment in newsegs:
493                    self.serial +=1
494                    self.uniqueID = 'M*%d' % self.serial
495                    self.Segments.visualise(segment,
496                                            self.uniqueID,
497                                            self.canvas,
498                                            self.SCALE)
499           
500        else:
501            showerror('pMesh',
502                      'Three or more vetices are needed to be able to auto_segment.')
503
504
505    def auto_segmentFilter (self):
506        dialog = auto_segmentFilterDialog(self.canvas)
507        newsegs, ObjectsToVisuallyDelete, self.meshLastAlpha = \
508                 self.mesh.auto_segmentFilter(raw_boundary=dialog.raw_boundary.get(),
509                             remove_holes=dialog.remove_holes.get(),
510                             smooth_indents=dialog.smooth_indents.get(),
511                             expand_pinch=dialog.expand_pinch.get())
512        #print "newsegs",newsegs
513        #print "ObjectsToVisuallyDelete",ObjectsToVisuallyDelete
514           
515        for drawOb in ObjectsToVisuallyDelete:
516            self.UserMesh.unvisualise(drawOb, self.canvas)
517               
518        for segment in newsegs:
519            self.serial +=1
520            self.uniqueID = 'M*%d' % self.serial
521            self.Segments.visualise(segment,
522                                    self.uniqueID,
523                                    self.canvas,
524                                    self.SCALE)
525       
526    def joinVerticesButton (self, parent):
527        self.joinVertices()
528       
529    def joinVertices (self):
530        """
531        add Segments to connect all vertices
532       
533        the parent attribute isn't used by this function.
534        need to userstand toolbarbutton.py to know how to
535        get rid of it.
536        """
537        if len(self.mesh.getUserVertices()) >= 3:
538            newsegs = self.mesh.joinVertices()
539            for segment in newsegs:
540                self.serial +=1
541                self.uniqueID = 'M*%d' % self.serial
542                self.Segments.visualise(segment,
543                                        self.uniqueID,
544                                        self.canvas,
545                                        self.SCALE)
546        else:
547            showerror('pMesh',
548                      'Three or more vetices are needed to be able to join vertices.')
549       
550    def windowMeshGen (self, parent):
551        """
552        The parent attribute isn't used by this function.
553        need to understand toolbarbutton.py to know how to
554        get rid of it.
555        """
556        # Put exceptions round things.
557        #catch failure in self.mesh.generateMesh
558        dialog = MeshGenDialog(self.canvas,
559                               self.MeshMinAngle,
560                               self.MeshMaxArea,
561                               self.MeshnumTriangles,
562                               self.MeshMaxAreaLast)
563       
564        if dialog.ValuesOk:
565            print dialog.minAngle
566            print dialog.maxArea
567           
568            self.clearSelections()
569            self.canvas.delete(ALL)
570            if dialog.goodMaxArea == True:
571                self.MeshMinAngle = dialog.minAngle
572                self.MeshMaxArea = dialog.maxArea
573                self.MeshMaxAreaLast = True
574               
575                self.mesh = self.MeshGenAreaAngle (dialog.minAngle,
576                                          dialog.maxArea,
577                                          self.mesh)
578            elif dialog.goodNumTriangles == True:
579                self.MeshMinAngle = dialog.minAngle
580                self.MeshnumTriangles  = dialog.numTriangles
581                self.MeshMaxAreaLast = False
582               
583                self.mesh = self.MeshGenAreaNumTriangles (dialog.minAngle,
584                                          dialog.numTriangles,
585                                          self.mesh)
586            else:
587                pass
588            print "userMeshChanged = False"
589            self.UserMeshChanged = False
590            self.visualiseMesh(self.mesh)
591            print "Mesh Generation finished"
592           
593    def MeshGenAreaAngle (self, minAngle, maxArea, mesh):
594        """
595        Generate a mesh, given a minAngle and max area
596        """
597        tempMesh = mesh
598        try:
599            tempMesh.generateMesh(mode = "pzq"+str(minAngle)
600                                  +"a"+str(maxArea)
601                                  +"a") #So areas for regions will be used
602        except AttributeError : # can't catch PyEval_RestoreThread
603            # This doesn't catch tempMesh.generateMesh failing
604            tempMesh = mesh
605        return tempMesh
606       
607
608    def MeshGenAreaNumTriangles (self, minAngle, numTriangles, mesh):
609        """
610        Generate a mesh, given a minAngle and rough # of triangles
611        """
612        #get big triangles
613        #calc area
614        #calc max triangle area
615        #
616        tempMesh = mesh
617        try:
618            tempMesh.generateMesh("pzq1")
619        except AttributeError : # can't catch PyEval_RestoreThread
620            # This doesn't catch tempMesh.generateMesh failing
621            pass
622        meshArea = 0
623        #print "tempMesh.getTriangulation()", tempMesh.getTriangulation()
624        meshArea = tempMesh.tri_mesh.calc_mesh_area()
625        maxArea = meshArea/numTriangles
626
627       
628        return self.MeshGenAreaAngle (minAngle,
629                                      maxArea,
630                                      self.mesh)
631       
632    def mouseDown(self, event):
633        """
634        On a mouse down event, depending on the current state,
635        either add a vertex or a seg etc
636        """
637        self.curObject = None
638        self.lastx = self.startx = self.canvas.canvasx(event.x)
639        #The screen canvas has y 'flipped'.  -1* unflips it
640        self.lasty = self.starty = -1*self.canvas.canvasy(event.y)
641        print "----------------------"
642        self.mouseDownCurFunc( self.lastx,
643                               self.lasty,event) #!!! remove the event?
644                                                 # do last
645   
646    def rightMouseUp(self, event):
647        """
648        On a right mouse button up event select the nearest object.
649        """
650        found=False
651        if event.widget.find_withtag(CURRENT): # if there's a widget with a tag
652            [tag,string] = self.canvas.gettags(CURRENT) # get a list of them
653            print "tag",tag  #tags ('M*1008', 'current')
654            if tag[:2] == 'M*':   #!!! this can be removed when there are
655                #    only mesh objects on screen
656                #key, value = string.split(tag, '*')
657                objectID = tag
658                print "Found!! objectID:", objectID
659               
660                meshObjects = self.getAllUserMeshObjects()
661                # It may be a triangle, which is ignored
662                if meshObjects.hasKey(objectID):
663                    selMeshObject = meshObjects.getMeshObject(objectID)
664                    found = True
665                    print "Found! selMeshObject", selMeshObject
666                    #Only select one object at a time
667                    if self.selMeshObject:
668                        self.deselectMeshObject(self.selMeshObject, self.selMeshTag)
669                    self.selectMeshObject(selMeshObject,objectID)
670
671    def getAllUserMeshObjects(self):
672        return self.UserMesh
673       
674    def DeleteSelectedMeshObject(self, event):
675        """
676        if an object is selected, delete it.
677        """
678        if self.selMeshObject:
679            #an object is selected
680            #first deselect the vertex, for selecting a segment
681            if self.selVertex:
682                self.deselectVertex(self.selVertex, self.selVertexTag)
683            ObjectsToVisuallyDelete = self.mesh.deleteMeshObject (self.selMeshObject)
684            for drawOb in ObjectsToVisuallyDelete:
685                self.UserMesh.unvisualise(drawOb, self.canvas)
686               
687            self.selMeshObject = None
688            self.selMeshTag = None
689           
690    def selectMeshObject(self, meshObject, objectID):
691        """
692        selected a mesh object.
693        """
694        self.canvas.delete(objectID)
695        self.selMeshObject = meshObject
696        self.selMeshTag = objectID
697        meshObject.draw(self.canvas,objectID, scale =self.SCALE ,colour = SELECT_COLOR)
698   
699    def deselectMeshObject(self, meshObject, objectID):
700        """
701        deselected a mesh object.
702        """
703        self.canvas.delete(objectID)
704        self.selMeshObject = None
705        self.selMeshTag = None
706        if isinstance(meshObject, mesh.Segment):
707            meshObject.draw(self.canvas,objectID,
708                        scale =self.SCALE ,colour = SEG_COLOUR)
709        else:
710            meshObject.draw(self.canvas,objectID,
711                        scale =self.SCALE )
712           
713    def drag(self,x,y,event):
714        """
715        Hack function.  called when in select and left mouse goes down
716        """
717        pass
718   
719   
720    def drawEastingNorthingVertex(self,x,y,event):
721        """
722        draw a vertex object, plus add it to the mesh data structure
723
724        event isn't used
725        """
726        self.serial +=1
727        self.uniqueID = 'M*%d' % self.serial
728        #x_scaled =  self.SCALE*x
729        #y_scaled = -1*self.SCALE*y
730        #print "x y:", x,y
731        vert = self.Vertices.draw(x-self.mesh.geo_reference.get_xllcorner,
732                                  y-self.mesh.geo_reference.get_yllcorner,
733                                  self.mesh,
734                                  self.uniqueID,
735                                  self.SCALE,
736                                  self.canvas,
737                                  event) #FIXME why is event passed on.
738        self.UserMeshChanged = True
739        return vert
740   
741    def drawVertex(self,x,y,event):
742        """
743        draw a vertex object, plus add it to the mesh data structure
744
745        event isn't used
746        """
747        self.serial +=1
748        self.uniqueID = 'M*%d' % self.serial
749        #x_scaled =  self.SCALE*x
750        #y_scaled = -1*self.SCALE*y
751        #print "x y:", x,y
752        vert = self.Vertices.draw(x,y,self.mesh,self.uniqueID,self.SCALE,self.canvas,event)
753        self.UserMeshChanged = True
754        return vert
755     
756    def drawHole(self,x,y,event):
757        """
758        draw a hole object, plus add it to the mesh data structure
759
760        event isn't used
761        """
762        self.serial +=1
763        self.uniqueID = 'M*%d' % self.serial
764        self.userMeshChanged = True
765        hole = self.Holes.draw(x,y,self.mesh,self.uniqueID,self.SCALE,self.canvas,event)
766        return hole   
767   
768    def drawRegion(self,x,y,event):
769        """
770        draw a region object, plus add it to the mesh data structure
771
772        event isn't used
773        """
774        self.serial +=1
775        self.uniqueID = 'M*%d' % self.serial
776        region = self.Regions.draw(x,y,self.mesh,self.uniqueID,self.SCALE,self.canvas,event)
777        return region
778   
779    def selectSegmentPoint(self,x,y, event):
780        """
781        logic when selecting a vertex object to add a segment
782        """
783        found=False
784        if event.widget.find_withtag(CURRENT): # if there's a widget with a tag
785            [tag,string] = self.canvas.gettags(CURRENT) # get a list of them
786            print "tag",tag  #tags ('M*1008', 'current')
787            objectID = tag
788            #print "Found!! objectID:", objectID
789            if self.Vertices.hasKey(objectID): #isinstance(self.meshObjects[objectID],mesh.Vertex):
790                vertex = self.Vertices.getMeshObject(objectID)
791                found = True
792                print "Found! vertex", vertex
793           
794        if found and self.selVertex == vertex:
795            print "The selected vertex has already been selected"
796            #The selected vertex has already been selected
797            # therefore deselect it
798            self.deselectVertex(self.selVertex, self.selVertexTag)
799            found = False
800                 
801        if found: 
802            #A vertex has been selected!
803            if self.selVertex:
804                if self.mesh.isUserSegmentNew(self.selVertex,vertex):
805                    #vertex is the 2nd vertex
806                    self.drawSegment(vertex,self.selVertex)
807                    self.deselectVertex(self.selVertex, self.selVertexTag)
808                    self.selectVertex(vertex,objectID)
809            else:
810                print "vertex is the 1st vertex" 
811                #vertex is the 1st vertex
812                self.selectVertex(vertex,objectID)
813        else:
814            print " There are no widgets.  This happen's too much"
815                   
816
817    def selectVertex(self, vertex,objectID):
818        """
819        select a vertex object when adding a segment
820        """
821        self.canvas.delete(objectID)
822        self.selVertex = vertex
823        self.selVertexTag = objectID
824        vertex.draw(self.canvas,objectID, scale =self.SCALE ,colour = VERT_SELECT_ADDING_SEG_COLOR)
825   
826    def deselectVertex(self, vertex,objectID):
827        """
828        deselect a vertex object when adding a segment
829        """
830        self.canvas.delete(objectID)
831        self.selVertex = None
832        self.selVertexTag = None
833        vertex.draw(self.canvas,objectID,  scale =self.SCALE )
834         
835    def drawSegment(self,v1,v2):
836        """
837        Create a seg object, draw it and add it to the mesh data structure
838        """
839        self.serial +=1
840        self.uniqueID = 'M*%d' % self.serial
841        self.userMeshChanged = True
842        seg = self.Segments.draw(v1,v2,self.mesh,self.uniqueID,self.SCALE,self.canvas,None)
843        return seg
844    def printGeoReference(self):
845        try:
846            print "geo reference", self.mesh.geo_reference
847        except:
848            print "no geo reference"
849       
850    def visualiseMesh(self,mesh):
851        """
852        visualise vertices, segments, triangulation, holes
853        """
854        if self.Visualise:
855            mesh.tri_mesh.draw_triangulation(self.canvas,
856                                             scale = self.SCALE)
857
858        for segment in mesh.getUserSegments():
859            self.serial +=1
860            self.uniqueID = 'M*%d' % self.serial
861            self.Segments.visualise(segment,
862                                    self.uniqueID,
863                                    self.canvas,
864                                    self.SCALE)
865        for vertex in mesh.getUserVertices():
866            self.serial +=1
867            self.uniqueID = 'M*%d' % self.serial
868            self.Vertices.visualise(vertex,
869                                    self.uniqueID,
870                                    self.canvas,
871                                    self.SCALE)
872           
873        for hole in mesh.getHoles():
874            self.serial +=1
875            self.uniqueID = 'M*%d' % self.serial
876            self.Holes.visualise(hole,
877                                    self.uniqueID,
878                                    self.canvas,
879                                    self.SCALE)   
880        for region in mesh.getRegions():
881            self.serial +=1
882            self.uniqueID = 'M*%d' % self.serial
883            self.Regions.visualise(region,
884                                    self.uniqueID,
885                                    self.canvas,
886                                    self.SCALE)
887    def obsolete_normalise4ObjMesh(self):
888        if self.mesh:
889            self.clearSelections()
890            self.canvas.delete(ALL)
891            self.mesh.normaliseMesh(400,-200,20)
892            self.visualiseMesh(self.mesh)
893            self.ResizeToFit()
894            self.ResizeToFit()
895           
896    def obsolete_nnormaliseMesh(self):
897        if self.mesh:
898            self.clearSelections()
899            self.canvas.delete(ALL)
900            self.mesh.normaliseMesh(1,0,1)
901            self.visualiseMesh(self.mesh)
902            self.ResizeToFit()
903            self.ResizeToFit()
904           
905       
906    def clearMesh(self):
907        """Clear the current mesh object, and the canvas """
908       
909        self.clearSelections()
910        self.canvas.delete(ALL)
911        self.deleteMesh()
912        self.initData()
913        self.createMesh()
914
915    def exportObj(self):
916        fileType = "obj"
917        fileTypeDesc = "obj mesh"
918       
919        ofile = tkFileDialog.asksaveasfilename(filetypes=[(fileTypeDesc,
920                                                           fileType),
921                                                          ("All Files", "*")])
922        if ofile:
923            addOn = "." + fileType
924            jumpback = - len(addOn)
925            if ofile[jumpback:] != addOn: 
926                ofile = ofile + addOn
927            try:
928                self.mesh.exportASCIIobj(ofile)
929            except IOError:
930                showerror('Export ASCII file',
931                                   'Can not write to file.')
932            except RuntimeError:
933                showerror('Export ASCII file',
934                                   'No triangulation to export.')
935
936   
937
938    def ImportUngenerate(self):
939        ofile = tkFileDialog.askopenfilename(initialdir=self.currentPath,
940                   filetypes=[ ("ungenerated polygon information", "txt"),
941                                           ("All Files", "*")])
942        if ofile == "":
943            # The user cancelled the loading action
944            return
945       
946        try:
947            self.clearSelections()
948            self.canvas.delete(ALL)
949            dict = mesh.importUngenerateFile(ofile)
950            self.mesh.addVertsSegs(dict)
951           
952        except SyntaxError: 
953            # This is assuming that the SyntaxError is thrown in
954            # importUngenerateFile
955            showerror('File error',
956                      ofile + ' is not in the correct format.')
957        except IOError: 
958            #!!! this error type can not be thrown?
959            showerror('File error',
960                      'file ' + ofile + ' could not be found.')
961        except RuntimeError: 
962            showerror('File error',
963                  'file ' + ofile + ' has an unknown file type.')
964   
965        self.visualiseMesh(self.mesh)
966        self.ResizeToFit()
967       
968    def exportASCIIsegmentoutlinefile(self):
969       
970        ofile = tkFileDialog.asksaveasfilename(initialdir=self.currentPath,
971                                               filetypes=[("mesh", "*.tsh *.msh"),
972                                             ("All Files", "*")])
973           
974        if ofile:
975            # .tsh is the default file format
976            if (ofile[-4:] == ".tsh" or ofile[-4:] == ".msh"): 
977                self.currentFilePathName = ofile
978            else:
979                self.currentFilePathName = ofile + ".tsh"
980               
981            try:
982                self.mesh.exportASCIIsegmentoutlinefile(ofile)
983            except IOError: #FIXME should this function be throwing any errors?
984                showerror('Export ASCII file',
985                                   'Can not write to file.')
986
987    def exportPointsFile(self):
988        ofile = tkFileDialog.asksaveasfilename(initialdir=self.currentPath,
989                                         filetypes=[("point files",
990                                                     "*.csv *.txt *.pts"),
991                                                ("All Files", "*")])
992        if ofile:
993            # .csv is the default file format
994            if (ofile[-4:] == ".csv" or ofile[-4:] == ".pts"): 
995                self.currentFilePathName = ofile
996            else:
997                self.currentFilePathName = ofile + ".csv"
998               
999            try:
1000                self.mesh.exportPointsFile(ofile)
1001            except IOError:
1002                showerror('Export ASCII file',
1003                                   'Can not write to file.')
1004                   
1005    def importFile(self):
1006        """
1007        import mesh data from a variety of formats (currently 2!)
1008        """
1009        print "self.currentPath",self.currentPath
1010        ofile = tkFileDialog.askopenfilename(initialdir=self.currentPath,
1011                                             filetypes=[ ("text Mesh",
1012                                                          "*.tsh *.msh"),
1013                                                         ("points",
1014                                                          "*.csv *.txt *.pts"),
1015                                                         ("All Files", "*")])
1016        if ofile == "":
1017            # The user cancelled the loading action
1018            return
1019       
1020        try:
1021            newmesh = mesh.importMeshFromFile(ofile)
1022            self.currentPath, dummy = os.path.split(ofile)
1023            #print "be good self.currentPath",self.currentPath
1024            self.currentFilePathName = ofile
1025            self.clearMesh()
1026            self.mesh = newmesh
1027
1028            #FIXME - to speed things up, don't visualise the mesh
1029            # use ResizeToFitWrapper
1030            self.visualiseMesh(self.mesh)
1031            self.ResizeToFit()
1032       
1033        except IOError: 
1034            #!!! this error type can not be thrown?
1035            showerror('File error',
1036                      'file ' + ofile + ' could not be loaded.')
1037
1038        except RuntimeError: 
1039            showerror('File error',
1040                  'file ' + ofile + ' has an unknown file type.')
1041        # Could not get the file name to showup in the title
1042        #appname =  ofile + " - " + APPLICATION_NAME
1043        #print "appname",appname
1044       
1045        except load_mesh.loadASCII.TitleAmountError: 
1046            showerror('File error',
1047                  'file ' + ofile + ' has a bad title line (first line).')
1048
1049   
1050    def ResizeToFitWrapper(self, Parent):
1051        """
1052        The parent attribute isn't used by this function.
1053        need to understand toolbarbutton.py to know how to
1054        get rid of it.
1055        """
1056        self.ResizeToFit()
1057       
1058    def ResizeToFit(self):
1059        """Visualise the mesh so it fits in the window"""
1060        if self.mesh.getUserVertices() == []:
1061            return #There are no vertices!
1062        # Resize the window
1063        self.scrolledcanvas.resizescrollregion()
1064        # I need this so the xview values are correct
1065        self.scrolledcanvas.update()
1066       
1067        xtop, xbottom = self.scrolledcanvas.xview()
1068        ytop, ybottom = self.scrolledcanvas.yview()
1069        xdiff = xbottom-xtop
1070        ydiff = ybottom-ytop
1071        if xdiff == 1 and xdiff == 1:
1072            #The mesh might be too small.
1073            #Make it too large, then resize
1074            #!!! Recursive hack.  Should be a better way
1075            fraction = 50
1076            self.SCALE *= fraction
1077            self.scrolledcanvas.scale(ALL, 0, 0, fraction, fraction)
1078            self.ResizeToFit()
1079        else:
1080            # without 0.99 some of the mesh may be off screen
1081            fraction = 0.99*min(xdiff,ydiff) 
1082            self.selectZoom(fraction)
1083           
1084    def saveDrawing(self):
1085        """
1086        Save the current drawing
1087        """
1088        #print "dsg!!! self.currentFilePathName ",self.currentFilePathName
1089        if (self.currentFilePathName[-4:] != ".tsh" or
1090            self.currentFilePathName[-4:] != ".msh"):
1091            # force user to choose a name
1092            self.saveAsDrawing()
1093        else:
1094            self.exportASCIItriangulationfile(self.currentFilePathName)
1095
1096    def saveAsDrawing(self):
1097        """
1098        Save the current drawing, prompting for a file name
1099        """
1100        ofile = tkFileDialog.asksaveasfilename(initialdir=self.currentPath,
1101                                               filetypes=[("mesh", "*.tsh *.msh"),
1102                                             ("All Files", "*")])
1103           
1104        if ofile:
1105            # .tsh is the default file format
1106            if (ofile[-4:] == ".tsh" or ofile[-4:] == ".msh"): 
1107                self.currentFilePathName = ofile
1108            else:
1109                self.currentFilePathName = ofile + ".tsh"
1110            self.exportASCIItriangulationfile(self.currentFilePathName)
1111
1112    def exportASCIItriangulationfile(self,currentFilePathName):
1113        """
1114        Have a warning prompt when saving a mesh where the generated mesh is
1115        different from the user mesh - eg boundary tags that aren't carried
1116        thru. Warning ~"Mesh not generated after changes.  Generate mesh?  "
1117        - cancel, don't gen, don't save.  Yes - generate mesh, go to save
1118        screen.  No - goto save screen.  To implement this need to know when
1119        the user has done a change, and the mesh hasn't been generated.  If
1120        there is no generated mesh do not prompt.
1121        """
1122        #print "self.UserMeshChanged",self.UserMeshChanged
1123        #print "self.mesh.isTriangulation()",self.mesh.isTriangulation()
1124        if (self.UserMeshChanged) and self.mesh.isTriangulation():
1125           
1126            m = _show("Warning",
1127                                   "A triangulation has not been generated, after mesh changes.  Generate triangulation before saving?",
1128                                   icon=QUESTION, 
1129                                   type=YESNOCANCEL)
1130            if m == "no":
1131                self.mesh.export_mesh_file(currentFilePathName)
1132                self.UserMeshChanged = False
1133            elif m == "cancel":
1134                pass
1135            elif m == "yes":
1136                self.windowMeshGen(None)
1137                self.mesh.export_mesh_file(currentFilePathName)
1138        else:
1139            self.mesh.export_mesh_file(currentFilePathName)
1140            self.UserMeshChanged = False
1141           
1142    def initData(self):
1143        """
1144        Initialise various lists and flags
1145        """
1146        self.serial      = 1000
1147        self.currentFilePathName = 'untitled'
1148
1149        # these are attributes I've added
1150        self.SCALE       = 1
1151        self.selVertex   = None     #The last vertex selected, in draw seg mode
1152        self.selVertexTag   = None     # The selected vertex drawn object tag
1153        self.mesh        = None
1154        self.MeshMinAngle = 20
1155        self.MeshMaxArea = 200
1156        self.MeshnumTriangles = 20
1157        self.MeshMaxAreaLast = False
1158        self.selMeshObject = None  # The mesh object selected in the current mode
1159        self.selMeshTag = None
1160        mesh.Segment.set_default_tag("")
1161        self.UserMeshChanged = False
1162        self.meshLastAlpha = None
1163       
1164        self.Visualise = True #Is the mesh shown or not?
1165   
1166    def ipostscript(self):
1167        """
1168        Print the canvas as a postscript file
1169        """
1170        ofile = tkFileDialog.asksaveasfilename(initialdir=self.currentPath,
1171                                               filetypes=[("postscript", "ps"),
1172                                                          ("All Files", "*")]) 
1173        if ofile:
1174            if ofile[-3:] != ".ps": 
1175                ofile = ofile + ".ps"
1176            postscript = self.canvas.postscript()
1177            fd = open(ofile, 'w')
1178            fd.write(postscript)
1179            fd.close()
1180       
1181    def close(self):
1182        self.quit()
1183       
1184    def createInterface(self):
1185        """
1186        Call all functions that create the GUI interface
1187        """
1188        self.initData()
1189        self.createMesh()
1190        AppShell.AppShell.createInterface(self)
1191        self.createButtons()
1192        self.createMenus()
1193        self.createBase()
1194        self.createTools()
1195        self.createZooms()
1196        self.createEdits()
1197        self.createVisualiseIcons()
1198        #print "FIX THIS BEFORE "
1199        #self.addCylinders() # !!!DSG start pmesh with a triangle
1200        self.selectFunc('pointer')
1201        self.currentPath = os.getcwd() 
1202
1203    def loadtestmesh(self,ofile):
1204        """
1205        debugging script to test loading a file
1206        """
1207        fd = open(ofile)
1208        a = mesh.Vertex (-10.0, 0.0)
1209        d = mesh.Vertex (0.0, 4.0)
1210        f = mesh.Vertex (4.0,0.0)
1211        g = mesh.Vertex (-5.0,5.0)
1212       
1213        s1 = mesh.Segment(a,d)
1214        s2 = mesh.Segment(d,f)
1215        s3 = mesh.Segment(a,f)
1216
1217        r1 = mesh.Region(0.3, 0.3)
1218       
1219        m = mesh.Mesh(userVertices=[a,d,f,g], userSegments=[s1,s2,s3], regions=[r1] )
1220       
1221        fd.close()
1222        print 'returning m'
1223        return oadtestmesh(ofile)
1224         
1225class  AddVertexDialog(Dialog):
1226    """
1227    Dialog box for adding a vertex by entering co-ordindates
1228    """
1229    def body(self, master):
1230        """
1231        GUI description
1232        """
1233        self.title("Add New Vertex")
1234       
1235        Label(master, text='X position:').grid(row=0, sticky=W)
1236        Label(master, text='Y position:').grid(row=1, sticky=W)
1237
1238        self.xstr   = Entry(master, width = 16, name ="entry")
1239        self.ystr  = Entry(master, width = 16)
1240       
1241        self.xstr.grid(row=0, column=1, sticky=W)
1242        self.ystr.grid(row=1, column=1, sticky=W)
1243        self.xstr.focus_force()
1244        self.= 0
1245        self.= 0
1246        self.xyValuesOk = False
1247 
1248
1249    def apply(self):
1250        """
1251        check entered values
1252        """
1253        try:
1254            self.x = float(self.xstr.get())
1255            self.y = float(self.ystr.get())
1256            self.xyValuesOk = True
1257           
1258        except ValueError:
1259            showerror('Bad Vertex values',
1260                                   'X Y values are not numbers.')
1261       
1262
1263class  auto_segmentDialog(Dialog):
1264    """
1265    Dialog box for adding segments
1266    """
1267    def __init__(self, parent, alpha):
1268        self.alpha = alpha
1269        Dialog.__init__(self, parent)
1270       
1271    def body(self, master):
1272        """
1273        GUI description
1274        """
1275        self.title("Automatically Add Segments")
1276
1277        self.use_optimum = IntVar()
1278        self.use_optimum.set(AUTO) # should initialise the radio buttons.
1279                                   #  It doesn't
1280                                   
1281        #self.use_optimum.set(NO_SELECTION)
1282        self.ck = Radiobutton(master, value = AUTO, variable=self.use_optimum) 
1283        self.ck.grid(row=1, column=0)
1284        Label(master, text='Use optimum alpha').grid(row=1, column=1, sticky=W)
1285
1286        self.ck2 = Radiobutton(master, value = SET_ALPHA,
1287                               variable=self.use_optimum) 
1288        self.ck2.grid(row=2, column=0)
1289       
1290        Label(master, text='alpha:').grid(row=2, column=1, sticky=W)
1291        if (self.alpha):
1292            alphaVar = StringVar()
1293            alphaVar.set(self.alpha)
1294            self.alpha_str  = Entry(master,
1295                                     textvariable = alphaVar,
1296                                     width = 16, name ="entry") 
1297        else: 
1298            self.alpha_str = Entry(master, width = 16, name ="entry")
1299       
1300        self.alpha_str.grid(row=2, column=3, sticky=W)
1301
1302        #boundary type buttons
1303        self.raw_boundary = IntVar()
1304        self.remove_holes = IntVar()
1305        self.smooth_indents = IntVar()
1306        self.expand_pinch = IntVar()
1307        self.ck3 = Checkbutton(master, state=NORMAL,
1308                               variable=self.raw_boundary) 
1309        self.ck3.grid(row=3, column=0)
1310        Label(master, text='Raw boundary').grid(row=3, column=1, sticky=W)
1311        #
1312        self.ck4 = Checkbutton(master, state=NORMAL,
1313                               variable=self.remove_holes) 
1314        self.ck4.grid(row=4, column=0)
1315        Label(master, text='Remove small holes').grid(row=4,column=1, sticky=W)
1316        #
1317        self.ck5 = Checkbutton(master,state=NORMAL,
1318                               variable=self.smooth_indents) 
1319        self.ck5.grid(row=5, column=0)
1320        Label(master,
1321              text='Remove sharp indents').grid(row=5, column=1, sticky=W)
1322        #
1323        self.ck6 = Checkbutton(master,state=NORMAL,
1324                               variable=self.expand_pinch) 
1325        self.ck6.grid(row=6, column=0)
1326        Label(master,
1327              text='Remove pinch off').grid(row=6, column=1,  sticky=W)
1328
1329       
1330        self.alpha  = 0
1331        self.alphaValueOk = False
1332       
1333
1334    def apply(self):
1335        """
1336        check entered values
1337        """
1338        try:
1339            self.alpha = float(self.alpha_str.get())
1340            self.alphaValueOk = True
1341           
1342        except ValueError:
1343            pass
1344            #showerror('Bad Alpha value',
1345            #                       'Alpha is negative.')
1346
1347
1348class  auto_segmentFilterDialog(Dialog):
1349    """
1350    Dialog box for adding segments
1351    """
1352    def __init__(self, parent):
1353        Dialog.__init__(self, parent)
1354       
1355    def body(self, master):
1356        """
1357        GUI description
1358        """
1359        self.title("Automatically Add Segments")
1360
1361        self.use_optimum = IntVar()
1362        self.use_optimum.set(AUTO) # should initialise the radio buttons.
1363                                   #  It doesn't
1364        self.boundary_type = IntVar()
1365                     
1366        #boundary type buttons
1367        self.raw_boundary = IntVar()
1368        self.remove_holes = IntVar()
1369        self.smooth_indents = IntVar()
1370        self.expand_pinch = IntVar()
1371       
1372        self.ck3 = Checkbutton(master, state=NORMAL,
1373                               variable=self.raw_boundary) 
1374        self.ck3.grid(row=3, column=0)
1375        Label(master, text='Raw boundary').grid(row=3, column=1, sticky=W)
1376        #
1377        self.ck4 = Checkbutton(master, state=NORMAL,
1378                               variable=self.remove_holes) 
1379        self.ck4.grid(row=4, column=0)
1380        Label(master, text='Remove small holes').grid(row=4,column=1, sticky=W)
1381        #
1382        self.ck5 = Checkbutton(master,state=NORMAL,
1383                               variable=self.smooth_indents) 
1384        self.ck5.grid(row=5, column=0)
1385        Label(master,
1386              text='Remove sharp indents').grid(row=5, column=1, sticky=W)
1387        #
1388        self.ck6 = Checkbutton(master,state=NORMAL,
1389                               variable=self.expand_pinch) 
1390        self.ck6.grid(row=6, column=0)
1391        Label(master,
1392              text='Remove pinch off').grid(row=6, column=1,  sticky=W)
1393       
1394       
1395
1396
1397class  MeshGenDialog(Dialog):
1398    """
1399    Dialog box for generating a mesh
1400    """
1401    # initial values, hard coded.
1402    # should be values associated with the current mesh
1403    lastMinAngle = 20
1404    lastMaxArea  = 100
1405
1406
1407    def __init__(self,
1408                 parent,
1409                 minAngle,
1410                 maxArea,
1411                 numTriangles,
1412                 MeshMaxAreaLast):
1413        self.minAngle = minAngle
1414        self.maxArea = maxArea
1415        self.numTriangles = numTriangles
1416        self.MeshMaxAreaLast = MeshMaxAreaLast
1417
1418        Dialog.__init__(self, parent)
1419
1420       
1421    def body(self, master):
1422        """
1423        GUI description
1424        """
1425        self.title("Generate Mesh")
1426       
1427        Label(master,
1428              text='Minimum Angle(0 - 40):').grid(row=0, sticky=W)
1429        Label(master,
1430              text='Angles>33 may not converge').grid(row=1, sticky=W)
1431        Label(master, text='Maximum Area:').grid(row=2, sticky=W)
1432        Label(master, text='OR # of triangles:').grid(row=3, sticky=W)
1433
1434
1435        minAngleVar = StringVar()
1436        minAngleVar.set(self.minAngle)
1437        self.minAnglestr   = Entry(master,
1438                                   width = 16,
1439                                   textvariable = minAngleVar,
1440                                   takefocus=1)
1441        if (self.MeshMaxAreaLast):
1442            maxAreaVar = StringVar()
1443            maxAreaVar.set(self.maxArea)
1444            self.maxAreastr  = Entry(master,
1445                                     textvariable = maxAreaVar,
1446                                     width = 16)   
1447            self.numTrianglesstr  = Entry(master,
1448                                          width = 16) 
1449        else: 
1450            self.maxAreastr  = Entry(master,
1451                                     width = 16)
1452            self.maxAreastr.focus_force()
1453            numTrianglesVar = StringVar()
1454            numTrianglesVar.set(self.numTriangles)   
1455            self.numTrianglesstr  = Entry(master,
1456                                          textvariable = numTrianglesVar,
1457                                          width = 16) 
1458
1459
1460        self.minAnglestr.grid(row=0, column=1, sticky=W)
1461        self.maxAreastr.grid(row=2, column=1, sticky=W)
1462        self.numTrianglesstr.grid(row=3, column=1, sticky=W)
1463
1464        self.numTriangles = 0
1465        self.minAngle  = 0
1466        self.maxArea  = 0
1467        self.ValuesOk = False
1468
1469
1470    def apply(self):
1471        """
1472        check entered values
1473        """
1474        self.goodMaxArea = self.goodNumTriangles = True
1475        self.ValuesOk = True
1476        try:
1477            self.minAngle = float(self.minAnglestr.get())
1478            MeshGenDialog.lastMinAngle =self.minAngle
1479        except ValueError:
1480            self.ValuesOk = False
1481            showerror('Bad mesh generation values',
1482                                   ' Values are not numbers.')
1483       
1484        try:   
1485            self.maxArea = float(self.maxAreastr.get())
1486            MeshGenDialog.lastMaxArea =self.maxArea
1487        except ValueError:
1488            self.goodMaxArea = False
1489         
1490        try:   
1491            self.numTriangles = int(self.numTrianglesstr.get())
1492            MeshGenDialog.lastNumTriangles =self.numTriangles
1493        except ValueError:
1494            self.goodNumTriangles= False
1495
1496        if self.goodMaxArea == False and self.goodNumTriangles == False:
1497            self.ValuesOk = False
1498            showerror('Bad mesh generation values',
1499                      'Values are not numbers.')
1500
1501        if self.goodMaxArea == True and self.goodNumTriangles == True:
1502            self.ValuesOk = False
1503            showerror('Bad mesh generation values',
1504                      'Give a maximum area OR number of triangles, not both.')
1505
1506        try: 
1507            # value checking
1508            if self.minAngle <0.0 or self.minAngle >40.0:
1509                raise IOError
1510            if self.goodMaxArea == True and self.maxArea <0.0:
1511                raise IOError
1512            if self.goodNumTriangles == True and self.numTriangles <=0:
1513                raise IOError
1514           
1515        except IOError:
1516            self.ValuesOk = False
1517            showerror('Bad mesh generation values',
1518                                   'Values are out of range.')
1519       
1520if __name__ == '__main__':
1521    draw = Draw()
1522    draw.run()
1523    #profile.run('draw.run()', 'pmeshprof')   
1524
Note: See TracBrowser for help on using the repository browser.