[GRASS-SVN] r31723 - grass-addons/visualization/nviz2/wxpython

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Jun 16 12:43:13 EDT 2008


Author: martinl
Date: 2008-06-16 12:43:13 -0400 (Mon, 16 Jun 2008)
New Revision: 31723

Added:
   grass-addons/visualization/nviz2/wxpython/nviz.py
Modified:
   grass-addons/visualization/nviz2/wxpython/mapdisp.py
   grass-addons/visualization/nviz2/wxpython/toolbars.py
Log:
nviz2/wx: initial modifications towards 3D map display

Modified: grass-addons/visualization/nviz2/wxpython/mapdisp.py
===================================================================
--- grass-addons/visualization/nviz2/wxpython/mapdisp.py	2008-06-16 14:30:44 UTC (rev 31722)
+++ grass-addons/visualization/nviz2/wxpython/mapdisp.py	2008-06-16 16:43:13 UTC (rev 31723)
@@ -60,6 +60,7 @@
 import globalvar
 import utils
 import gdialogs
+import nviz
 from vdigit import VDigitCategoryDialog as VDigitCategoryDialog
 from vdigit import VDigitZBulkDialog    as VDigitZBulkDialog
 from vdigit import VDigitDuplicatesDialog as VDigitDuplicatesDialog
@@ -539,9 +540,21 @@
 
     def UpdateMap(self, render=True, renderVector=True):
         """
-        Updates the canvas anytime there is a change to the underlaying images
-        or to the geometry of the canvas.
+        Updates the canvas anytime there is a change to the
+        underlaying images or to the geometry of the canvas.
+        """
+        if self.parent.toolbars['nviz']:
+            self.UpdateMap3D() # OpenGL
+        else:
+            self.UpdateMap2D(render, renderVector)
 
+    def UpdateMap2D(self, render=True, renderVector=True):
+        """
+        Updates the canvas anytime there is a change to the
+        underlaying images or to the geometry of the canvas.
+
+        This method works in 2D mode.
+
         @param render re-render map composition
         @param renderVector re-render vector map layer enabled for editing (used for digitizer)
         """
@@ -661,11 +674,49 @@
         ### self.Map.SetRegion()
         self.parent.StatusbarUpdate()
 
-        Debug.msg (2, "BufferedWindow.UpdateMap(): render=%s, renderVector=%s -> time=%g" % \
+        Debug.msg (2, "BufferedWindow.UpdateMap2D(): render=%s, renderVector=%s -> time=%g" % \
                    (render, renderVector, (stop-start)))
 
         return True
 
+    def UpdateMap3D(self):
+        """
+        Updates the canvas anytime there is a change to the
+        underlaying images or to the geometry of the canvas.
+
+        This method works in 3D mode.
+
+        Instead PseudoDC is used GLCanvas
+        """
+        if not self.parent.toolbars['nviz']:
+            return False
+
+        start = time.clock()
+
+        self.resize = False
+
+        #
+        # clear current canvas first
+        #
+        self.pdc.Clear()
+        self.pdc.RemoveAll()
+        self.pdcTmp.Clear()
+        self.pdcTmp.RemoveAll()
+        self.Draw(self.pdc, pdctype='clear')
+
+        stop = time.clock()
+
+        #
+        # update statusbar
+        #
+        ### self.Map.SetRegion()
+        self.parent.StatusbarUpdate()
+
+        Debug.msg (2, "BufferedWindow.UpdateMap3D(): time=%g" % \
+                   (stop-start))
+
+        return True
+
     def DrawCompRegionExtent(self):
         """Draw computational region extent in the display
         
@@ -2308,7 +2359,8 @@
         #
         self.toolbars = { 'map' : None,
                           'vdigit' : None,
-                          'georect' : None }
+                          'georect' : None, 
+                          'nviz' : None }
         for toolb in toolbars:
             self.AddToolbar(toolb)
 
@@ -2371,6 +2423,7 @@
         self.MapWindow = BufferedWindow(self, id=wx.ID_ANY, Map=self.Map, tree=self.tree, gismgr=self.gismanager)
         self.MapWindow.Bind(wx.EVT_MOTION, self.OnMotion)
         self.MapWindow.SetCursor(self.cursors["default"])
+        self.MapWindowGL = None # used by Nviz (default is 2D display mode)
 
         #
         # initialize region values
@@ -2434,7 +2487,8 @@
          - map basic map toolbar
          - digit vector digitizer
          - georect georectifier
-         """
+        """
+        # default toolbar
         if name == "map":
             self.toolbars['map'] = toolbars.MapToolbar(self, self.Map)
 
@@ -2445,8 +2499,8 @@
                               LeftDockable(False).RightDockable(False).
                               BottomDockable(False).TopDockable(True).
                               CloseButton(False).Layer(2))
-
-        if name == "digit":
+        # vector digitizer
+        elif name == "vdigit":
             self.toolbars['vdigit'] = toolbars.VDigitToolbar(self, self.Map, self.tree)
 
             for toolRow in range(0, self.toolbars['vdigit'].numOfRows):
@@ -2463,18 +2517,58 @@
             self.MapWindow.zoomtype = 0
             self.MapWindow.pen     = wx.Pen(colour='red',   width=2, style=wx.SOLID)
             self.MapWindow.polypen = wx.Pen(colour='green', width=2, style=wx.SOLID)
-
-        if name == "georect":
+        # georectifier
+        elif name == "georect":
             self.toolbars['georect'] = toolbars.GRToolbar(self, self.Map)
 
             self._mgr.AddPane(self.toolbars['georect'].toolbar,
                               wx.aui.AuiPaneInfo().
-                              Name("georecttoolbar").Caption(_("Georectification Toolbar")).
+                              Name("georecttoolbar").Caption(_("Georectification toolbar")).
                               ToolbarPane().Top().
                               LeftDockable(False).RightDockable(False).
                               BottomDockable(False).TopDockable(True).
                               CloseButton(False).Layer(2))
+        # nviz
+        elif name == "nviz":
+            # check for GLCanvas and OpenGL
+            msg = None
+            if not nviz.haveGLCanvas:
+                msg = _("Unable to start Nviz. The GLCanvas class has not been included with this build "
+                        "of wxPython! Switching back to 2D display mode.")
+            if not nviz.haveOpenGL:
+                msg = _("Unable to start Nviz. The OpenGL package was not found. You can get it "
+                        "at http://PyOpenGL.sourceforge.net. Switching back to 2D display mode.")
 
+            if msg:
+                wx.MessageBox(parent=self,
+                              message=msg,
+                              caption=_("Error"))
+                return
+
+            #
+            # create GL window & NVIZ toolbar
+            #
+            self.MapWindowGL = nviz.GLWindow(self)
+            self.toolbars['nviz'] = toolbars.NvizToolbar(self, self.Map)
+
+            #
+            # switch from MapWindow to MapWindowGL
+            # add nviz toolbar
+            #
+            self._mgr.DetachPane(self.MapWindow)
+            self.MapWindow.Hide()
+            self._mgr.AddPane(self.MapWindowGL, wx.aui.AuiPaneInfo().CentrePane().
+                              Dockable(False).BestSize((-1,-1)).
+                              CloseButton(False).DestroyOnClose(True).
+                              Layer(0))
+            self._mgr.AddPane(self.toolbars['nviz'].toolbar,
+                              wx.aui.AuiPaneInfo().
+                              Name("nviztoolbar").Caption(_("Nviz toolbar")).
+                              ToolbarPane().Top().Row(1).
+                              LeftDockable(False).RightDockable(False).
+                              BottomDockable(False).TopDockable(True).
+                              CloseButton(False).Layer(2))
+            
         self._mgr.Update()
 
     def RemoveToolbar (self, name):
@@ -2487,14 +2581,29 @@
         # cannot hide main toolbar
         if name == "map":
             return
-        elif name == "digit":
+        elif name == "vdigit":
             # TODO: not destroy only hide
             for toolRow in range(0, self.toolbars['vdigit'].numOfRows):
                 self._mgr.DetachPane (self.toolbars['vdigit'].toolbar[toolRow])
                 self.toolbars['vdigit'].toolbar[toolRow].Destroy()
-            self.toolbars['vdigit'] = None
+        else:
+            self._mgr.DetachPane (self.toolbars[name].toolbar)
+            self.toolbars[name].toolbar.Destroy()
 
-        self.toolbars['map'].combo.SetValue ("Tools");
+        self.toolbars[name] = None
+
+        if name == 'nviz':
+            # switch from MapWindowGL to MapWindow
+            self._mgr.DetachPane(self.MapWindowGL)
+            self.MapWindowGL.Hide()
+            self.MapWindow.Show()
+            self._mgr.AddPane(self.MapWindow, wx.aui.AuiPaneInfo().CentrePane().
+                              Dockable(False).BestSize((-1,-1)).
+                              CloseButton(False).DestroyOnClose(True).
+                              Layer(0))
+        
+        self.toolbars['map'].combo.SetValue ("Tools")
+
         self._mgr.Update()
 
     def __InitDisplay(self):

Added: grass-addons/visualization/nviz2/wxpython/nviz.py
===================================================================
--- grass-addons/visualization/nviz2/wxpython/nviz.py	                        (rev 0)
+++ grass-addons/visualization/nviz2/wxpython/nviz.py	2008-06-16 16:43:13 UTC (rev 31723)
@@ -0,0 +1,140 @@
+"""
+ at package nviz.py
+
+ at brief 2.5/3D visialization mode for Map Display Window
+
+List of classes:
+ - GLCanvas
+
+(C) 2008 by the GRASS Development Team
+
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import wx
+try:
+    from wx import glcanvas
+    haveGLCanvas = True
+except ImportError:
+    haveGLCanvas = False
+
+try:
+    from OpenGL.GL import *
+    from OpenGL.GLUT import *
+    haveOpenGL = True
+except ImportError:
+    haveOpenGL = False
+
+class GLWindow(glcanvas.GLCanvas):
+    """OpenGL canvas for Map Display Window"""
+    def __init__(self, parent):
+        self.parent = parent # MapWindow
+        glcanvas.GLCanvas.__init__(self, parent, wx.ID_ANY)
+        self.init = False
+
+        # initialize mouse position
+        self.lastx = self.x = 30
+        self.lasty = self.y = 30
+
+        self.size = None
+        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        #        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+        #        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+        #        self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
+
+    def OnEraseBackground(self, event):
+        pass # do nothing, to avoid flashing on MSW
+
+    def OnSize(self, event):
+        size = self.size = self.parent.GetClientSize()
+        if self.GetContext():
+            self.SetCurrent()
+            glViewport(0, 0, size.width, size.height)
+        
+        event.Skip()
+
+    def OnPaint(self, event):
+        dc = wx.PaintDC(self)
+        self.SetCurrent()
+        if not self.init:
+            self.InitGL()
+            self.init = True
+        self.OnDraw()
+
+    def InitGL(self):
+        # set viewing projection
+        glMatrixMode(GL_PROJECTION)
+        glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0)
+
+        # position viewer
+        glMatrixMode(GL_MODELVIEW)
+        glTranslatef(0.0, 0.0, -2.0)
+
+        # position object
+        glRotatef(self.y, 1.0, 0.0, 0.0)
+        glRotatef(self.x, 0.0, 1.0, 0.0)
+
+        glEnable(GL_DEPTH_TEST)
+        glEnable(GL_LIGHTING)
+        glEnable(GL_LIGHT0)
+
+    def OnDraw(self):
+        # clear color and depth buffers
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+        # draw six faces of a cube
+        glBegin(GL_QUADS)
+        glNormal3f( 0.0, 0.0, 1.0)
+        glVertex3f( 0.5, 0.5, 0.5)
+        glVertex3f(-0.5, 0.5, 0.5)
+        glVertex3f(-0.5,-0.5, 0.5)
+        glVertex3f( 0.5,-0.5, 0.5)
+
+        glNormal3f( 0.0, 0.0,-1.0)
+        glVertex3f(-0.5,-0.5,-0.5)
+        glVertex3f(-0.5, 0.5,-0.5)
+        glVertex3f( 0.5, 0.5,-0.5)
+        glVertex3f( 0.5,-0.5,-0.5)
+
+        glNormal3f( 0.0, 1.0, 0.0)
+        glVertex3f( 0.5, 0.5, 0.5)
+        glVertex3f( 0.5, 0.5,-0.5)
+        glVertex3f(-0.5, 0.5,-0.5)
+        glVertex3f(-0.5, 0.5, 0.5)
+
+        glNormal3f( 0.0,-1.0, 0.0)
+        glVertex3f(-0.5,-0.5,-0.5)
+        glVertex3f( 0.5,-0.5,-0.5)
+        glVertex3f( 0.5,-0.5, 0.5)
+        glVertex3f(-0.5,-0.5, 0.5)
+
+        glNormal3f( 1.0, 0.0, 0.0)
+        glVertex3f( 0.5, 0.5, 0.5)
+        glVertex3f( 0.5,-0.5, 0.5)
+        glVertex3f( 0.5,-0.5,-0.5)
+        glVertex3f( 0.5, 0.5,-0.5)
+
+        glNormal3f(-1.0, 0.0, 0.0)
+        glVertex3f(-0.5,-0.5,-0.5)
+        glVertex3f(-0.5,-0.5, 0.5)
+        glVertex3f(-0.5, 0.5, 0.5)
+        glVertex3f(-0.5, 0.5,-0.5)
+        glEnd()
+
+        if self.size is None:
+            self.size = self.GetClientSize()
+        w, h = self.size
+        w = max(w, 1.0)
+        h = max(h, 1.0)
+        xScale = 180.0 / w
+        yScale = 180.0 / h
+        glRotatef((self.y - self.lasty) * yScale, 1.0, 0.0, 0.0);
+        glRotatef((self.x - self.lastx) * xScale, 0.0, 1.0, 0.0);
+
+        self.SwapBuffers()

