nviz_mapdisp.py 42 KB

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