nviz_mapdisp.py 45 KB

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