Modified: grass-addons/visualization/nviz2/wxpython/toolbars.py
===================================================================
--- grass-addons/visualization/nviz2/wxpython/toolbars.py	2008-06-16 14:30:44 UTC (rev 31722)
+++ grass-addons/visualization/nviz2/wxpython/toolbars.py	2008-06-16 16:43:13 UTC (rev 31723)
@@ -8,7 +8,8 @@
     * GCPToolbar
     * VDigitToolbar
     * ProfileToolbar
-    
+    * NvizToolbar
+
 PURPOSE: Toolbars for Map Display window
 
 AUTHORS: The GRASS Development Team
@@ -111,10 +112,10 @@
         
         # optional tools
         self.combo = wx.ComboBox(parent=self.toolbar, id=wx.ID_ANY, value='Tools',
-                                 choices=['Digitize'], style=wx.CB_READONLY, size=(90, -1))
+                                 choices=['Digitize', 'Nviz'], style=wx.CB_READONLY, size=(90, -1))
 
         self.comboid = self.toolbar.AddControl(self.combo)
-        self.mapdisplay.Bind(wx.EVT_COMBOBOX, self.OnSelect, self.comboid)
+        self.mapdisplay.Bind(wx.EVT_COMBOBOX, self.OnSelectTool, self.comboid)
 
         # realize the toolbar
         self.toolbar.Realize()
