nviz_mapdisp.py 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. """
  2. @package nviz_mapdisp.py
  3. @brief Nviz extension for wxGUI
  4. This module implements 3D visualization mode of map display.
  5. List of classes:
  6. - GLWindow
  7. (C) 2008-2009 by the GRASS Development Team
  8. This program is free software under the GNU General Public
  9. License (>=v2). Read the file COPYING that comes with GRASS
  10. for details.
  11. @author Martin Landa <landa.martin gmail.com> (Google SoC 2008)
  12. """
  13. import os
  14. import sys
  15. import time
  16. import copy
  17. from threading import Thread
  18. import wx
  19. import wx.lib.scrolledpanel as scrolled
  20. from wx.lib.newevent import NewEvent
  21. from wx import glcanvas
  22. import gcmd
  23. import globalvar
  24. from debug import Debug as Debug
  25. from mapdisp_window import MapWindow
  26. from goutput import wxCmdOutput
  27. from preferences import globalSettings as UserSettings
  28. from workspace import Nviz as NvizDefault
  29. import wxnviz
  30. # sys.path.append(os.path.join(globalvar.ETCWXDIR, "nviz"))
  31. # import grass7_wxnviz as wxnviz
  32. wxUpdateProperties, EVT_UPDATE_PROP = NewEvent()
  33. wxUpdateView, EVT_UPDATE_VIEW = NewEvent()
  34. class NvizThread(Thread):
  35. def __init__(self, log, progressbar, window):
  36. Thread.__init__(self)
  37. self.log = log
  38. self.progressbar = progressbar
  39. self.window = window
  40. self.nvizClass = None
  41. self.setDaemon(True)
  42. def run(self):
  43. self.nvizClass = wxnviz.Nviz(self.log)
  44. class GLWindow(MapWindow, glcanvas.GLCanvas):
  45. """!OpenGL canvas for Map Display Window"""
  46. def __init__(self, parent, id,
  47. pos=wx.DefaultPosition,
  48. size=wx.DefaultSize,
  49. style=wx.NO_FULL_REPAINT_ON_RESIZE,
  50. Map=None, tree=None, lmgr=None):
  51. self.parent = parent # MapFrame
  52. self.Map = Map
  53. self.tree = tree
  54. self._layermanager = lmgr
  55. glcanvas.GLCanvas.__init__(self, parent, id)
  56. MapWindow.__init__(self, parent, id, pos, size, style,
  57. Map, tree, self._layermanager)
  58. self.Hide()
  59. self.init = False
  60. self.initView = False
  61. # render mode
  62. self.render = { 'quick' : False,
  63. # do not render vector lines in quick mode
  64. 'vlines' : False,
  65. 'vpoints' : False }
  66. # list of loaded map layers (layer tree items)
  67. self.layers = []
  68. #
  69. # use display region instead of computational
  70. #
  71. os.environ['GRASS_REGION'] = self.Map.SetRegion()
  72. #
  73. # create nviz instance
  74. #
  75. if self._layermanager:
  76. logerr = self._layermanager.goutput.cmd_stderr
  77. logmsg = self._layermanager.goutput.cmd_output
  78. else:
  79. logerr = logmsg = None
  80. self.nvizThread = NvizThread(logerr,
  81. self.parent.statusbarWin['progress'],
  82. logmsg)
  83. self.nvizThread.start()
  84. time.sleep(.1)
  85. self.nvizClass = self.nvizThread.nvizClass
  86. # GRASS_REGION needed only for initialization
  87. del os.environ['GRASS_REGION']
  88. #
  89. # default values
  90. #
  91. self.view = copy.deepcopy(UserSettings.Get(group='nviz', key='view')) # copy
  92. self.iview = UserSettings.Get(group='nviz', key='view', internal=True)
  93. self.nvizDefault = NvizDefault()
  94. self.size = None
  95. self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
  96. self.Bind(wx.EVT_SIZE, self.OnSize)
  97. self.Bind(wx.EVT_PAINT, self.OnPaint)
  98. self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
  99. self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
  100. self.Bind(wx.EVT_MOTION, self.OnMouseAction)
  101. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseAction)
  102. self.Bind(EVT_UPDATE_PROP, self.UpdateMapObjProperties)
  103. self.Bind(EVT_UPDATE_VIEW, self.UpdateView)
  104. self.Bind(wx.EVT_CLOSE, self.OnClose)
  105. def OnClose(self, event):
  106. # cleanup when window actually closes (on quit) and not just is hidden
  107. self.Reset()
  108. def OnEraseBackground(self, event):
  109. pass # do nothing, to avoid flashing on MSW
  110. def OnSize(self, event):
  111. self.size = self.parent.GetClientSize()
  112. if self.GetContext():
  113. Debug.msg(3, "GLCanvas.OnSize(): w=%d, h=%d" % \
  114. (self.size.width, self.size.height))
  115. self.SetCurrent()
  116. self.nvizClass.ResizeWindow(self.size.width,
  117. self.size.height)
  118. event.Skip()
  119. def OnPaint(self, event):
  120. Debug.msg(3, "GLCanvas.OnPaint()")
  121. dc = wx.PaintDC(self)
  122. self.SetCurrent()
  123. if not self.initView:
  124. self.nvizClass.InitView()
  125. self.initView = True
  126. self.LoadDataLayers()
  127. self.UnloadDataLayers()
  128. if not self.init:
  129. self.ResetView()
  130. if hasattr(self.parent, "nvizToolWin"):
  131. self.parent.nvizToolWin.UpdatePage('view')
  132. layer = self.GetSelectedLayer()
  133. if layer:
  134. if layer.type == 'raster':
  135. self.parent.nvizToolWin.UpdatePage('surface')
  136. elif layer.type == 'vector':
  137. self.parent.nvizToolWin.UpdatePage('vector')
  138. self.parent.nvizToolWin.UpdateSettings()
  139. # update widgets
  140. win = self.parent.nvizToolWin.FindWindowById( \
  141. self.parent.nvizToolWin.win['vector']['lines']['surface'])
  142. win.SetItems(self.GetLayerNames('raster'))
  143. self.init = True
  144. self.UpdateMap()
  145. def OnMouseAction(self, event):
  146. # change position
  147. if event.Dragging() and event.LeftIsDown():
  148. ### self.lastX = self.lastY = self.x = self.y
  149. ### self.x, self.y = event.GetPosition()
  150. ### self.Refresh(False)
  151. pass
  152. # change perspective with mouse wheel
  153. wheel = event.GetWheelRotation()
  154. if wheel != 0:
  155. current = event.GetPositionTuple()[:]
  156. Debug.msg (5, "GLWindow.OnMouseMotion(): wheel=%d" % wheel)
  157. prev_value = self.view['persp']['value']
  158. if wheel > 0:
  159. value = -1 * self.view['persp']['step']
  160. else:
  161. value = self.view['persp']['step']
  162. self.view['persp']['value'] += value
  163. if self.view['persp']['value'] < 1:
  164. self.view['persp']['value'] = 1
  165. elif self.view['persp']['value'] > 100:
  166. self.view['persp']['value'] = 100
  167. if prev_value != self.view['persp']['value']:
  168. if hasattr(self.parent, "nvizToolWin"):
  169. self.parent.nvizToolWin.UpdateSettings()
  170. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  171. self.iview['height']['value'],
  172. self.view['persp']['value'],
  173. self.view['twist']['value'])
  174. # redraw map
  175. self.OnPaint(None)
  176. # update statusbar
  177. ### self.parent.StatusbarUpdate()
  178. def OnLeftDown(self, event):
  179. self.CaptureMouse()
  180. ### self.x, self.y = self.lastX, self.lastY = event.GetPosition()
  181. def OnLeftUp(self, event):
  182. self.ReleaseMouse()
  183. def UpdateView(self, event):
  184. """!Change view settings"""
  185. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  186. self.iview['height']['value'],
  187. self.view['persp']['value'],
  188. self.view['twist']['value'])
  189. if event and event.zExag:
  190. self.nvizClass.SetZExag(self.view['z-exag']['value'])
  191. if event: event.Skip()
  192. def UpdateMap(self, render=True):
  193. """
  194. Updates the canvas anytime there is a change to the
  195. underlaying images or to the geometry of the canvas.
  196. @param render re-render map composition
  197. """
  198. start = time.clock()
  199. self.resize = False
  200. if self.render['quick'] is False:
  201. self.parent.statusbarWin['progress'].Show()
  202. self.parent.statusbarWin['progress'].SetRange(2)
  203. self.parent.statusbarWin['progress'].SetValue(0)
  204. if self.render['quick'] is False:
  205. self.parent.statusbarWin['progress'].SetValue(1)
  206. self.nvizClass.Draw(False, -1)
  207. elif self.render['quick'] is True:
  208. # quick
  209. mode = wxnviz.DRAW_QUICK_SURFACE | wxnviz.DRAW_QUICK_VOLUME
  210. if self.render['vlines']:
  211. mode |= wxnviz.DRAW_QUICK_VLINES
  212. if self.render['vpoints']:
  213. mode |= wxnviz.DRAW_QUICK_VPOINTS
  214. self.nvizClass.Draw(True, mode)
  215. else: # None -> reuse last rendered image
  216. pass # TODO
  217. self.SwapBuffers()
  218. stop = time.clock()
  219. if self.render['quick'] is False:
  220. self.parent.statusbarWin['progress'].SetValue(2)
  221. # hide process bar
  222. self.parent.statusbarWin['progress'].Hide()
  223. #
  224. # update statusbar
  225. #
  226. # self.parent.StatusbarUpdate()
  227. Debug.msg(3, "GLWindow.UpdateMap(): quick=%d, -> time=%g" % \
  228. (self.render['quick'], (stop-start)))
  229. # print stop-start
  230. def EraseMap(self):
  231. """
  232. Erase the canvas
  233. """
  234. self.nvizClass.EraseMap()
  235. self.SwapBuffers()
  236. def IsLoaded(self, item):
  237. """!Check if layer (item) is already loaded
  238. @param item layer item
  239. """
  240. layer = self.tree.GetPyData(item)[0]['maplayer']
  241. data = self.tree.GetPyData(item)[0]['nviz']
  242. if not data:
  243. return 0
  244. if layer.type == 'raster':
  245. if not data['surface'].has_key('object'):
  246. return 0
  247. elif layer.type == 'vector':
  248. if not data['vlines'].has_key('object') and \
  249. not data['points'].has_key('object'):
  250. return 0
  251. return 1
  252. def _GetDataLayers(self, item, litems):
  253. """!Return get list of enabled map layers"""
  254. # load raster & vector maps
  255. while item and item.IsOk():
  256. type = self.tree.GetPyData(item)[0]['type']
  257. if type == 'group':
  258. subItem = self.tree.GetFirstChild(item)[0]
  259. self._GetDataLayers(subItem, litems)
  260. item = self.tree.GetNextSibling(item)
  261. if not item.IsChecked() or \
  262. type not in ('raster', 'vector', '3d-raster'):
  263. item = self.tree.GetNextSibling(item)
  264. continue
  265. litems.append(item)
  266. item = self.tree.GetNextSibling(item)
  267. def LoadDataLayers(self):
  268. """!Load raster/vector from current layer tree
  269. @todo volumes
  270. """
  271. if not self.tree:
  272. return
  273. listOfItems = []
  274. item = self.tree.GetFirstChild(self.tree.root)[0]
  275. self._GetDataLayers(item, listOfItems)
  276. start = time.time()
  277. while(len(listOfItems) > 0):
  278. item = listOfItems.pop()
  279. type = self.tree.GetPyData(item)[0]['type']
  280. if item not in self.layers:
  281. try:
  282. if type == 'raster':
  283. self.LoadRaster(item)
  284. elif type == '3d-raster':
  285. self.LoadRaster3d(item)
  286. except gcmd.NvizError, e:
  287. print >> sys.stderr, "Nviz:" + e.message
  288. try:
  289. if type == 'vector':
  290. data = self.tree.GetPyData(item)[0]['nviz']
  291. vecType = []
  292. if data and data.has_key('vector'):
  293. for v in ('lines', 'points'):
  294. if data['vector'][v]:
  295. vecType.append(v)
  296. self.LoadVector(item, vecType)
  297. except gcmd.NvizError, e:
  298. print >> sys.stderr, "Nviz:" + e.message
  299. self.init = False
  300. stop = time.time()
  301. Debug.msg(3, "GLWindow.LoadDataLayers(): time=%f" % (stop-start))
  302. # print stop - start
  303. def UnloadDataLayers(self):
  304. """!Unload any layers that have been deleted from layer tree"""
  305. if not self.tree:
  306. return
  307. listOfItems = []
  308. item = self.tree.GetFirstChild(self.tree.root)[0]
  309. self._GetDataLayers(item, listOfItems)
  310. start = time.time()
  311. for layer in self.layers:
  312. if layer not in listOfItems:
  313. ltype = self.tree.GetPyData(layer)[0]['type']
  314. try:
  315. if ltype == 'raster':
  316. self.UnloadRaster(layer)
  317. elif ltype == '3d-raster':
  318. self.UnloadRaster3d(layer)
  319. elif ltype == 'vector':
  320. data = self.tree.GetPyData(layer)[0]['nviz']
  321. vecType = []
  322. if data and data.has_key('vector'):
  323. for v in ('lines', 'points'):
  324. if data['vector'][v]:
  325. vecType.append(v)
  326. self.UnloadVector(layer, vecType)
  327. self.UpdateView(None)
  328. except gcmd.NvizError, e:
  329. print >> sys.stderr, "Nviz:" + e.message
  330. self.parent.nvizToolWin.UpdateSettings()
  331. stop = time.time()
  332. Debug.msg(3, "GLWindow.UnloadDataLayers(): time=%f" % (stop-start))
  333. def SetMapObjProperties(self, item, id, nvizType):
  334. """!Set map object properties
  335. Properties must be afterwards updated by
  336. UpdateMapObjProperties().
  337. @param item layer item
  338. @param id nviz layer id (or -1)
  339. @param nvizType nviz data type (surface, points, vector)
  340. """
  341. type = self.tree.GetPyData(item)[0]['maplayer'].type
  342. # reference to original layer properties (can be None)
  343. data = self.tree.GetPyData(item)[0]['nviz']
  344. if data is None:
  345. # init data structure
  346. self.tree.GetPyData(item)[0]['nviz'] = {}
  347. data = self.tree.GetPyData(item)[0]['nviz']
  348. if type == 'raster':
  349. # reset to default properties
  350. data[nvizType] = self.nvizDefault.SetSurfaceDefaultProp()
  351. elif type == 'vector':
  352. # reset to default properties (lines/points)
  353. data['vector'] = self.nvizDefault.SetVectorDefaultProp()
  354. elif type == '3d-raster':
  355. # reset to default properties
  356. data[nvizType] = self.nvizDefault.SetVolumeDefaultProp()
  357. else:
  358. # complete data (use default values)
  359. if type == 'raster':
  360. data['surface'] = self.nvizDefault.SetSurfaceDefaultProp()
  361. if type == 'vector':
  362. if not data['vector']['lines']:
  363. self.nvizDefault.SetVectorLinesDefaultProp(data['vector']['lines'])
  364. if not data['vector']['points']:
  365. self.nvizDefault.SetVectorPointsDefaultProp(data['vector']['points'])
  366. # set updates
  367. for sec in data.keys():
  368. for sec1 in data[sec].keys():
  369. for sec2 in data[sec][sec1].keys():
  370. if sec2 != 'all':
  371. data[sec][sec1][sec2]['update'] = None
  372. event = wxUpdateProperties(data=data)
  373. wx.PostEvent(self, event)
  374. # set id
  375. if id > 0:
  376. if type in ('raster', '3d-raster'):
  377. data[nvizType]['object'] = { 'id' : id,
  378. 'init' : False }
  379. elif type == 'vector':
  380. data['vector'][nvizType]['object'] = { 'id' : id,
  381. 'init' : False }
  382. return data
  383. def LoadRaster(self, item):
  384. """!Load 2d raster map and set surface attributes
  385. @param layer item
  386. """
  387. return self._loadRaster(item)
  388. def LoadRaster3d(self, item):
  389. """!Load 3d raster map and set surface attributes
  390. @param layer item
  391. """
  392. return self._loadRaster(item)
  393. def _loadRaster(self, item):
  394. """!Load 2d/3d raster map and set its attributes
  395. @param layer item
  396. """
  397. layer = self.tree.GetPyData(item)[0]['maplayer']
  398. if layer.type not in ('raster', '3d-raster'):
  399. return
  400. if layer.type == 'raster':
  401. id = self.nvizClass.LoadSurface(str(layer.name), None, None)
  402. nvizType = 'surface'
  403. errorMsg = _("Loading raster map")
  404. elif layer.type == '3d-raster':
  405. id = self.nvizClass.LoadVolume(str(layer.name), None, None)
  406. nvizType = 'volume'
  407. errorMsg = _("Loading 3d raster map")
  408. else:
  409. id = -1
  410. if id < 0:
  411. if layer.type in ('raster', '3d-raster'):
  412. print >> sys.stderr, "Nviz:" + "%s <%s> %s" % (errorMsg, layer.name, _("failed"))
  413. else:
  414. print >> sys.stderr, "Nviz:" + _("Unsupported layer type '%s'") % layer.type
  415. self.layers.append(item)
  416. # set default/workspace layer properties
  417. data = self.SetMapObjProperties(item, id, nvizType)
  418. # update properties
  419. event = wxUpdateProperties(data=data)
  420. wx.PostEvent(self, event)
  421. # update tools window
  422. if hasattr(self.parent, "nvizToolWin") and \
  423. item == self.GetSelectedLayer(type='item'):
  424. toolWin = self.parent.nvizToolWin
  425. if layer.type == 'raster':
  426. win = toolWin.FindWindowById( \
  427. toolWin.win['vector']['lines']['surface'])
  428. win.SetItems(self.GetLayerNames(layer.type))
  429. toolWin.UpdatePage(nvizType)
  430. toolWin.SetPage(nvizType)
  431. return id
  432. def UnloadRaster(self, item):
  433. """!Unload 2d raster map
  434. @param layer item
  435. """
  436. return self._unloadRaster(item)
  437. def UnloadRaster3d(self, item):
  438. """!Unload 3d raster map
  439. @param layer item
  440. """
  441. return self._unloadRaster(item)
  442. def _unloadRaster(self, item):
  443. """!Unload 2d/3d raster map
  444. @param item layer item
  445. """
  446. layer = self.tree.GetPyData(item)[0]['maplayer']
  447. if layer.type not in ('raster', '3d-raster'):
  448. return
  449. data = self.tree.GetPyData(item)[0]['nviz']
  450. if layer.type == 'raster':
  451. nvizType = 'surface'
  452. unloadFn = self.nvizClass.UnloadSurface
  453. errorMsg = _("Unable to unload raster map")
  454. successMsg = _("Raster map")
  455. else:
  456. nvizType = 'volume'
  457. unloadFn = self.nvizClass.UnloadVolume
  458. errorMsg = _("Unable to unload 3d raster map")
  459. successMsg = _("3d raster map")
  460. id = data[nvizType]['object']['id']
  461. if unloadFn(id) == 0:
  462. print >> sys.stderr, "Nviz:" + "%s <%s>" % (errorMsg, layer.name)
  463. else:
  464. print "Nviz:" + "%s <%s> %s" % (successMsg, layer.name, _("unloaded successfully"))
  465. data[nvizType].pop('object')
  466. self.layers.remove(item)
  467. # update tools window
  468. if hasattr(self.parent, "nvizToolWin") and \
  469. layer.type == 'raster':
  470. toolWin = self.parent.nvizToolWin
  471. win = toolWin.FindWindowById( \
  472. toolWin.win['vector']['lines']['surface'])
  473. win.SetItems(self.GetLayerNames(layer.type))
  474. # remove surface page
  475. if toolWin.notebook.GetSelection() == toolWin.page[nvizType]['id']:
  476. toolWin.notebook.RemovePage(toolWin.page[nvizType]['id'])
  477. toolWin.page[nvizType]['id'] = -1
  478. toolWin.page['settings']['id'] = 1
  479. def LoadVector(self, item, vecType=None):
  480. """!Load 2D or 3D vector map overlay
  481. @param item layer item
  482. @param vecType vector type (lines / points)
  483. """
  484. layer = self.tree.GetPyData(item)[0]['maplayer']
  485. if layer.type != 'vector':
  486. return
  487. if vecType is None:
  488. # load data type by default
  489. vecType = []
  490. for v in ('lines', 'points'):
  491. if UserSettings.Get(group='nviz', key='vector',
  492. subkey=[v, 'show']):
  493. vecType.append(v)
  494. # set default properties
  495. self.SetMapObjProperties(item, -1, 'lines')
  496. self.SetMapObjProperties(item, -1, 'points')
  497. id = -1
  498. for type in vecType:
  499. if type == 'lines':
  500. id = self.nvizClass.LoadVector(str(layer.name), False)
  501. else:
  502. id = self.nvizClass.LoadVector(str(layer.name), True)
  503. if id < 0:
  504. print >> sys.stderr, "Nviz:" + _("Loading vector map <%(name)s> (%(type)s) failed") % \
  505. { 'name' : layer.name, 'type' : type }
  506. continue
  507. # update layer properties
  508. self.SetMapObjProperties(item, id, type)
  509. self.layers.append(item)
  510. # update properties
  511. data = self.tree.GetPyData(item)[0]['nviz']
  512. event = wxUpdateProperties(data=data)
  513. wx.PostEvent(self, event)
  514. # update tools window
  515. if hasattr(self.parent, "nvizToolWin") and \
  516. item == self.GetSelectedLayer(type='item'):
  517. toolWin = self.parent.nvizToolWin
  518. toolWin.UpdatePage('vector')
  519. toolWin.SetPage('vector')
  520. return id
  521. def UnloadVector(self, item, vecType=None):
  522. """!Unload vector map overlay
  523. @param item layer item
  524. @param vecType vector type (lines, points)
  525. """
  526. layer = self.tree.GetPyData(item)[0]['maplayer']
  527. data = self.tree.GetPyData(item)[0]['nviz']['vector']
  528. if vecType is None:
  529. vecType = []
  530. for v in ('lines', 'points'):
  531. if UserSettings.Get(group='nviz', key='vector',
  532. subkey=[v, 'show']):
  533. vecType.append(v)
  534. for vtype in vecType:
  535. if not data[vtype].has_key('object'):
  536. continue
  537. id = data[vtype]['object']['id']
  538. if vtype == 'lines':
  539. ret = self.nvizClass.UnloadVector(id, False)
  540. else:
  541. ret = self.nvizClass.UnloadVector(id, True)
  542. if ret == 0:
  543. print >> sys.stderr, "Nviz:" + _("Unable to unload vector map <%(name)s> (%(type)s)") % \
  544. { 'name': layer.name, 'type' : vtype }
  545. else:
  546. print "Nviz:" + _("Vector map <%(name)s> (%(type)s) unloaded successfully") % \
  547. { 'name' : layer.name, 'type' : vtype }
  548. data[vtype].pop('object')
  549. self.layers.remove(id)
  550. # update tools window
  551. if hasattr(self.parent, "nvizToolWin") and \
  552. vecType is None:
  553. toolWin = self.parent.nvizToolWin
  554. # remove surface page
  555. if toolWin.notebook.GetSelection() == toolWin.page['surface']['id']:
  556. toolWin.notebook.RemovePage(toolWin.page['surface']['id'])
  557. toolWin.page['surface']['id'] = -1
  558. toolWin.page['settings']['id'] = 1
  559. def Reset(self):
  560. """!Reset (unload data)"""
  561. for item in self.layers:
  562. type = self.tree.GetPyData(item)[0]['maplayer'].type
  563. if type == 'raster':
  564. self.UnloadRaster(item)
  565. elif type == '3d-raster':
  566. self.UnloadRaster3d(item)
  567. elif type == 'vector':
  568. self.UnloadVector(item)
  569. self.init = False
  570. def OnZoomToMap(self, event):
  571. """
  572. Set display extents to match selected raster
  573. or vector map or volume.
  574. @todo vector, volume
  575. """
  576. layer = self.GetSelectedLayer()
  577. if layer is None:
  578. return
  579. Debug.msg (3, "GLWindow.OnZoomToMap(): layer=%s, type=%s" % \
  580. (layer.name, layer.type))
  581. self.nvizClass.SetViewportDefault()
  582. def ResetView(self):
  583. """!Reset to default view"""
  584. self.view['z-exag']['value'], \
  585. self.iview['height']['value'], \
  586. self.iview['height']['min'], \
  587. self.iview['height']['max'] = self.nvizClass.SetViewDefault()
  588. self.view['pos']['x'] = UserSettings.Get(group='nviz', key='view',
  589. subkey=('pos', 'x'))
  590. self.view['pos']['y'] = UserSettings.Get(group='nviz', key='view',
  591. subkey=('pos', 'x'))
  592. self.view['persp']['value'] = UserSettings.Get(group='nviz', key='view',
  593. subkey=('persp', 'value'))
  594. self.view['twist']['value'] = UserSettings.Get(group='nviz', key='view',
  595. subkey=('twist', 'value'))
  596. event = wxUpdateView(zExag=False)
  597. wx.PostEvent(self, event)
  598. def UpdateMapObjProperties(self, event):
  599. """!Generic method to update data layer properties"""
  600. data = event.data
  601. if data.has_key('surface'):
  602. id = data['surface']['object']['id']
  603. self.UpdateSurfaceProperties(id, data['surface'])
  604. # -> initialized
  605. data['surface']['object']['init'] = True
  606. elif data.has_key('volume'):
  607. id = data['volume']['object']['id']
  608. self.UpdateVolumeProperties(id, data['volume'])
  609. # -> initialized
  610. data['volume']['object']['init'] = True
  611. elif data.has_key('vector'):
  612. for type in ('lines', 'points'):
  613. if data['vector'][type].has_key('object'):
  614. id = data['vector'][type]['object']['id']
  615. self.UpdateVectorProperties(id, data['vector'], type)
  616. # -> initialized
  617. data['vector'][type]['object']['init'] = True
  618. def UpdateSurfaceProperties(self, id, data):
  619. """!Update surface map object properties"""
  620. # surface attributes
  621. for attrb in ('topo', 'color', 'mask',
  622. 'transp', 'shine', 'emit'):
  623. if not data['attribute'].has_key(attrb) or \
  624. not data['attribute'][attrb].has_key('update'):
  625. continue
  626. map = data['attribute'][attrb]['map']
  627. value = data['attribute'][attrb]['value']
  628. if map is None: # unset
  629. # only optional attributes
  630. if attrb == 'mask':
  631. # TODO: invert mask
  632. # TODO: broken in NVIZ
  633. self.nvizClass.UnsetSurfaceMask(id)
  634. elif attrb == 'transp':
  635. self.nvizClass.UnsetSurfaceTransp(id)
  636. elif attrb == 'emit':
  637. self.nvizClass.UnsetSurfaceEmit(id)
  638. else:
  639. if type(value) == type('') and \
  640. len(value) <= 0: # ignore empty values (TODO: warning)
  641. continue
  642. if attrb == 'topo':
  643. self.nvizClass.SetSurfaceTopo(id, map, str(value))
  644. elif attrb == 'color':
  645. self.nvizClass.SetSurfaceColor(id, map, str(value))
  646. elif attrb == 'mask':
  647. # TODO: invert mask
  648. # TODO: broken in NVIZ
  649. self.nvizClass.SetSurfaceMask(id, False, str(value))
  650. elif attrb == 'transp':
  651. self.nvizClass.SetSurfaceTransp(id, map, str(value))
  652. elif attrb == 'shine':
  653. self.nvizClass.SetSurfaceShine(id, map, str(value))
  654. elif attrb == 'emit':
  655. self.nvizClass.SetSurfaceEmit(id, map, str(value))
  656. data['attribute'][attrb].pop('update')
  657. # draw res
  658. if data['draw']['resolution'].has_key('update'):
  659. coarse = data['draw']['resolution']['coarse']
  660. fine = data['draw']['resolution']['fine']
  661. if data['draw']['all']:
  662. self.nvizClass.SetSurfaceRes(-1, fine, coarse)
  663. else:
  664. self.nvizClass.SetSurfaceRes(id, fine, coarse)
  665. data['draw']['resolution'].pop('update')
  666. # draw style
  667. if data['draw']['mode'].has_key('update'):
  668. if data['draw']['mode']['value'] < 0: # need to calculate
  669. data['draw']['mode']['value'] = \
  670. self.nvizDefault.GetDrawMode(mode=data['draw']['mode']['desc']['mode'],
  671. style=data['draw']['mode']['desc']['style'],
  672. shade=data['draw']['mode']['desc']['shading'],
  673. string=True)
  674. style = data['draw']['mode']['value']
  675. if data['draw']['all']:
  676. self.nvizClass.SetSurfaceStyle(-1, style)
  677. else:
  678. self.nvizClass.SetSurfaceStyle(id, style)
  679. data['draw']['mode'].pop('update')
  680. # wire color
  681. if data['draw']['wire-color'].has_key('update'):
  682. color = data['draw']['wire-color']['value']
  683. if data['draw']['all']:
  684. self.nvizClass.SetWireColor(-1, str(color))
  685. else:
  686. self.nvizClass.SetWireColor(id, str(color))
  687. data['draw']['wire-color'].pop('update')
  688. # position
  689. if data['position'].has_key('update'):
  690. x = data['position']['x']
  691. y = data['position']['y']
  692. z = data['position']['z']
  693. self.nvizClass.SetSurfacePosition(id, x, y, z)
  694. data['position'].pop('update')
  695. def UpdateVolumeProperties(self, id, data, isosurfId=None):
  696. """!Update volume (isosurface/slice) map object properties"""
  697. #
  698. # draw
  699. #
  700. if data['draw']['resolution'].has_key('update'):
  701. self.nvizClass.SetIsosurfaceRes(id, data['draw']['resolution']['value'])
  702. data['draw']['resolution'].pop('update')
  703. if data['draw']['shading'].has_key('update'):
  704. if data['draw']['shading']['value'] < 0: # need to calculate
  705. data['draw']['shading']['value'] = \
  706. self.nvizDefault.GetDrawMode(shade=data['draw']['shading'],
  707. string=False)
  708. data['draw']['shading'].pop('update')
  709. #
  710. # isosurface attributes
  711. #
  712. isosurfId = 0
  713. for isosurf in data['isosurface']:
  714. for attrb in ('color', 'mask',
  715. 'transp', 'shine', 'emit'):
  716. if not isosurf.has_key(attrb) or \
  717. not isosurf[attrb].has_key('update'):
  718. continue
  719. map = isosurf[attrb]['map']
  720. value = isosurf[attrb]['value']
  721. if map is None: # unset
  722. # only optional attributes
  723. if attrb == 'mask':
  724. # TODO: invert mask
  725. # TODO: broken in NVIZ
  726. self.nvizClass.UnsetIsosurfaceMask(id, isosurfId)
  727. elif attrb == 'transp':
  728. self.nvizClass.UnsetIsosurfaceTransp(id, isosurfId)
  729. elif attrb == 'emit':
  730. self.nvizClass.UnsetIsosurfaceEmit(id, isosurfId)
  731. else:
  732. if type(value) == type('') and \
  733. len(value) <= 0: # ignore empty values (TODO: warning)
  734. continue
  735. elif attrb == 'color':
  736. self.nvizClass.SetIsosurfaceColor(id, isosurfId, map, str(value))
  737. elif attrb == 'mask':
  738. # TODO: invert mask
  739. # TODO: broken in NVIZ
  740. self.nvizClass.SetIsosurfaceMask(id, isosurfId, False, str(value))
  741. elif attrb == 'transp':
  742. self.nvizClass.SetIsosurfaceTransp(id, isosurfId, map, str(value))
  743. elif attrb == 'shine':
  744. self.nvizClass.SetIsosurfaceShine(id, isosurfId, map, str(value))
  745. elif attrb == 'emit':
  746. self.nvizClass.SetIsosurfaceEmit(id, isosurfId, map, str(value))
  747. isosurf[attrb].pop('update')
  748. isosurfId += 1
  749. def UpdateVectorProperties(self, id, data, type):
  750. """!Update vector layer properties
  751. @param id layer id
  752. @param data properties
  753. @param type lines/points
  754. """
  755. if type == 'points':
  756. self.UpdateVectorPointsProperties(id, data[type])
  757. else:
  758. self.UpdateVectorLinesProperties(id, data[type])
  759. def UpdateVectorLinesProperties(self, id, data):
  760. """!Update vector line map object properties"""
  761. # mode
  762. if data['color'].has_key('update') or \
  763. data['width'].has_key('update') or \
  764. data['mode'].has_key('update'):
  765. width = data['width']['value']
  766. color = data['color']['value']
  767. if data['mode']['type'] == 'flat':
  768. flat = True
  769. if data.has_key('surface'):
  770. data.pop('surface')
  771. else:
  772. flat = False
  773. self.nvizClass.SetVectorLineMode(id, color,
  774. width, flat)
  775. if data['color'].has_key('update'):
  776. data['color'].pop('update')
  777. if data['width'].has_key('update'):
  778. data['width'].pop('update')
  779. if data['mode'].has_key('update'):
  780. data['mode'].pop('update')
  781. # height
  782. if data['height'].has_key('update'):
  783. self.nvizClass.SetVectorLineHeight(id,
  784. data['height']['value'])
  785. data['height'].pop('update')
  786. # surface
  787. if data['mode'].has_key('update'):
  788. sid = self.GetLayerId(type='raster', name=data['mode']['surface'])
  789. if sid > -1:
  790. self.nvizClass.SetVectorLineSurface(id, sid)
  791. data['mode'].pop('update')
  792. def UpdateVectorPointsProperties(self, id, data):
  793. """!Update vector point map object properties"""
  794. if data['size'].has_key('update') or \
  795. data['width'].has_key('update') or \
  796. data['marker'].has_key('update') or \
  797. data['color'].has_key('update'):
  798. ret = self.nvizClass.SetVectorPointMode(id, data['color']['value'],
  799. data['width']['value'], float(data['size']['value']),
  800. data['marker']['value'] + 1)
  801. error = None
  802. if ret == -1:
  803. error = _("Vector point layer not found (id=%d)") % id
  804. elif ret == -2:
  805. error = _("Unable to set data layer properties (id=%d)") % id
  806. if error:
  807. raise gcmd.NvizError(parent=self.parent,
  808. message=_("Setting data layer properties failed.\n\n%s") % error)
  809. for prop in ('size', 'width', 'marker', 'color'):
  810. if data[prop].has_key('update'):
  811. data[prop].pop('update')
  812. # height
  813. if data['height'].has_key('update'):
  814. self.nvizClass.SetVectorPointHeight(id,
  815. data['height']['value'])
  816. data['height'].pop('update')
  817. # surface
  818. if data['mode'].has_key('update'):
  819. sid = self.GetLayerId(type='raster', name=data['mode']['surface'])
  820. if sid > -1:
  821. self.nvizClass.SetVectorPointSurface(id, sid)
  822. data['mode'].pop('update')
  823. def GetLayerNames(self, type):
  824. """!Return list of map layer names of given type"""
  825. layerName = []
  826. for item in self.layers:
  827. mapLayer = self.tree.GetPyData(item)[0]['maplayer']
  828. if type != mapLayer.GetType():
  829. continue
  830. layerName.append(mapLayer.GetName())
  831. return layerName
  832. def GetLayerData(self, type, name):
  833. """!Return layer item data
  834. @return {} if no layer item found
  835. """
  836. for item in self.layers:
  837. mapLayer = self.tree.GetPyData(item)[0]['maplayer'].GetName()
  838. if mapLayer == name:
  839. return self.tree.GetPyData(item)[0]['nviz']
  840. return {}
  841. def GetLayerId(self, type, name):
  842. """!Get layer object id or -1"""
  843. if len(name) < 1:
  844. return -1
  845. for item in self.layers:
  846. mapLayer = self.tree.GetPyData(item)[0]['maplayer']
  847. if type != mapLayer.GetType() or \
  848. name != mapLayer.GetName():
  849. continue
  850. data = self.tree.GetPyData(item)[0]['nviz']
  851. if type == 'raster':
  852. return data['surface']['object']['id']
  853. elif type == 'vpoint':
  854. return data['vector']['points']['object']['id']
  855. elif type == 'vline':
  856. return data['vector']['lines']['object']['id']
  857. elif type == '3d-raster':
  858. return data['volume']['object']['id']
  859. return -1