nviz_mapdisp.py 45 KB

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