@@ -188,15 +189,18 @@
             ("", "", "", "", "", "", "")
             )
 
-    def OnSelect(self, event):
+    def OnSelectTool(self, event):
         """
         Select / enable tool available in tools list
         """
         tool =  event.GetString()
 
         if tool == "Digitize" and not self.mapdisplay.toolbars['vdigit']:
-            self.mapdisplay.AddToolbar("digit")
+            self.mapdisplay.AddToolbar("vdigit")
 
+        elif tool == "Nviz" and not self.mapdisplay.toolbars['nviz']:
+            self.mapdisplay.AddToolbar("nviz")
+
 class GRToolbar(AbstractToolbar):
     """
     Georectify Display toolbar
@@ -525,7 +529,7 @@
             self.parent.dialogs['attributes'].OnCancel(None)
 
         # disable the toolbar
-        self.parent.RemoveToolbar ("digit")
+        self.parent.RemoveToolbar ("vdigit")
 
     def OnMoveVertex(self, event):
         """Move line vertex"""
@@ -987,3 +991,40 @@
              wx.ITEM_NORMAL, Icons["quit"].GetLabel(), Icons["quit"].GetDesc(),
              self.parent.OnQuit),
             )
+
+class NvizToolbar(AbstractToolbar):
+    """
+    Nviz toolbar
+    """
+    def __init__(self, parent, map):
+        self.parent     = parent
+        self.mapcontent = map
+
+        self.toolbar = wx.ToolBar(parent=self.parent, id=wx.ID_ANY)
+
+        # self.SetToolBar(self.toolbar)
+        self.toolbar.SetToolBitmapSize(globalvar.toolbarSize)
+
+        self.InitToolbar(self.parent, self.toolbar, self.ToolbarData())
+
+        # realize the toolbar
+        self.toolbar.Realize()
+
+    def ToolbarData(self):
+        """Toolbar data"""
+
+        self.quit = wx.NewId()
+                
+        # tool, label, bitmap, kind, shortHelp, longHelp, handler
+        return   (
+            (self.quit, 'quit', Icons["quit"].GetBitmap(),
+             wx.ITEM_NORMAL, Icons["quit"].GetLabel(), Icons["quit"].GetDesc(),
+             self.OnExit),
+            )
+
+    def OnExit (self, event=None):
+        """Quit nviz tool (swith to 2D mode)"""
+
+        # disable the toolbar
+        self.parent.RemoveToolbar ("nviz")
+



More information about the grass-commit mailing list