nviz_mapdisp.py 44 KB

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