GRASS Programmer's Manual  6.4.2(2012)
nviz_mapdisp.py
Go to the documentation of this file.
00001 """
00002 @package nviz_mapdisp.py
00003 
00004 @brief Nviz extension for wxGUI
00005 
00006 This module implements 3D visualization mode of map display.
00007 
00008 List of classes:
00009  - GLWindow
00010 
00011 (C) 2008-2009 by the GRASS Development Team
00012 
00013 This program is free software under the GNU General Public
00014 License (>=v2). Read the file COPYING that comes with GRASS
00015 for details.
00016 
00017 @author Martin Landa <landa.martin gmail.com> (Google SoC 2008)
00018 """
00019 
00020 import os
00021 import sys
00022 import time
00023 import copy
00024 import math
00025 
00026 from threading import Thread
00027 
00028 import wx
00029 import wx.lib.scrolledpanel as scrolled
00030 from wx.lib.newevent import NewEvent
00031 from wx import glcanvas
00032 
00033 import gcmd
00034 import globalvar
00035 from debug          import Debug
00036 from mapdisp_window import MapWindow
00037 from goutput        import wxCmdOutput
00038 from preferences    import globalSettings as UserSettings
00039 from workspace      import Nviz as NvizDefault
00040 
00041 try:
00042     import wxnviz
00043 except (ImportError, NameError):
00044     pass
00045 
00046 wxUpdateProperties, EVT_UPDATE_PROP  = NewEvent()
00047 wxUpdateView,       EVT_UPDATE_VIEW  = NewEvent()
00048 wxUpdateLight,      EVT_UPDATE_LIGHT = NewEvent()
00049 
00050 class NvizThread(Thread):
00051     def __init__(self, log, progressbar, window):
00052         Thread.__init__(self)
00053         
00054         self.log = log
00055         self.progressbar = progressbar
00056         self.window = window
00057         
00058         self._display = None
00059         
00060         self.setDaemon(True)
00061 
00062     def run(self):
00063         self._display = wxnviz.Nviz(self.log, self.progressbar)
00064         
00065     def GetDisplay(self):
00066         """!Get display instance"""
00067         return self._display
00068     
00069 class GLWindow(MapWindow, glcanvas.GLCanvas):
00070     """!OpenGL canvas for Map Display Window"""
00071     def __init__(self, parent, id = wx.ID_ANY,
00072                  Map = None, tree = None, lmgr = None):
00073         self.parent = parent # MapFrame
00074         
00075         glcanvas.GLCanvas.__init__(self, parent, id)
00076         MapWindow.__init__(self, parent, id, 
00077                            Map, tree, lmgr)
00078         self.Hide()
00079         
00080         self.init = False
00081         self.initView = False
00082         
00083         # render mode 
00084         self.render = { 'quick' : False,
00085                         # do not render vector lines in quick mode
00086                         'vlines' : False,
00087                         'vpoints' : False }
00088         
00089         # list of loaded map layers (layer tree items)
00090         self.layers  = list()
00091         # list of query points
00092         self.qpoints = list()
00093         
00094         #
00095         # use display region instead of computational
00096         #
00097         os.environ['GRASS_REGION'] = self.Map.SetRegion()
00098         
00099         #
00100         # create nviz instance
00101         #
00102         if self.lmgr:
00103             self.log = self.lmgr.goutput
00104             logerr = self.lmgr.goutput.GetLog(err = True)
00105             logmsg = self.lmgr.goutput.GetLog()
00106         else:
00107             self.log = logmsg = sys.stdout
00108             logerr = sys.stderr
00109         
00110         self.nvizThread = NvizThread(logerr,
00111                                      self.parent.statusbarWin['progress'],
00112                                      logmsg)
00113         self.nvizThread.start()
00114         time.sleep(.1)
00115         self._display = self.nvizThread.GetDisplay()
00116         
00117         # GRASS_REGION needed only for initialization
00118         del os.environ['GRASS_REGION']
00119         
00120         self.img = wx.Image(self.Map.mapfile, wx.BITMAP_TYPE_ANY)
00121         
00122         # size of MapWindow, to avoid resizing if size is the same
00123         self.size = (0,0)
00124         
00125         #
00126         # default values
00127         #
00128         self.view = copy.deepcopy(UserSettings.Get(group = 'nviz', key = 'view')) # copy
00129         self.iview = UserSettings.Get(group = 'nviz', key = 'view', internal = True)
00130         
00131         self.nvizDefault = NvizDefault()
00132         self.light = copy.deepcopy(UserSettings.Get(group = 'nviz', key = 'light')) # copy
00133         
00134         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
00135         self.Bind(wx.EVT_SIZE,             self.OnSize)
00136         self.Bind(wx.EVT_PAINT,            self.OnPaint)
00137         self.Bind(wx.EVT_LEFT_UP,          self.OnLeftUp)
00138         self.Bind(wx.EVT_MOUSE_EVENTS,     self.OnMouseAction)
00139         self.Bind(wx.EVT_MOTION,           self.OnMotion)
00140         
00141         self.Bind(EVT_UPDATE_PROP,  self.UpdateMapObjProperties)
00142         self.Bind(EVT_UPDATE_VIEW,  self.UpdateView)
00143         self.Bind(EVT_UPDATE_LIGHT, self.UpdateLight)
00144         
00145         self.Bind(wx.EVT_CLOSE, self.OnClose)
00146         
00147     def OnClose(self, event):
00148         # cleanup when window actually closes (on quit) and not just is hidden
00149         self.Reset()
00150         
00151     def OnEraseBackground(self, event):
00152         pass # do nothing, to avoid flashing on MSW
00153     
00154     def OnSize(self, event):
00155         size = self.GetClientSize()
00156         if self.size != size \
00157             and self.GetContext():
00158             Debug.msg(3, "GLCanvas.OnSize(): w = %d, h = %d" % \
00159                       (size.width, size.height))
00160             self.SetCurrent()
00161             self._display.ResizeWindow(size.width,
00162                                        size.height)
00163         self.size = size
00164         event.Skip()
00165         
00166     def OnPaint(self, event):
00167         Debug.msg(1, "GLCanvas.OnPaint()")
00168         
00169         dc = wx.PaintDC(self)
00170         self.SetCurrent()
00171         
00172         if not self.initView:
00173             self._display.InitView()
00174             self.initView = True
00175         
00176         self.LoadDataLayers()
00177         self.UnloadDataLayers()
00178         
00179         if not self.init:
00180             self.ResetView()
00181             
00182             if hasattr(self.lmgr, "nviz"):
00183                 self.lmgr.nviz.UpdatePage('view')
00184                 self.lmgr.nviz.UpdatePage('light')
00185                 layer = self.GetSelectedLayer()
00186                 if layer:
00187                     if layer.type ==  'raster':
00188                         self.lmgr.nviz.UpdatePage('surface')
00189                         self.lmgr.nviz.UpdatePage('fringe')
00190                     elif layer.type ==  'vector':
00191                         self.lmgr.nviz.UpdatePage('vector')
00192                 
00193                 ### self.lmgr.nviz.UpdateSettings()
00194                 
00195                 # update widgets
00196                 win = self.lmgr.nviz.FindWindowById( \
00197                     self.lmgr.nviz.win['vector']['lines']['surface'])
00198                 win.SetItems(self.GetLayerNames('raster'))
00199             
00200             self.init = True
00201         
00202         self.UpdateMap()
00203                 
00204     def OnMouseAction(self, event):
00205         # change perspective with mouse wheel
00206         wheel = event.GetWheelRotation()
00207         
00208         if wheel !=  0:
00209             current  = event.GetPositionTuple()[:]
00210             Debug.msg (5, "GLWindow.OnMouseMotion(): wheel = %d" % wheel)
00211             prev_value = self.view['persp']['value']
00212             if wheel > 0:
00213                 value = -1 * self.view['persp']['step']
00214             else:
00215                 value = self.view['persp']['step']
00216             self.view['persp']['value'] +=  value
00217             if self.view['persp']['value'] < 1:
00218                 self.view['persp']['value'] = 1
00219             elif self.view['persp']['value'] > 100:
00220                 self.view['persp']['value'] = 100
00221             
00222             if prev_value !=  self.view['persp']['value']:
00223                 if hasattr(self.lmgr, "nviz"):
00224                     self.lmgr.nviz.UpdateSettings()
00225                     
00226                     self._display.SetView(self.view['position']['x'], self.view['position']['y'],
00227                                           self.iview['height']['value'],
00228                                           self.view['persp']['value'],
00229                                           self.view['twist']['value'])
00230                 
00231                 # redraw map
00232                 self.OnPaint(None)
00233                 
00234                 # update statusbar
00235                 ### self.parent.StatusbarUpdate()
00236         
00237         event.Skip()
00238 
00239     def Pixel2Cell(self, (x, y)):
00240         """!Convert image coordinates to real word coordinates
00241 
00242         @param x, y image coordinates
00243         
00244         @return easting, northing
00245         @return None on error
00246         """
00247         size = self.GetClientSize()
00248         # UL -> LL
00249         sid, x, y, z = self._display.GetPointOnSurface(x, y)
00250         
00251         if not sid:
00252             return None
00253         
00254         return (x, y)
00255     
00256     def OnLeftUp(self, event):
00257         self.ReleaseMouse()
00258         if self.mouse["use"] == "nvizQuerySurface":
00259             self.OnQuerySurface(event)
00260         elif self.mouse["use"] == "nvizQueryVector":
00261             self.OnQueryVector(event)
00262     
00263     def OnQuerySurface(self, event):
00264         """!Query surface on given position"""
00265         result = self._display.QueryMap(event.GetX(), event.GetY())
00266         if result:
00267             self.qpoints.append((result['x'], result['y'], result['z']))
00268             self.log.WriteLog("%-30s: %.3f" % (_("Easting"),   result['x']))
00269             self.log.WriteLog("%-30s: %.3f" % (_("Northing"),  result['y']))
00270             self.log.WriteLog("%-30s: %.3f" % (_("Elevation"), result['z']))
00271             self.log.WriteLog("%-30s: %s" % (_("Surface map elevation"), result['elevation']))
00272             self.log.WriteLog("%-30s: %s" % (_("Surface map color"), result['color']))
00273             if len(self.qpoints) > 1:
00274                 prev = self.qpoints[-2]
00275                 curr = self.qpoints[-1]
00276                 dxy = math.sqrt(pow(prev[0]-curr[0], 2) +
00277                                 pow(prev[1]-curr[1], 2))
00278                 dxyz = math.sqrt(pow(prev[0]-curr[0], 2) +
00279                                  pow(prev[1]-curr[1], 2) +
00280                                  pow(prev[2]-curr[2], 2))
00281                 self.log.WriteLog("%-30s: %.3f" % (_("XY distance from previous"), dxy))
00282                 self.log.WriteLog("%-30s: %.3f" % (_("XYZ distance from previous"), dxyz))
00283                 self.log.WriteLog("%-30s: %.3f" % (_("Distance along surface"),
00284                                               self._display.GetDistanceAlongSurface(result['id'],
00285                                                                                     (curr[0], curr[1]),
00286                                                                                     (prev[0], prev[1]),
00287                                                                                     useExag = False)))
00288                 self.log.WriteLog("%-30s: %.3f" % (_("Distance along exag. surface"),
00289                                               self._display.GetDistanceAlongSurface(result['id'],
00290                                                                                     (curr[0], curr[1]),
00291                                                                                     (prev[0], prev[1]),
00292                                                                                       useExag = True)))
00293             self.log.WriteCmdLog('-' * 80)
00294         else:
00295             self.log.WriteLog(_("No point on surface"))
00296             self.log.WriteCmdLog('-' * 80)
00297     
00298     def OnQueryVector(self, event):
00299         """!Query vector on given position"""
00300         self.log.WriteWarning(_("Function not implemented yet"))
00301         self.log.WriteCmdLog('-' * 80)
00302         
00303     def UpdateView(self, event):
00304         """!Change view settings"""
00305         data = self.view
00306         self._display.SetView(data['position']['x'], data['position']['y'],
00307                               self.iview['height']['value'],
00308                               data['persp']['value'],
00309                               data['twist']['value'])
00310         
00311         if event and event.zExag and 'value' in data['z-exag']:
00312             self._display.SetZExag(data['z-exag']['value'])
00313         
00314         if event:
00315             event.Skip()
00316 
00317     def UpdateLight(self, event):
00318         """!Change light settings"""
00319         data = self.light
00320         self._display.SetLight(x = data['position']['x'], y = data['position']['y'],
00321                                z = data['position']['z'] / 100., color = data['color'],
00322                                bright = data['bright'] / 100.,
00323                                ambient = data['ambient'] / 100.)
00324         self._display.DrawLightingModel()
00325         
00326     def UpdateMap(self, render = True):
00327         """!Updates the canvas anytime there is a change to the
00328         underlaying images or to the geometry of the canvas.
00329         
00330         @param render re-render map composition
00331         """
00332         start = time.clock()
00333         
00334         self.resize = False
00335         
00336         if self.render['quick'] is False:
00337             self.parent.statusbarWin['progress'].Show()
00338             self.parent.statusbarWin['progress'].SetRange(2)
00339             self.parent.statusbarWin['progress'].SetValue(0)
00340         
00341         if self.render['quick'] is False:
00342             self.parent.statusbarWin['progress'].SetValue(1)
00343             self._display.Draw(False, -1)
00344         elif self.render['quick'] is True:
00345             # quick
00346             mode = wxnviz.DRAW_QUICK_SURFACE | wxnviz.DRAW_QUICK_VOLUME
00347             if self.render['vlines']:
00348                 mode |=  wxnviz.DRAW_QUICK_VLINES
00349             if self.render['vpoints']:
00350                 mode |=  wxnviz.DRAW_QUICK_VPOINTS
00351             self._display.Draw(True, mode)
00352         else: # None -> reuse last rendered image
00353             pass # TODO
00354         
00355         self.SwapBuffers()
00356         
00357         stop = time.clock()
00358         
00359         if self.render['quick'] is False:
00360             self.parent.statusbarWin['progress'].SetValue(2)
00361             # hide process bar
00362             self.parent.statusbarWin['progress'].Hide()
00363         
00364         Debug.msg(3, "GLWindow.UpdateMap(): quick = %d, -> time = %g" % \
00365                       (self.render['quick'], (stop-start)))
00366         
00367     def EraseMap(self):
00368         """!Erase the canvas
00369         """
00370         self._display.EraseMap()
00371         self.SwapBuffers()
00372         
00373     def IsLoaded(self, item):
00374         """!Check if layer (item) is already loaded
00375         
00376         @param item layer item
00377         """
00378         layer = self.tree.GetPyData(item)[0]['maplayer']
00379         data = self.tree.GetPyData(item)[0]['nviz']
00380         
00381         if not data:
00382             return 0
00383         
00384         if layer.type ==  'raster':
00385             if 'object' not in data['surface']:
00386                 return 0
00387         elif layer.type ==  'vector':
00388             if 'object' not in data['vlines'] and \
00389                     'object' not in data['points']:
00390                 return 0
00391         
00392         return 1
00393 
00394     def _GetDataLayers(self, item, litems):
00395         """!Return get list of enabled map layers"""
00396         # load raster & vector maps
00397         while item and item.IsOk():
00398             type = self.tree.GetPyData(item)[0]['type']
00399             if type ==  'group':
00400                 subItem = self.tree.GetFirstChild(item)[0]
00401                 self._GetDataLayers(subItem, litems)
00402                 item = self.tree.GetNextSibling(item)
00403                 
00404             if not item.IsChecked() or \
00405                     type not in ('raster', 'vector', '3d-raster'):
00406                 item = self.tree.GetNextSibling(item)
00407                 continue
00408             
00409             litems.append(item)
00410             
00411             item = self.tree.GetNextSibling(item)
00412         
00413     def LoadDataLayers(self):
00414         """!Load raster/vector from current layer tree
00415         
00416         @todo volumes
00417         """
00418         if not self.tree:
00419             return
00420         
00421         listOfItems = []
00422         item = self.tree.GetFirstChild(self.tree.root)[0]
00423         self._GetDataLayers(item, listOfItems)
00424         
00425         start = time.time()
00426         
00427         while(len(listOfItems) > 0):
00428             item = listOfItems.pop()
00429             type = self.tree.GetPyData(item)[0]['type']
00430             if item in self.layers:
00431                 continue
00432             try:
00433                 if type ==  'raster':
00434                     self.LoadRaster(item)
00435                 elif type ==  '3d-raster':
00436                     self.LoadRaster3d(item)
00437                 elif type ==  'vector':
00438                     # data = self.tree.GetPyData(item)[0]['nviz']
00439                     # vecType = []
00440                     # if data and 'vector' in data:
00441                     #     for v in ('lines', 'points'):
00442                     #         if data['vector'][v]:
00443                     #             vecType.append(v)
00444                     layer = self.tree.GetPyData(item)[0]['maplayer']
00445                     npoints, nlines, nfeatures, mapIs3D = self.lmgr.nviz.VectorInfo(layer)
00446                     if npoints > 0:
00447                         self.LoadVector(item, points = True)
00448                     if nlines > 0:
00449                         self.LoadVector(item, points = False)
00450             except gcmd.GException, e:
00451                 GError(parent = self,
00452                        message = e.value)
00453             self.init = False
00454         
00455         stop = time.time()
00456         
00457         Debug.msg(3, "GLWindow.LoadDataLayers(): time = %f" % (stop-start))
00458                 
00459     def UnloadDataLayers(self):
00460         """!Unload any layers that have been deleted from layer tree"""
00461         if not self.tree:
00462             return
00463         
00464         listOfItems = []
00465         item = self.tree.GetFirstChild(self.tree.root)[0]
00466         self._GetDataLayers(item, listOfItems)
00467         
00468         start = time.time()
00469         
00470         for layer in self.layers:
00471             if layer not in listOfItems:
00472                 ltype = self.tree.GetPyData(layer)[0]['type']
00473                 try:
00474                     if ltype ==  'raster':
00475                         self.UnloadRaster(layer)
00476                     elif ltype ==  '3d-raster':
00477                         self.UnloadRaster3d(layer) 
00478                     elif ltype ==  'vector':
00479                         self.UnloadVector(layer, True)
00480                         self.UnloadVector(layer, False)
00481                     
00482                     self.UpdateView(None)
00483                 except gcmd.GException, e:
00484                     gcmd.GError(parent = self,
00485                                 message = e.value)
00486                 
00487                 self.lmgr.nviz.UpdateSettings()        
00488         
00489         stop = time.time()
00490         
00491         Debug.msg(3, "GLWindow.UnloadDataLayers(): time = %f" % (stop-start))        
00492 
00493     def SetVectorFromCmd(self, item, data):
00494         """!Set 3D view properties from cmd (d.vect)
00495 
00496         @param item Layer Tree item
00497         @param nviz data
00498         """
00499         cmd = self.tree.GetPyData(item)[0]['cmd']
00500         if cmd[0] != 'd.vect':
00501             return
00502         for opt in cmd[1:]:
00503             try:
00504                 key, value = opt.split('=')
00505             except ValueError:
00506                 continue
00507             if key == 'color':
00508                 data['lines']['color']['value'] = value
00509                 data['points']['color']['value'] = value
00510 
00511     def SetMapObjProperties(self, item, id, nvizType):
00512         """!Set map object properties
00513         
00514         Properties must be afterwards updated by
00515         UpdateMapObjProperties().
00516         
00517         @param item layer item
00518         @param id nviz layer id (or -1)
00519         @param nvizType nviz data type (surface, points, vector)
00520         """
00521         type = self.tree.GetPyData(item)[0]['maplayer'].type
00522         # reference to original layer properties (can be None)
00523         data = self.tree.GetPyData(item)[0]['nviz']
00524         
00525         if not data:
00526             # init data structure
00527             self.tree.GetPyData(item)[0]['nviz'] = {}
00528             data = self.tree.GetPyData(item)[0]['nviz']
00529             
00530             if type ==  'raster':
00531                 # reset to default properties
00532                 data[nvizType] = self.nvizDefault.SetSurfaceDefaultProp()
00533                         
00534             elif type ==  'vector':
00535                 # reset to default properties (lines/points)
00536                 data['vector'] = self.nvizDefault.SetVectorDefaultProp()
00537                 self.SetVectorFromCmd(item, data['vector'])
00538                 
00539             elif type ==  '3d-raster':
00540                 # reset to default properties 
00541                 data[nvizType] = self.nvizDefault.SetVolumeDefaultProp()
00542         
00543         else:
00544             # complete data (use default values)
00545             if type ==  'raster':
00546                 data['surface'] = self.nvizDefault.SetSurfaceDefaultProp()
00547             if type ==  'vector':
00548                 if not data['vector']['lines']:
00549                     self.nvizDefault.SetVectorLinesDefaultProp(data['vector']['lines'])
00550                 if not data['vector']['points']:
00551                     self.nvizDefault.SetVectorPointsDefaultProp(data['vector']['points'])
00552                     
00553             # set updates
00554             for sec in data.keys():
00555                 for sec1 in data[sec].keys():
00556                     for sec2 in data[sec][sec1].keys():
00557                         if sec2 !=  'all':
00558                             data[sec][sec1][sec2]['update'] = None
00559             
00560             event = wxUpdateProperties(data = data)
00561             wx.PostEvent(self, event)
00562         
00563         # set id
00564         if id > 0:
00565             if type in ('raster', '3d-raster'):
00566                data[nvizType]['object'] = { 'id' : id,
00567                                             'init' : False }
00568             elif type ==  'vector':
00569                 data['vector'][nvizType]['object'] = { 'id' : id,
00570                                                        'init' : False }
00571         
00572         return data
00573 
00574     def LoadRaster(self, item):
00575         """!Load 2d raster map and set surface attributes
00576         
00577         @param layer item
00578         """
00579         return self._loadRaster(item)
00580     
00581     def LoadRaster3d(self, item):
00582         """!Load 3d raster map and set surface attributes
00583         
00584         @param layer item
00585         """
00586         return self._loadRaster(item)
00587     
00588     def _loadRaster(self, item):
00589         """!Load 2d/3d raster map and set its attributes
00590         
00591         @param layer item
00592         """
00593         layer = self.tree.GetPyData(item)[0]['maplayer']
00594         
00595         if layer.type not in ('raster', '3d-raster'):
00596             return
00597         
00598         if layer.type ==  'raster':
00599             id = self._display.LoadSurface(str(layer.name), None, None)
00600             nvizType = 'surface'
00601             errorMsg = _("Loading raster map")
00602         elif layer.type ==  '3d-raster':
00603             id = self._display.LoadVolume(str(layer.name), None, None)
00604             nvizType = 'volume'
00605             errorMsg = _("Loading 3d raster map")
00606         else:
00607             id = -1
00608         
00609         if id < 0:
00610             if layer.type in ('raster', '3d-raster'):
00611                 self.log.WriteError("%s <%s> %s" % (errorMsg, layer.name, _("failed")))
00612             else:
00613                 self.log.WriteError(_("Unsupported layer type '%s'") % layer.type)
00614         
00615         self.layers.append(item)
00616         
00617         # set default/workspace layer properties
00618         data = self.SetMapObjProperties(item, id, nvizType)
00619         
00620         # update properties
00621         event = wxUpdateProperties(data = data)
00622         wx.PostEvent(self, event)
00623         
00624         # update tools window
00625         if hasattr(self.lmgr, "nviz") and \
00626                 item ==  self.GetSelectedLayer(type = 'item'):
00627             toolWin = self.lmgr.nviz
00628             if layer.type ==  'raster':
00629                 win = toolWin.FindWindowById( \
00630                     toolWin.win['vector']['lines']['surface'])
00631                 win.SetItems(self.GetLayerNames(layer.type))
00632             
00633             #toolWin.UpdatePage(nvizType)
00634             #toolWin.SetPage(nvizType)
00635         
00636         return id
00637     
00638     def UnloadRaster(self, item):
00639         """!Unload 2d raster map
00640         
00641         @param layer item
00642         """
00643         return self._unloadRaster(item)
00644     
00645     def UnloadRaster3d(self, item):
00646         """!Unload 3d raster map
00647         
00648         @param layer item
00649         """
00650         return self._unloadRaster(item)
00651     
00652     def _unloadRaster(self, item):
00653         """!Unload 2d/3d raster map
00654         
00655         @param item layer item
00656         """
00657         layer = self.tree.GetPyData(item)[0]['maplayer']
00658         
00659         if layer.type not in ('raster', '3d-raster'):
00660             return
00661         
00662         data = self.tree.GetPyData(item)[0]['nviz']
00663         
00664         if layer.type ==  'raster':
00665             nvizType = 'surface'
00666             unloadFn = self._display.UnloadSurface
00667             errorMsg = _("Unable to unload raster map")
00668             successMsg = _("Raster map")
00669         else:
00670             nvizType = 'volume'
00671             unloadFn = self._display.UnloadVolume
00672             errorMsg = _("Unable to unload 3d raster map")
00673             successMsg = _("3d raster map")
00674         
00675         id = data[nvizType]['object']['id']
00676         
00677         if unloadFn(id) ==  0:
00678             self.log.WriteError("%s <%s>" % (errorMsg, layer.name))
00679         else:
00680             self.log.WriteLog("%s <%s> %s" % (successMsg, layer.name, _("unloaded successfully")))
00681         
00682         data[nvizType].pop('object')
00683         
00684         self.layers.remove(item)
00685         
00686         # update tools window
00687         if hasattr(self.lmgr, "nviz") and \
00688                 layer.type ==  'raster':
00689             toolWin = self.lmgr.nviz
00690             win = toolWin.FindWindowById( \
00691                 toolWin.win['vector']['lines']['surface'])
00692             win.SetItems(self.GetLayerNames(layer.type))
00693             
00694     def LoadVector(self, item, points = None):
00695         """!Load 2D or 3D vector map overlay
00696         
00697         @param item layer item
00698         @param points True to load points, False to load lines, None
00699         to load both
00700         """
00701         layer = self.tree.GetPyData(item)[0]['maplayer']
00702         if layer.type !=  'vector':
00703             return
00704         
00705         # set default properties
00706         if points is None:
00707             self.SetMapObjProperties(item, -1, 'lines')
00708             self.SetMapObjProperties(item, -1, 'points')
00709             vecTypes = ('points', 'lines')
00710         elif points:
00711             self.SetMapObjProperties(item, -1, 'points')
00712             vecTypes = ('points', )
00713         else:
00714             self.SetMapObjProperties(item, -1, 'lines')
00715             vecTypes = ('lines', )
00716         
00717         id = -1
00718         for vecType in vecTypes:
00719             if vecType == 'lines':
00720                 id = self._display.LoadVector(str(layer.GetName()), False)
00721             else:
00722                 id = self._display.LoadVector(str(layer.GetName()), True)
00723             if id < 0:
00724                 self.log.WriteError(_("Loading vector map <%(name)s> (%(type)s) failed") % \
00725                     { 'name' : layer.name, 'type' : vecType })
00726             # update layer properties
00727             self.SetMapObjProperties(item, id, vecType)
00728         
00729         self.layers.append(item)
00730         
00731         # update properties
00732         data = self.tree.GetPyData(item)[0]['nviz']
00733         event = wxUpdateProperties(data = data)
00734         wx.PostEvent(self, event)
00735         
00736         # update tools window
00737         if hasattr(self.lmgr, "nviz") and \
00738                 item ==  self.GetSelectedLayer(type = 'item'):
00739             toolWin = self.lmgr.nviz
00740             
00741             toolWin.UpdatePage('vector')
00742             ### toolWin.SetPage('vector')
00743         
00744         return id
00745 
00746     def UnloadVector(self, item, points = None):
00747         """!Unload vector map overlay
00748         
00749         @param item layer item
00750         @param points,lines True to unload given feature type
00751         """
00752         layer = self.tree.GetPyData(item)[0]['maplayer']
00753         data = self.tree.GetPyData(item)[0]['nviz']['vector']
00754         
00755         # if vecType is None:
00756         #     vecType = []
00757         #     for v in ('lines', 'points'):
00758         #         if UserSettings.Get(group = 'nviz', key = 'vector',
00759         #                             subkey = [v, 'show']):
00760         #             vecType.append(v)
00761         
00762         if points is None:
00763             vecTypes = ('points', 'lines')
00764         elif points:
00765             vecTypes = ('points', )
00766         else:
00767             vecTypes = ('lines', )
00768         
00769         for vecType in vecTypes:
00770             if 'object' not in data[vecType]:
00771                 continue
00772             
00773             id = data[vecType]['object']['id']
00774             
00775             if vecType ==  'lines':
00776                 ret = self._display.UnloadVector(id, False)
00777             else:
00778                 ret = self._display.UnloadVector(id, True)
00779             if ret ==  0:
00780                 self.log.WriteError(_("Unable to unload vector map <%(name)s> (%(type)s)") % \
00781                     { 'name': layer.name, 'type' : vecType })
00782             else:
00783                 self.log.WriteLog(_("Vector map <%(name)s> (%(type)s) unloaded successfully") % \
00784                     { 'name' : layer.name, 'type' : vecType })
00785             
00786             data[vecType].pop('object')
00787             
00788             ### self.layers.remove(id)
00789         
00790     def Reset(self):
00791         """!Reset (unload data)"""
00792         for item in self.layers:
00793             type = self.tree.GetPyData(item)[0]['maplayer'].type
00794             if type ==  'raster':
00795                 self.UnloadRaster(item)
00796             elif type ==  '3d-raster':
00797                 self.UnloadRaster3d(item)
00798             elif type ==  'vector':
00799                 self.UnloadVector(item)
00800         
00801         self.init = False
00802 
00803     def OnZoomToMap(self, event):
00804         """!Set display extents to match selected raster or vector
00805         map or volume.
00806         
00807         @todo vector, volume
00808         """
00809         layer = self.GetSelectedLayer()
00810         
00811         if layer is None:
00812             return
00813         
00814         Debug.msg (3, "GLWindow.OnZoomToMap(): layer = %s, type = %s" % \
00815                        (layer.name, layer.type))
00816         
00817         self._display.SetViewportDefault()
00818 
00819     def ResetView(self):
00820         """!Reset to default view"""
00821         self.view['z-exag']['value'], \
00822             self.iview['height']['value'], \
00823             self.iview['height']['min'], \
00824             self.iview['height']['max'] = self._display.SetViewDefault()
00825         
00826         self.view['z-exag']['min'] = 0
00827         self.view['z-exag']['max'] = self.view['z-exag']['value'] * 10
00828         
00829         self.view['position']['x'] = UserSettings.Get(group = 'nviz', key = 'view',
00830                                                  subkey = ('position', 'x'))
00831         self.view['position']['y'] = UserSettings.Get(group = 'nviz', key = 'view',
00832                                                  subkey = ('position', 'y'))
00833         self.view['persp']['value'] = UserSettings.Get(group = 'nviz', key = 'view',
00834                                                        subkey = ('persp', 'value'))
00835         
00836         self.view['twist']['value'] = UserSettings.Get(group = 'nviz', key = 'view',
00837                                                        subkey = ('twist', 'value'))
00838         
00839         event = wxUpdateView(zExag = False)
00840         wx.PostEvent(self, event)
00841         
00842     def UpdateMapObjProperties(self, event):
00843         """!Generic method to update data layer properties"""
00844         data = event.data
00845         
00846         if 'surface' in data:
00847             id = data['surface']['object']['id']
00848             self.UpdateSurfaceProperties(id, data['surface'])
00849             # -> initialized
00850             data['surface']['object']['init'] = True
00851             
00852         elif 'volume' in data:
00853             id = data['volume']['object']['id']
00854             self.UpdateVolumeProperties(id, data['volume'])
00855             # -> initialized
00856             data['volume']['object']['init'] = True
00857             
00858         elif 'vector' in data:
00859             for type in ('lines', 'points'):
00860                 if 'object' in data['vector'][type]:
00861                     id = data['vector'][type]['object']['id']
00862                     self.UpdateVectorProperties(id, data['vector'], type)
00863                     # -> initialized
00864                     data['vector'][type]['object']['init'] = True
00865         
00866     def UpdateSurfaceProperties(self, id, data):
00867         """!Update surface map object properties"""
00868         # surface attributes
00869         for attrb in ('topo', 'color', 'mask',
00870                      'transp', 'shine', 'emit'):
00871             if attrb not in data['attribute'] or \
00872                     'update' not in data['attribute'][attrb]:
00873                 continue
00874             
00875             map = data['attribute'][attrb]['map']
00876             value = data['attribute'][attrb]['value']
00877             
00878             if map is None: # unset
00879                 # only optional attributes
00880                 if attrb ==  'mask':
00881                     # TODO: invert mask
00882                     # TODO: broken in NVIZ
00883                     self._display.UnsetSurfaceMask(id)
00884                 elif attrb ==  'transp':
00885                     self._display.UnsetSurfaceTransp(id)
00886                 elif attrb ==  'emit':
00887                     self._display.UnsetSurfaceEmit(id) 
00888             else:
00889                 if type(value) ==  type('') and \
00890                         len(value) <=  0: # ignore empty values (TODO: warning)
00891                     continue
00892                 if attrb ==  'topo':
00893                     self._display.SetSurfaceTopo(id, map, str(value)) 
00894                 elif attrb ==  'color':
00895                     self._display.SetSurfaceColor(id, map, str(value))
00896                 elif attrb ==  'mask':
00897                     # TODO: invert mask
00898                     # TODO: broken in NVIZ
00899                     self._display.SetSurfaceMask(id, False, str(value))
00900                 elif attrb ==  'transp':
00901                     self._display.SetSurfaceTransp(id, map, str(value)) 
00902                 elif attrb ==  'shine':
00903                     self._display.SetSurfaceShine(id, map, str(value)) 
00904                 elif attrb ==  'emit':
00905                     self._display.SetSurfaceEmit(id, map, str(value)) 
00906             data['attribute'][attrb].pop('update')
00907         
00908         # draw res
00909         if 'update' in data['draw']['resolution']:
00910             coarse = data['draw']['resolution']['coarse']
00911             fine   = data['draw']['resolution']['fine']
00912             
00913             if data['draw']['all']:
00914                 self._display.SetSurfaceRes(-1, fine, coarse)
00915             else:
00916                 self._display.SetSurfaceRes(id, fine, coarse)
00917             data['draw']['resolution'].pop('update')
00918         
00919         # draw style
00920         if 'update' in data['draw']['mode']:
00921             if data['draw']['mode']['value'] < 0: # need to calculate
00922                 data['draw']['mode']['value'] = \
00923                     self.nvizDefault.GetDrawMode(mode = data['draw']['mode']['desc']['mode'],
00924                                                  style = data['draw']['mode']['desc']['style'],
00925                                                  shade = data['draw']['mode']['desc']['shading'],
00926                                                  string = True)
00927             style = data['draw']['mode']['value']
00928             if data['draw']['all']:
00929                 self._display.SetSurfaceStyle(-1, style)
00930             else:
00931                 self._display.SetSurfaceStyle(id, style)
00932             data['draw']['mode'].pop('update')
00933         
00934         # wire color
00935         if 'update' in data['draw']['wire-color']:
00936             color = data['draw']['wire-color']['value']
00937             if data['draw']['all']:
00938                 self._display.SetWireColor(-1, str(color))
00939             else:
00940                 self._display.SetWireColor(id, str(color))
00941             data['draw']['wire-color'].pop('update')
00942         
00943         # position
00944         if 'update' in data['position']:
00945             x = data['position']['x']
00946             y = data['position']['y']
00947             z = data['position']['z']
00948             self._display.SetSurfacePosition(id, x, y, z)
00949             data['position'].pop('update')
00950         data['draw']['all'] = False
00951         
00952     def UpdateVolumeProperties(self, id, data, isosurfId = None):
00953         """!Update volume (isosurface/slice) map object properties"""
00954         if 'update' in data['draw']['resolution']:
00955             self._display.SetIsosurfaceRes(id, data['draw']['resolution']['value'])
00956             data['draw']['resolution'].pop('update')
00957         
00958         if 'update' in data['draw']['shading']:
00959             if data['draw']['shading']['value'] < 0: # need to calculate
00960                 data['draw']['shading']['value'] = \
00961                     self.nvizDefault.GetDrawMode(shade = data['draw']['shading'],
00962                                                  string = False)
00963             data['draw']['shading'].pop('update')
00964         
00965         #
00966         # isosurface attributes
00967         #
00968         isosurfId = 0
00969         for isosurf in data['isosurface']:
00970             for attrb in ('color', 'mask',
00971                           'transp', 'shine', 'emit'):
00972                 if attrb not in isosurf or \
00973                         'update' not in isosurf[attrb]:
00974                     continue
00975                 map = isosurf[attrb]['map']
00976                 value = isosurf[attrb]['value']
00977                 
00978                 if map is None: # unset
00979                     # only optional attributes
00980                     if attrb ==  'mask':
00981                         # TODO: invert mask
00982                         # TODO: broken in NVIZ
00983                         self._display.UnsetIsosurfaceMask(id, isosurfId)
00984                     elif attrb ==  'transp':
00985                         self._display.UnsetIsosurfaceTransp(id, isosurfId)
00986                     elif attrb ==  'emit':
00987                         self._display.UnsetIsosurfaceEmit(id, isosurfId) 
00988                 else:
00989                     if type(value) ==  type('') and \
00990                             len(value) <=  0: # ignore empty values (TODO: warning)
00991                         continue
00992                     elif attrb ==  'color':
00993                         self._display.SetIsosurfaceColor(id, isosurfId, map, str(value))
00994                     elif attrb ==  'mask':
00995                         # TODO: invert mask
00996                         # TODO: broken in NVIZ
00997                         self._display.SetIsosurfaceMask(id, isosurfId, False, str(value))
00998                     elif attrb ==  'transp':
00999                         self._display.SetIsosurfaceTransp(id, isosurfId, map, str(value)) 
01000                     elif attrb ==  'shine':
01001                         self._display.SetIsosurfaceShine(id, isosurfId, map, str(value)) 
01002                     elif attrb ==  'emit':
01003                         self._display.SetIsosurfaceEmit(id, isosurfId, map, str(value)) 
01004                 isosurf[attrb].pop('update')
01005             isosurfId +=  1
01006         
01007     def UpdateVectorProperties(self, id, data, type):
01008         """!Update vector layer properties
01009         
01010         @param id layer id
01011         @param data properties
01012         @param type lines/points
01013         """
01014         if type ==  'points':
01015             self.UpdateVectorPointsProperties(id, data[type])
01016         else:
01017             self.UpdateVectorLinesProperties(id, data[type])
01018         
01019     def UpdateVectorLinesProperties(self, id, data):
01020         """!Update vector line map object properties"""
01021         # mode
01022         if 'update' in data['color'] or \
01023                 'update' in data['width'] or \
01024                 'update' in data['mode']:
01025             width = data['width']['value']
01026             color = data['color']['value']
01027             if data['mode']['type'] ==  'flat':
01028                 flat = True
01029                 if 'surface' in data:
01030                     data.pop('surface')
01031             else:
01032                 flat = False
01033             
01034             self._display.SetVectorLineMode(id, color,
01035                                             width, flat)
01036             
01037             if 'update' in data['color']:
01038                 data['color'].pop('update')
01039             if 'update' in data['width']:
01040                 data['width'].pop('update')
01041             if 'update' in data['mode']:
01042                 data['mode'].pop('update')
01043         
01044         # height
01045         if 'update' in data['height']:
01046             self._display.SetVectorLineHeight(id,
01047                                               data['height']['value'])
01048             data['height'].pop('update')
01049         
01050         # surface
01051         if 'update' in data['mode']:
01052             sid = self.GetLayerId(type = 'raster', name = data['mode']['surface'])
01053             if sid > -1:
01054                 self._display.SetVectorLineSurface(id, sid)
01055             
01056             data['mode'].pop('update')
01057         
01058     def UpdateVectorPointsProperties(self, id, data):
01059         """!Update vector point map object properties"""
01060         if 'update' in data['size'] or \
01061                 'update' in data['width'] or \
01062                 'update' in data['marker'] or \
01063                 'update' in data['color']:
01064             ret = self._display.SetVectorPointMode(id, data['color']['value'],
01065                                                    data['width']['value'], float(data['size']['value']),
01066                                                    data['marker']['value'] + 1)
01067             
01068             error = None
01069             if ret ==  -1:
01070                 error = _("Vector point layer not found (id = %d)") % id
01071             elif ret ==  -2:
01072                 error = _("Unable to set data layer properties (id = %d)") % id
01073 
01074             if error:
01075                 raise gcmd.GException(_("Setting data layer properties failed.\n\n%s") % error)
01076             
01077             for prop in ('size', 'width', 'marker', 'color'):
01078                 if 'update' in data[prop]:
01079                     data[prop].pop('update')
01080         
01081         # height
01082         if 'update' in data['height']:
01083             self._display.SetVectorPointHeight(id,
01084                                                data['height']['value'])
01085             data['height'].pop('update')
01086         
01087         # surface
01088         if 'update' in data['mode']:
01089             sid = self.GetLayerId(type = 'raster', name = data['mode']['surface'])
01090             if sid > -1:
01091                 self._display.SetVectorPointSurface(id, sid)
01092             
01093             data['mode'].pop('update')
01094             
01095     def GetLayerNames(self, type):
01096         """!Return list of map layer names of given type"""
01097         layerName = []
01098         
01099         for item in self.layers:
01100             mapLayer = self.tree.GetPyData(item)[0]['maplayer']
01101             if type !=  mapLayer.GetType():
01102                 continue
01103             
01104             layerName.append(mapLayer.GetName())
01105         
01106         return layerName
01107     
01108     def GetLayerId(self, type, name):
01109         """!Get layer object id or -1"""
01110         if len(name) < 1:
01111             return -1
01112         
01113         for item in self.layers:
01114             mapLayer = self.tree.GetPyData(item)[0]['maplayer']
01115             if type !=  mapLayer.GetType() or \
01116                     name !=  mapLayer.GetName():
01117                 continue
01118             
01119             data = self.tree.GetPyData(item)[0]['nviz']
01120             
01121             if type ==  'raster':
01122                 return data['surface']['object']['id']
01123             elif type ==  'vpoint':
01124                 return data['vector']['points']['object']['id']
01125             elif type ==  'vline':
01126                 return data['vector']['lines']['object']['id']
01127             elif type ==  '3d-raster':
01128                 return data['volume']['object']['id']
01129         
01130         return -1
01131     
01132     def SaveToFile(self, FileName, FileType, width, height):
01133         """!This draws the DC to a buffer that can be saved to a file.
01134         
01135         @todo fix BufferedPaintDC
01136         
01137         @param FileName file name
01138         @param FileType type of bitmap
01139         @param width image width
01140         @param height image height
01141         """
01142         self._display.SaveToFile(FileName, width, height)
01143                 
01144         # pbuffer = wx.EmptyBitmap(max(1, self.Map.width), max(1, self.Map.height))
01145         # dc = wx.BufferedPaintDC(self, pbuffer)
01146         # dc.Clear()
01147         # self.SetCurrent()
01148         # self._display.Draw(False, -1)
01149         # pbuffer.SaveFile(FileName, FileType)
01150         # self.SwapBuffers()
01151         
01152     def GetDisplay(self):
01153         """!Get display instance"""
01154         return self._display
01155         
01156     def ZoomToMap(self):
01157         """!Reset view
01158         """
01159         self.lmgr.nviz.OnResetView(None)
01160 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines