source: sasview/src/sas/sasgui/perspectives/simulation/SimCanvas.py @ a5e1b6ca

ticket-1249
Last change on this file since a5e1b6ca was 34f23c8, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

py3/wx4 compatibility changes for gui. Refs #1249

  • Property mode set to 100644
File size: 19.1 KB
RevLine 
[959eb01]1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
[34f23c8]4project funded by the US National Science Foundation.
[959eb01]5
6See the license text in license.txt
7
8copyright 2009, University of Tennessee
9"""
10import wx
11import math
12
13try:
14    import OpenGL
15except:
16    import sys, os
17    sys.path.insert(1,os.path.dirname(sys.executable))
18
19import OpenGL.GL
20try:
21    from wx import glcanvas
22    haveGLCanvas = True
23except ImportError:
24    haveGLCanvas = False
25try:
26    # The Python OpenGL package can be found at
27    # http://PyOpenGL.sourceforge.net/
28    from OpenGL.GL import *
29    from OpenGL.GLU import *
30    from OpenGL.GLUT import *
31    haveOpenGL = True
32except ImportError:
33    haveOpenGL = False
[34f23c8]34
[959eb01]35# Color set
[34f23c8]36DEFAULT_COLOR = [1.0, 1.0, 0.0, .2]
[959eb01]37COLOR_RED     = [1.0, 0.0, 0.0, .2]
38COLOR_GREEN   = [0.0, 1.0, 0.0, .2]
39COLOR_BLUE    = [0.0, 0.0, 1.0, .2]
40COLOR_YELLOW  = [1.0, 1.0, 0.0, .2]
41COLOR_HIGHLIGHT = [.2, .2, .8, .5]
42
43# List of shapes
44SHAPE_LIST = []
45
46import ShapeParameters
47
48class SimPanel(wx.Panel):
49    """
[34f23c8]50        3D viewer to support real-space simulation.
[959eb01]51    """
52    window_name = "3dview"
53    window_caption = "3D viewer"
[34f23c8]54
[959eb01]55    def __init__(self, parent, id = -1, plots = None, standalone=False, **kwargs):
56        wx.Panel.__init__(self, parent, id = id, **kwargs)
57        self.parent = parent
[34f23c8]58
[959eb01]59        #Add a sizer
60        mainSizer = wx.BoxSizer(wx.VERTICAL)
61        sliderSizer = wx.BoxSizer(wx.HORIZONTAL)
[34f23c8]62
63        self.canvas    = CanvasBase(self)
[959eb01]64        self.canvas.SetMinSize((200,2100))
65
66        #Add the model to it's sizer
67        mainSizer.Add(self.canvas, 1, wx.EXPAND)
68
69        #Add the Subsizers to mainsizer
70        mainSizer.Add(sliderSizer, 0, wx.EXPAND)
71
72        self.SetSizer(mainSizer)
73        self.Bind(wx.EVT_CONTEXT_MENU, self._on_context_menu)
[34f23c8]74
75
[959eb01]76    def _on_context_menu(self, event):
77        """
78            Default context menu for a plot panel
79        """
80        # Slicer plot popup menu
81        id = wx.NewId()
82        slicerpop = wx.Menu()
83        slicerpop.Append(id, '&Reset 3D View')
84        wx.EVT_MENU(self, id, self.canvas.resetView)
[34f23c8]85
[959eb01]86        pos = event.GetPosition()
87        pos = self.ScreenToClient(pos)
[34f23c8]88        self.PopupMenu(slicerpop, pos)
89
[959eb01]90class CanvasBase(glcanvas.GLCanvas):
91    """
92        3D canvas to display OpenGL 3D shapes
93    """
94    window_name = "Simulation"
95    window_caption = "Simulation"
[34f23c8]96
[959eb01]97    def __init__(self, parent):
98        glcanvas.GLCanvas.__init__(self, parent, -1)
99        self.init = False
100        # initial mouse position
101        self.lastx = self.x = 30
102        self.lasty = self.y = 30
103        self.tr_lastx = self.tr_x = 30
104        self.tr_lasty = self.tr_y = 30
105        self.size = None
106        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
107        self.Bind(wx.EVT_SIZE, self.OnSize)
108        self.Bind(wx.EVT_PAINT, self.OnPaint)
109        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
110        self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseDown)
111        self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
112        self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
113        self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
114        self.Bind(wx.EVT_MOUSEWHEEL, self._onMouseWheel)
[34f23c8]115
[959eb01]116        self.initialized = False
117        self.shapes = []
118        self.parent = parent
[34f23c8]119
[959eb01]120        # Reference vectors
121        self.x_vec = [1,0,0]
122        self.y_vec = [0,1,0]
[34f23c8]123
[959eb01]124        self.mouse_down = False
125        self.scale = 1.0
126        self.zoom  = 1.0
127        self.translation = [0,0,0]
[34f23c8]128
[959eb01]129        # Bind to Edit events
130        self.parent.Bind(ShapeParameters.EVT_EDIT_SHAPE, self._onEditShape)
[34f23c8]131
[959eb01]132    def resetView(self, evt=None):
133        """
134            Resets zooming, translation and rotation.
135        """
136        self.zoom = 1.0
137        self.scale = 1.0
138        self.x_vec = [1,0,0]
139        self.y_vec = [0,1,0]
140        glLoadIdentity()
141        self.Refresh()
[34f23c8]142
[959eb01]143    def _onEditShape(self, evt):
144        evt.Skip()
145        evt.shape.highlight(True)
146        for item in self.shapes:
147            if not item == evt.shape:
148                item.highlight(False)
149        self.Refresh(False)
150
151    def OnEraseBackground(self, event):
152        pass # Do nothing, to avoid flashing on MSW.
153
154    def OnSize(self, event):
155        size = self.size = self.GetClientSize()
156        if self.GetContext():
157            glViewport(0, 0, size.width, size.height)
158        event.Skip()
159
[34f23c8]160    def OnPaint(self, event):
[959eb01]161        size = self.GetClientSize()
162        side = size.width
163        if size.height<size.width:
164            side = size.height
[34f23c8]165
[959eb01]166        if self.GetContext():
167            glViewport(0, 0, side, side)
168            self.SetMinSize((side,side))
[34f23c8]169
[959eb01]170        dc = wx.PaintDC(self)
171        self.SetCurrent()
172        if not self.init:
173            self.InitGL()
174            self.init = True
175        self.OnDraw()
[34f23c8]176        event.Skip()
177
[959eb01]178    def _onMouseWheel(self, evt):
179        # Initialize mouse position so we don't have unwanted rotation
180        self.x, self.y = self.lastx, self.lasty = evt.GetPosition()
181        self.tr_x, self.tr_y = self.tr_lastx, self.tr_lasty = evt.GetPosition()
[34f23c8]182
[959eb01]183        scale = 1.15
184        if evt.GetWheelRotation()<0:
185            scale = 1.0/scale
[34f23c8]186
187        self.zoom *= scale
188
[959eb01]189        glScale(scale, scale, scale)
190        self.Refresh(False)
[34f23c8]191
[959eb01]192    def OnMouseDown(self, evt):
193        self.SetFocus()
194        self.CaptureMouse()
195        self.x, self.y = self.lastx, self.lasty = evt.GetPosition()
196        self.tr_x, self.tr_y = self.tr_lastx, self.tr_lasty = self.x, self.y
197        self.mouse_down = True
198
199    def OnMouseUp(self, evt):
200        self.ReleaseMouse()
201        self.mouse_down = False
202
203    def OnRightUp(self, evt):
204        self.OnMouseUp(evt)
205        if self.x==self.tr_lastx and self.y==self.tr_lasty:
206            self._on_context_menu(evt)
207
208    def _on_context_menu(self, event):
209        """
210            Default context menu for a plot panel
211        """
212        id = wx.NewId()
213        slicerpop = wx.Menu()
214        slicerpop.Append(id, '&Reset 3D View')
215        wx.EVT_MENU(self, id, self.resetView)
[34f23c8]216
[959eb01]217        pos = event.GetPosition()
218        #pos = self.ScreenToClient(pos)
[34f23c8]219        self.PopupMenu(slicerpop, pos)
[959eb01]220
221    def OnMouseMotion(self, evt):
222        if evt.Dragging() and evt.LeftIsDown():
223            self.tr_lastx, self.tr_lasty = self.tr_x, self.tr_y
224            x, y = evt.GetPosition()
[34f23c8]225
[959eb01]226            # Min distance to do anything
227            if math.fabs(self.lastx-x)>10 or math.fabs(self.lasty-y)>10:
[34f23c8]228
[959eb01]229                self.lastx, self.lasty = self.x, self.y
[34f23c8]230
231
[959eb01]232                if math.fabs(self.lastx-x)>math.fabs(self.lasty-y):
233                    self.x = x
234                else:
235                    self.y = y
[34f23c8]236
[959eb01]237                #self.x, self.y = evt.GetPosition()
238                self.Refresh(False)
[34f23c8]239
[959eb01]240        elif evt.Dragging() and evt.RightIsDown():
241            self.lastx, self.lasty = self.x, self.y
242            self.tr_lastx, self.tr_lasty = self.tr_x, self.tr_y
243            self.tr_x, self.tr_y = evt.GetPosition()
244            self.Refresh(False)
[34f23c8]245
246    def InitGL( self ):
[959eb01]247        glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA)
248        #glShadeModel(GL_FLAT);
[34f23c8]249
[959eb01]250        glMatrixMode(GL_PROJECTION)
[34f23c8]251
[959eb01]252        glLight(GL_LIGHT0, GL_AMBIENT, [.2, .2, .2, 0])
[34f23c8]253
[959eb01]254        # Object color
255        #glLight(GL_LIGHT0, GL_DIFFUSE, COLOR_BLUE)
[34f23c8]256
[959eb01]257        glLight(GL_LIGHT0, GL_POSITION, [1.0, 1.0, -1.0, 0.0])
[34f23c8]258
259
[959eb01]260        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [1, 1, 1, 0])
261        glEnable(GL_LIGHTING)
262        glEnable(GL_LIGHT0)
263        glEnable(GL_BLEND)
264        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
[34f23c8]265
[959eb01]266        glEnable ( GL_ALPHA_TEST ) ;
267        glAlphaFunc ( GL_GREATER, 0 ) ;
268        glPixelStorei(GL_PACK_ALIGNMENT, 1)
269        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
[34f23c8]270
[959eb01]271        glEnable(GL_NORMALIZE)
272        glDepthFunc(GL_LESS)
273        glEnable(GL_DEPTH_TEST)
274        glDepthMask(GL_TRUE);
275        glClearColor (1.0, 1.0, 1.0, 0.0);
276        #glClear (GL_COLOR_BUFFER_BIT);
277        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
[34f23c8]278
279
[959eb01]280        gluPerspective(0, 1.0, 0.1, 60.0);
281
282        glMatrixMode(GL_MODELVIEW)
283
284    def getMaxSize(self):
285        max_size = 0.0
286        # Ready to draw shapes
287        for item in self.shapes:
288            item.draw()
289            l = item.get_length()
290            if l>max_size:
291                max_size = l
292        return max_size
293
294    def OnDraw(self):
295        # clear color and depth buffers
296        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
297        # use a fresh transformation matrix
[34f23c8]298
[959eb01]299        # get the max object size to re-scale
300        max_size = 1.0
301        # Ready to draw shapes
302        for item in self.shapes:
303            item.draw()
304            l = item.get_length()
305            if l>max_size:
306                max_size = l
[34f23c8]307
[959eb01]308        max_size *= 1.05
309        scale = self.scale/max_size
310        glScale(scale, scale, scale)
311        self.scale = max_size
[34f23c8]312
[959eb01]313        self.drawAxes()
[34f23c8]314
[959eb01]315        if self.mouse_down:
316            if math.fabs((self.x - self.lastx))>math.fabs((self.y - self.lasty)):
[34f23c8]317                angle = 10.0*(self.x - self.lastx) / math.fabs(self.x - self.lastx)
[959eb01]318                glRotate(angle, self.y_vec[0], self.y_vec[1], self.y_vec[2]);
319                self._rot_y(angle)
320            elif math.fabs(self.y - self.lasty)>0:
[34f23c8]321                angle = 10.0*(self.y - self.lasty) / math.fabs(self.y - self.lasty)
[959eb01]322                glRotate(angle, self.x_vec[0], self.x_vec[1], self.x_vec[2]);
323                self._rot_x(angle)
324
325            self.lasty = self.y
326            self.lastx = self.x
[34f23c8]327
328            w, h = self.GetVirtualSize()
329
[959eb01]330            # Translate in the x-y plane
331            vx = self.x_vec[0] * 2.0*float(self.tr_x - self.tr_lastx)/w \
332               + self.y_vec[0] * 2.0*float(self.tr_lasty - self.tr_y)/h
333            vy = self.x_vec[1] * 2.0*float(self.tr_x - self.tr_lastx)/w \
334               + self.y_vec[1] * 2.0*float(self.tr_lasty - self.tr_y)/h
335            vz = self.x_vec[2] * 2.0*float(self.tr_x - self.tr_lastx)/w \
336               + self.y_vec[2] * 2.0*float(self.tr_lasty - self.tr_y)/h
[34f23c8]337
338            glTranslate(self.scale*vx/self.zoom, self.scale*vy/self.zoom, self.scale*vz/self.zoom)
339
[959eb01]340        # push into visible buffer
341        self.SwapBuffers()
[34f23c8]342
[959eb01]343    def _matrix_mult(self, v, axis, angle):
344        c = math.cos(angle)
[34f23c8]345        s = math.sin(angle)
[959eb01]346        x = axis[0]
347        y = axis[1]
348        z = axis[2]
349        vx = v[0]*(x*x*(1-c)+c)   + v[1]*(x*y*(1-c)-z*s) + v[2]*(x*z*(1-c)+y*s)
350        vy = v[0]*(y*x*(1-c)+z*s) + v[1]*(y*y*(1-c)+c)   + v[2]*(y*z*(1-c)-x*s)
351        vz = v[0]*(x*z*(1-c)-y*s) + v[1]*(y*z*(1-c)+x*s) + v[2]*(z*z*(1-c)+c)
352        return [vx, vy, vz]
[34f23c8]353
[959eb01]354    def _rot_y(self, theta):
355        """
356            Rotate the view by theta around the y-axis
357        """
[34f23c8]358        angle = theta/180.0*math.pi
[959eb01]359        axis = self.y_vec
360        self.x_vec = self._matrix_mult(self.x_vec, self.y_vec, -angle)
[34f23c8]361
[959eb01]362    def _rot_x(self, theta):
363        """
364            Rotate the view by theta around the x-axis
365        """
366        angle = theta/180.0*math.pi
367        self.y_vec = self._matrix_mult(self.y_vec, self.x_vec, -angle)
[34f23c8]368
369
[959eb01]370    def addShape(self, shape, name=None):
371        """
372            Add a shape to the list of displayed shapes
373            @param shape: BaseShape object
374            @param name: name given to the shape
375        """
376        if not name==None:
377            shape.name = name
378        shape.params['order']=len(self.shapes)
379        self.shapes.append(shape)
380        self.Refresh(False)
381
382    def delShape(self, name):
383        """
384            Delete a shape by name
385            @param name: name of the shape to be deleted
386        """
387        for i in range(len(self.shapes)):
388            if self.shapes[i].name == name:
389                del self.shapes[i]
390                break
391        self.Refresh(False)
392
393    def getMaxVolume(self):
394        """
395            Returns the maximum volume of the combination of all shapes.
396            The maximum volume is the simple sum of the volumes of all the shapes.
397            @return: sum of the volumes of all the shapes [float]
398        """
399        sum = 0
400        for item in self.shapes:
401            sum += item.get_volume()
402        return sum
403
404    def drawAxes(self):
[34f23c8]405        """
[959eb01]406            Draw 3D axes
407        """
408        pos = self.scale * 0.7
[34f23c8]409
[959eb01]410        # Z-axis is red
[34f23c8]411        zaxis= Arrow(x=pos, y=-pos, z=0, r_cyl=self.scale*0.005, r_cone=self.scale*0.01,
[959eb01]412                     l_cyl=self.scale*0.1, l_cone=self.scale*0.05)
413        zaxis.color = COLOR_RED
414        zaxis.draw()
[34f23c8]415
[959eb01]416        # Y-axis is yellow
[34f23c8]417        yaxis= Arrow(x=pos, y=-pos, z=0, r_cyl=self.scale*0.005, r_cone=self.scale*0.01,
[959eb01]418                     l_cyl=self.scale*0.1, l_cone=self.scale*0.05)
419        yaxis.color = COLOR_YELLOW
420        yaxis.rotate(-90,0,0)
421        yaxis.draw()
[34f23c8]422
[959eb01]423        # X-axis is green
[34f23c8]424        xaxis= Arrow(x=pos, y=-pos, z=0, r_cyl=self.scale*0.005, r_cone=self.scale*0.01,
[959eb01]425                     l_cyl=self.scale*0.1, l_cone=self.scale*0.05)
426        xaxis.color = COLOR_GREEN
427        xaxis.rotate(0,-90,0)
428        xaxis.draw()
[34f23c8]429
[959eb01]430        glLight(GL_LIGHT0, GL_DIFFUSE, DEFAULT_COLOR)
431
432
433class BaseShape:
434    """
435        Basic shape functionality
436    """
437    def __init__(self, x=0, y=0, z=0):
438        self.name = ''
439        ## Position
440        self.x = x
441        self.y = y
442        self.z = z
443        ## Orientation
444        self.theta_x = 0
445        self.theta_y = 0
446        self.theta_z = 0
[34f23c8]447
[959eb01]448        # Params
449        self.params = {}
450        self.params['contrast']  = 1.0
451        self.params['order']     = 0
452        self.details = {}
453        self.details['contrast'] = 'A-2'
454        self.details['order']    = ' '
[34f23c8]455
[959eb01]456        self.highlighted = False
457        self.color = DEFAULT_COLOR
[34f23c8]458
[959eb01]459    def get_volume(self):
460        return 0
[34f23c8]461
[959eb01]462    def get_length(self):
463        return 1.0
[34f23c8]464
[959eb01]465    def highlight(self, value=False):
466        self.highlighted = value
[34f23c8]467
[959eb01]468    def rotate(self, alpha, beta, gamma):
[34f23c8]469        """
[959eb01]470            Set the rotation angles of the shape
471            @param alpha: angle around the x-axis [degrees]
472            @param beta: angle around the y-axis [degrees]
473            @param gamma: angle around the z-axis [degrees]
474        """
475        self.theta_x = alpha
476        self.theta_y = beta
477        self.theta_z = gamma
[34f23c8]478
[959eb01]479    def _rotate(self):
480        """
481            Perform the OpenGL rotation
[34f23c8]482
[959eb01]483            Note that the rotation order is reversed.
484            We do Y, X, Z do be compatible with simulation...
485        """
[34f23c8]486
[959eb01]487        glRotated(self.theta_z, 0, 0, 1)
488        glRotated(self.theta_x, 1, 0, 0)
489        glRotated(self.theta_y, 0, 1, 0)
[34f23c8]490
[959eb01]491    def _pre_draw(self):
492        if self.highlighted:
493            glLight(GL_LIGHT0, GL_DIFFUSE, COLOR_HIGHLIGHT)
494        else:
495            glLight(GL_LIGHT0, GL_DIFFUSE, self.color)
496
497
498class Arrow(BaseShape):
499    """
500        Arrow shape used to show the three axes
501    """
502    def __init__(self, x=0, y=0, z=0, r_cyl=0.01, r_cone=0.02, l_cyl=0.3, l_cone=0.1):
503        BaseShape.__init__(self, x, y, z)
504        self.r_cyl = r_cyl
505        self.r_cone = r_cone
506        self.l_cyl = l_cyl
507        self.l_cone = l_cone
[34f23c8]508
[959eb01]509    def draw(self):
510        self._pre_draw()
511        glPushMatrix()
512        glTranslate(self.x, self.y, self.z)
[34f23c8]513
[959eb01]514        # Perform rotation
515        glRotate(self.theta_x, 1, 0, 0)
516        glRotate(self.theta_y, 0, 1, 0)
517        glRotate(self.theta_z, 0, 0, 1)
518
519        # Draw axis cylinder
520        qobj = gluNewQuadric();
521        gluCylinder(qobj, self.r_cyl, self.r_cyl, self.l_cyl, 15, 5);
[34f23c8]522
[959eb01]523        glTranslate(0, 0, self.z+self.l_cyl)
[34f23c8]524
[959eb01]525        # Draw cone of the arrow
526        glutSolidCone(self.r_cone, self.l_cone, 30, 5)
[34f23c8]527
[959eb01]528        # Translate back to original position
529        glTranslate(-self.x, -self.y, -self.z)
530        glPopMatrix()
531
532class Cone(BaseShape):
533    """
534        Conical shape
535    """
536    def __init__(self, x=0, y=0, z=0, radius=0.5, height=1):
537        BaseShape.__init__(self, x, y, z)
538        self.radius = radius
539        self.height = height
[34f23c8]540
[959eb01]541    def draw(self):
542        glPushMatrix()
543        glTranslate(self.x, self.y, self.z)
544        glutSolidCone(self.radius, self.height, 30, 5)
545        self._rotate()
546        glTranslate(-self.x, -self.y, -self.z)
547        glPopMatrix()
548
549class Sphere(BaseShape):
550    """
551        Spherical shape
552    """
553    def __init__(self, x=0, y=0, z=0, radius=10.0):
554        BaseShape.__init__(self, x, y, z)
555        self.name = 'sphere'
556        self.params['radius'] = radius
557        self.details['radius'] = 'A'
[34f23c8]558
[959eb01]559    def get_volume(self):
560        return 4.0/3.0*math.pi*self.params['radius']*self.params['radius']*self.params['radius']
[34f23c8]561
[959eb01]562    def get_length(self):
563        return 2.0*self.params['radius']
[34f23c8]564
[959eb01]565    def draw(self):
566        self._pre_draw()
567        glPushMatrix()
568        glTranslate(self.x, self.y, self.z)
569        #glutSolidSphere(self.params['radius'], 30, 30)
570        qobj = gluNewQuadric();
571        #gluQuadricDrawStyle(qobj,GLU_SILHOUETTE)
572        gluSphere(qobj,self.params['radius'], 30, 30)
573        glTranslate(-self.x, -self.y, -self.z)
574        glPopMatrix()
575        glLight(GL_LIGHT0, GL_DIFFUSE, DEFAULT_COLOR)
576
577    def accept(self, visitor):
578        return visitor.fromSphere(self)
579
580    def accept_update(self, visitor):
581        return visitor.update_sphere(self)
582
583class Cylinder(BaseShape):
584    """
585        Cylinder shape, by default the cylinder is oriented along
[34f23c8]586        the z-axis.
587
[959eb01]588        The reference point of the cylinder is the center of the
589        bottom circle.
590    """
591    def __init__(self, x=0, y=0, z=0, radius=10.0, length=100.0):
592        BaseShape.__init__(self, x, y, z)
593        self.name = 'cylinder'
594        self.params['radius'] = radius
595        self.params['length'] = length
596        self.details['radius'] = 'A'
597        self.details['length'] = 'A'
[34f23c8]598
[959eb01]599    def get_volume(self):
600        return math.pi*self.params['radius']*self.params['radius']*self.params['length']
[34f23c8]601
[959eb01]602    def get_length(self):
603        if self.params['length']>2.0*self.params['radius']:
604            return self.params['length']
605        else:
606            return 2.0*self.params['radius']
[34f23c8]607
[959eb01]608    def draw(self):
609        self._pre_draw()
610        glPushMatrix()
[34f23c8]611
[959eb01]612        glTranslate(self.x, self.y, self.z)
[34f23c8]613        self._rotate()
[959eb01]614        qobj = gluNewQuadric();
615        # gluCylinder(qobj, r_base, r_top, L, div around z, div along z)
616        gluCylinder(qobj, self.params['radius'], self.params['radius'], self.params['length'], 15, 5);
617
618        glTranslate(-self.x, -self.y, -self.z)
619        glPopMatrix()
620        glLight(GL_LIGHT0, GL_DIFFUSE, DEFAULT_COLOR)
[34f23c8]621
[959eb01]622    def accept(self, visitor):
623        return visitor.fromCylinder(self)
[34f23c8]624
[959eb01]625    def accept_update(self, visitor):
626        return visitor.update_cylinder(self)
[34f23c8]627
[959eb01]628# Fill the shape list
629SHAPE_LIST.append(dict(name='Sphere',   id=wx.NewId(), cl=Sphere))
630SHAPE_LIST.append(dict(name='Cylinder', id=wx.NewId(), cl=Cylinder))
[34f23c8]631
[959eb01]632def getShapes():
633    """
634        Returns a list of all available shapes
635    """
636    return SHAPE_LIST
[34f23c8]637
[959eb01]638def getShapeClass(id):
639    """
640        Returns a child class of BaseShape corresponding
641        to the supplied shape ID.
642        @param id: shape ID number
643    """
644    def f(s): return s['id']==id
645    if SHAPE_LIST is not None:
646        shape = filter(f, SHAPE_LIST)
647        return shape[0]['cl']
648    return None
[34f23c8]649
[959eb01]650def getShapeClassByName(name):
651    """
652        Returns a child class of BaseShape corresponding
653        to the supplied shape name.
654        @param name: shape name
655    """
656    def f(s): return s['name']==name
657    if SHAPE_LIST is not None:
658        shape = filter(f, SHAPE_LIST)
659        return shape[0]['cl']
660    return None
Note: See TracBrowser for help on using the repository browser.