nviz.py 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189
  1. """
  2. @package nviz.py
  3. @brief 2.5/3D visialization mode for Map Display Window
  4. List of classes:
  5. - GLWindow
  6. - NvizToolWindow
  7. - ViewPositionWindow
  8. (C) 2008 by the GRASS Development Team
  9. This program is free software under the GNU General Public
  10. License (>=v2). Read the file COPYING that comes with GRASS
  11. for details.
  12. @author Martin Landa <landa.martin gmail.com> (Google SoC 2008)
  13. """
  14. import os
  15. import sys
  16. import time
  17. import copy
  18. from threading import Thread
  19. import wx
  20. import wx.lib.colourselect as csel
  21. import wx.lib.scrolledpanel as scrolled
  22. errorMsg = ''
  23. try:
  24. from wx import glcanvas
  25. haveGLCanvas = True
  26. except ImportError, e:
  27. haveGLCanvas = False
  28. errorMsg = e
  29. try:
  30. from OpenGL.GL import *
  31. from OpenGL.GLUT import *
  32. haveOpenGL = True
  33. except ImportError, e:
  34. haveOpenGL = False
  35. errorMsg = e
  36. import globalvar
  37. import gcmd
  38. import gselect
  39. from debug import Debug as Debug
  40. from mapdisp import MapWindow as MapWindow
  41. from preferences import globalSettings as UserSettings
  42. try:
  43. nvizPath = os.path.join(globalvar.ETCWXDIR, "nviz")
  44. sys.path.append(nvizPath)
  45. import grass7_wxnviz as wxnviz
  46. haveNviz = True
  47. except ImportError, e:
  48. haveNviz = False
  49. errorMsg = e
  50. class GLWindow(MapWindow, glcanvas.GLCanvas):
  51. """OpenGL canvas for Map Display Window"""
  52. def __init__(self, parent, id,
  53. pos=wx.DefaultPosition,
  54. size=wx.DefaultSize,
  55. style=wx.NO_FULL_REPAINT_ON_RESIZE,
  56. Map=None, tree=None, gismgr=None):
  57. self.parent = parent # MapFrame
  58. self.Map = Map
  59. self.tree = tree
  60. self.gismgr = gismgr
  61. glcanvas.GLCanvas.__init__(self, parent, id)
  62. MapWindow.__init__(self, parent, id, pos, size, style,
  63. Map, tree, gismgr)
  64. self.parent = parent # MapFrame
  65. self.init = False
  66. self.render = True # render in full resolution
  67. #
  68. # create nviz instance
  69. #
  70. self.nvizClass = wxnviz.Nviz()
  71. #
  72. # set current display
  73. #
  74. self.nvizClass.SetDisplay(self)
  75. #
  76. # initialize mouse position
  77. #
  78. self.lastX = self.x = 30
  79. self.lastY = self.y = 30
  80. #
  81. # default values
  82. #
  83. self.view = copy.deepcopy(UserSettings.Get(group='nviz', key='view')) # copy
  84. self.iview = UserSettings.Get(group='nviz', key='view', internal=True)
  85. self.update = [] # list of properties to be updated
  86. self.size = None
  87. self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
  88. self.Bind(wx.EVT_SIZE, self.OnSize)
  89. self.Bind(wx.EVT_PAINT, self.OnPaint)
  90. self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
  91. self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
  92. self.Bind(wx.EVT_MOTION, self.OnMouseAction)
  93. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseAction)
  94. def OnEraseBackground(self, event):
  95. pass # do nothing, to avoid flashing on MSW
  96. def OnSize(self, event):
  97. self.size = self.parent.GetClientSize()
  98. if self.GetContext():
  99. Debug.msg(3, "GLCanvas.OnPaint(): w=%d, h=%d" % \
  100. (self.size.width, self.size.height))
  101. self.SetCurrent()
  102. self.nvizClass.ResizeWindow(self.size.width,
  103. self.size.height)
  104. event.Skip()
  105. def OnPaint(self, event):
  106. Debug.msg(3, "GLCanvas.OnPaint()")
  107. dc = wx.PaintDC(self)
  108. self.SetCurrent()
  109. if not self.init:
  110. self.nvizClass.InitView()
  111. self.LoadDataLayers()
  112. self.ResetView()
  113. if hasattr(self.parent, "nvizToolWin"):
  114. self.parent.nvizToolWin.UpdatePage('view')
  115. layer = self.GetSelectedLayer()
  116. if layer:
  117. if layer.type == 'raster':
  118. self.parent.nvizToolWin.UpdatePage('surface')
  119. elif layer.type == 'vector':
  120. self.parent.nvizToolWin.UpdatePage('vector')
  121. self.parent.nvizToolWin.UpdateSettings()
  122. self.init = True
  123. self.UpdateMap()
  124. def OnMouseAction(self, event):
  125. # change position
  126. if event.Dragging() and event.LeftIsDown():
  127. self.lastX = self.lastY = self.x = self.y
  128. self.x, self.y = event.GetPosition()
  129. self.Refresh(False)
  130. # change perspective with mouse wheel
  131. wheel = event.GetWheelRotation()
  132. if wheel != 0:
  133. current = event.GetPositionTuple()[:]
  134. Debug.msg (5, "GLWindow.OnMouseMotion(): wheel=%d" % wheel)
  135. if wheel > 0:
  136. value = -1 * self.view['persp']['step']
  137. else:
  138. value = self.view['persp']['step']
  139. self.view['persp']['value'] += value
  140. if self.view['persp']['value'] < 1:
  141. self.view['persp']['value'] = 1
  142. elif self.view['persp']['value'] > 100:
  143. self.view['persp']['value'] = 100
  144. if hasattr(self.parent, "nvizToolWin"):
  145. self.parent.nvizToolWin.UpdateSettings()
  146. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  147. self.iview['height']['value'],
  148. self.view['persp']['value'],
  149. self.view['twist']['value'])
  150. # redraw map
  151. self.OnPaint(None)
  152. # update statusbar
  153. ### self.parent.StatusbarUpdate()
  154. def OnLeftDown(self, event):
  155. self.CaptureMouse()
  156. self.x, self.y = self.lastX, self.lastY = event.GetPosition()
  157. def OnLeftUp(self, event):
  158. self.ReleaseMouse()
  159. def UpdateMap(self, render=True):
  160. """
  161. Updates the canvas anytime there is a change to the
  162. underlaying images or to the geometry of the canvas.
  163. @param render re-render map composition
  164. """
  165. start = time.clock()
  166. self.resize = False
  167. # if self.size is None:
  168. # self.size = self.GetClientSize()
  169. # w, h = self.size
  170. # w = float(max(w, 1.0))
  171. # h = float(max(h, 1.0))
  172. # d = float(min(w, h))
  173. # xScale = d / w
  174. # yScale = d / h
  175. # print w, h, d, xScale, yScale
  176. # print self.y, self.lastY, self.x, self.lastX
  177. # print (self.y - self.lastY) * yScale, (self.x - self.lastX) * xScale
  178. # print self.x * xScale
  179. #glRotatef((self.y - self.lastY) * yScale, 1.0, 0.0, 0.0);
  180. #glRotatef((self.x - self.lastX) * xScale, 0.0, 1.0, 0.0);
  181. if self.render:
  182. self.parent.onRenderGauge.Show()
  183. self.parent.onRenderGauge.SetRange(2)
  184. self.parent.onRenderGauge.SetValue(0)
  185. if 'view' in self.update:
  186. if 'z-exag' in self.update:
  187. self.nvizClass.SetZExag(self.view['z-exag']['value'])
  188. self.update.remove('z-exag')
  189. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  190. self.iview['height']['value'],
  191. self.view['persp']['value'],
  192. self.view['twist']['value'])
  193. self.update.remove('view')
  194. if self.render is True:
  195. self.parent.onRenderGauge.SetValue(1)
  196. wx.Yield()
  197. self.nvizClass.Draw(False)
  198. else:
  199. self.nvizClass.Draw(True) # quick
  200. self.SwapBuffers()
  201. stop = time.clock()
  202. if self.render:
  203. self.parent.onRenderGauge.SetValue(2)
  204. # hide process bar
  205. self.parent.onRenderGauge.Hide()
  206. #
  207. # update statusbar
  208. #
  209. # self.parent.StatusbarUpdate()
  210. Debug.msg(3, "GLWindow.UpdateMap(): render=%s, -> time=%g" % \
  211. (self.render, (stop-start)))
  212. def EraseMap(self):
  213. """
  214. Erase the canvas
  215. """
  216. self.nvizClass.EraseMap()
  217. self.SwapBuffers()
  218. def IsLoaded(self, layer):
  219. """Check if layer is already loaded"""
  220. data = self.tree.GetPyData(layer)[0]['nviz']
  221. if not data or not data.has_key('object'):
  222. return 0
  223. return 1
  224. def LoadDataLayers(self):
  225. """Load raster/vector from current layer tree
  226. @todo volumes
  227. """
  228. listOfItems = []
  229. # load raster & vector maps
  230. item = self.tree.GetFirstChild(self.tree.root)[0]
  231. while item and item.IsOk():
  232. type = self.tree.GetPyData(item)[0]['type']
  233. if type not in ('raster', 'vector'):
  234. continue
  235. listOfItems.append(item)
  236. item = self.tree.GetNextSibling(item)
  237. while(len(listOfItems) > 0):
  238. item = listOfItems.pop()
  239. type = self.tree.GetPyData(item)[0]['type']
  240. mapLayer = self.tree.GetPyData(item)[0]['maplayer']
  241. data = self.tree.GetPyData(item)[0]['nviz']
  242. if type == 'raster':
  243. id = self.LoadRaster(mapLayer)
  244. elif type == 'vector':
  245. id = self.LoadVector(mapLayer)
  246. if type == 'raster' or type == 'vector':
  247. # init layer data properties
  248. if data is None:
  249. self.tree.GetPyData(item)[0]['nviz'] = {}
  250. data = self.tree.GetPyData(item)[0]['nviz']
  251. if type == 'raster':
  252. data['surface'] = {}
  253. for sec in ('attribute', 'draw', 'mask', 'position'):
  254. data['surface'][sec] = {}
  255. self.SetSurfaceDefaultProp(data['surface'])
  256. elif type == 'vector':
  257. data['vector'] = {}
  258. for sec in ('lines', ):
  259. data['vector'][sec] = {}
  260. self.SetVectorDefaultProp(data['vector'])
  261. # set updates
  262. else:
  263. for sec in data.keys():
  264. for sec1 in data[sec].keys():
  265. for sec2 in data[sec][sec1].keys():
  266. self.update.append('%s:%s:%s' % (sec, sec1, sec2))
  267. # associate with map object id
  268. if not data.has_key('object'):
  269. data['object'] = { 'id' : id,
  270. 'init' : False }
  271. if not data.has_key('view'):
  272. data['view'] = None
  273. self.UpdateLayerProperties(item)
  274. def LoadRaster(self, layer):
  275. """Load raster map -> surface"""
  276. if layer.type != 'raster':
  277. return
  278. id = self.nvizClass.LoadSurface(str(layer.name), None, None)
  279. if id < 0:
  280. raise gcmd.NvizError(parent=self.parent,
  281. message=_("Unable to load raster map <%s>" % layer.name))
  282. return id
  283. def UnloadRaster(self, id):
  284. """Unload raster map"""
  285. if self.nvizClass.UnloadSurface(id) == 0:
  286. raise gcmd.NvizError(parent=self.parent,
  287. message=_("Unable to unload raster map <%s>" % layer.name))
  288. def GetSurfaceMode(self, mode, style, shade):
  289. """Determine surface draw mode"""
  290. value = 0
  291. desc = {}
  292. if mode == 0: # coarse
  293. value |= wxnviz.DM_WIRE
  294. desc['mode'] = 'coarse'
  295. elif mode == 1: # fine
  296. value |= wxnviz.DM_POLY
  297. desc['mode'] = 'fine'
  298. else: # both
  299. value |= wxnviz.DM_WIRE_POLY
  300. desc['mode'] = 'both'
  301. if style == 0: # wire
  302. value |= wxnviz.DM_GRID_WIRE
  303. desc['style'] = 'wire'
  304. else: # surface
  305. value |= wxnviz.DM_GRID_SURF
  306. desc['style'] = 'surface'
  307. if shade == 0:
  308. value |= wxnviz.DM_FLAT
  309. desc['shading'] = 'flat'
  310. else: # surface
  311. value |= wxnviz.DM_GOURAUD
  312. desc['shading'] = 'gouraud'
  313. return (value, desc)
  314. def SetSurfaceDefaultProp(self, data):
  315. """Set default surface properties"""
  316. #
  317. # attributes
  318. #
  319. data['attribute']['shine'] = {}
  320. data['attribute']['shine']['map'] = \
  321. UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'map'])
  322. data['attribute']['shine']['value'] = \
  323. UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'value'])
  324. self.update.append('surface:attribute:shine')
  325. #
  326. # draw
  327. #
  328. for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
  329. if control[:3] == 'res':
  330. if 'surface:draw:%s' % 'resolution' not in self.update:
  331. self.update.append('surface:draw:%s' % 'resolution')
  332. data['draw']['resolution'] = { 'all' : False,
  333. control[4:] : value }
  334. else:
  335. data['draw']['resolution'][control[4:]] = value
  336. continue
  337. else:
  338. self.update.append('surface:draw:%s' % control)
  339. if control == 'wire-color':
  340. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  341. elif control in ('mode', 'style', 'shading'):
  342. if not data['draw'].has_key('mode'):
  343. data['draw']['mode'] = {}
  344. continue
  345. data['draw'][control] = { 'value' : value,
  346. 'all' : False }
  347. value, desc = self.GetSurfaceMode(UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'mode']),
  348. UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'style']),
  349. UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading']))
  350. data['draw']['mode'] = { 'value' : value,
  351. 'desc' : desc,
  352. 'all' : False }
  353. def LoadVector(self, layer):
  354. """Load vector map overlay"""
  355. if layer.type != 'vector':
  356. return
  357. id = self.nvizClass.LoadVector(str(layer.name))
  358. if id < 0:
  359. raise gcmd.NvizError(parent=self.parent,
  360. message=_("Unable to load vector map <%s>" % layer.name))
  361. return id
  362. def UnloadVector(self, id):
  363. """Unload vector map overlay"""
  364. if self.nvizClass.UnloadVector(id) == 0:
  365. raise gcmd.NvizError(parent=self.parent,
  366. message=_("Unable to unload vector map <%s>" % layer.name))
  367. def SetVectorDefaultProp(self, data):
  368. """Set default vector properties"""
  369. #
  370. # lines
  371. #
  372. # width
  373. data['lines']['width'] = \
  374. UserSettings.Get(group='nviz', key='vector',
  375. subkey=['lines', 'width'])
  376. self.update.append('vector:lines:width')
  377. # color
  378. value = UserSettings.Get(group='nviz', key='vector',
  379. subkey=['lines', 'color'])
  380. color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  381. data['lines']['color'] = color
  382. self.update.append('vector:lines:color')
  383. # mode
  384. if UserSettings.Get(group='nviz', key='vector',
  385. subkey=['lines', 'flat']):
  386. type = 'flat'
  387. map = None
  388. else:
  389. type = 'surface'
  390. map = '' # TODO
  391. data['lines']['mode'] = {}
  392. data['lines']['mode']['type'] = type
  393. if map:
  394. data['lines']['mode']['map'] = map
  395. self.update.append('vector:lines:mode')
  396. # height
  397. data['lines']['height'] = UserSettings.Get(group='nviz', key='vector',
  398. subkey=['lines', 'height'])
  399. self.update.append('vector:lines:height')
  400. def Reset(self):
  401. """Reset (unload data)"""
  402. self.nvizClass.Reset()
  403. self.init = False
  404. def OnZoomToMap(self, event):
  405. """
  406. Set display extents to match selected raster
  407. or vector map or volume.
  408. @todo vector, volume
  409. """
  410. layer = self.GetSelectedLayer()
  411. if layer is None:
  412. return
  413. Debug.msg (3, "GLWindow.OnZoomToMap(): layer=%s, type=%s" % \
  414. (layer.name, layer.type))
  415. self.nvizClass.SetViewportDefault()
  416. def ResetView(self):
  417. """Reset to default view"""
  418. self.view['z-exag']['value'], \
  419. self.iview['height']['value'] = self.nvizClass.SetViewDefault()
  420. self.view['pos']['x'] = UserSettings.Get(group='nviz', key='view',
  421. subkey=('pos', 'x'))
  422. self.view['pos']['y'] = UserSettings.Get(group='nviz', key='view',
  423. subkey=('pos', 'x'))
  424. self.view['persp']['value'] = UserSettings.Get(group='nviz', key='view',
  425. subkey=('persp', 'value'))
  426. self.view['twist']['value'] = UserSettings.Get(group='nviz', key='view',
  427. subkey=('twist', 'value'))
  428. self.update.append('view')
  429. def UpdateLayerProperties(self, layer=None):
  430. """Update data layer properties
  431. @param layer layer item or None (for selected item)
  432. """
  433. if not layer:
  434. mapLayer = self.GetSelectedLayer()
  435. data = self.GetSelectedLayer(nviz=True)
  436. else:
  437. mapLayer = self.tree.GetPyData(layer)[0]['maplayer']
  438. data = self.tree.GetPyData(layer)[0]['nviz']
  439. id = data['object']['id']
  440. if mapLayer.type == 'raster':
  441. self.UpdateRasterProperties(id, data['surface'])
  442. elif mapLayer.type == 'vector':
  443. self.UpdateVectorProperties(id, data['vector'])
  444. # -> initialized
  445. data['object']['init'] = True
  446. def UpdateRasterProperties(self, id, data):
  447. """Apply changes for surfaces"""
  448. # surface attributes
  449. for attrb in ('topo', 'color', 'mask',
  450. 'transp', 'shine', 'emit'):
  451. if 'surface:attribute:%s' % attrb in self.update:
  452. map = data['attribute'][attrb]['map']
  453. value = data['attribute'][attrb]['value']
  454. if map is None: # unset
  455. # only optional attributes
  456. if attrb == 'mask':
  457. # TODO: invert mask
  458. # TODO: broken in NVIZ
  459. self.nvizClass.UnsetSurfaceMask(id)
  460. elif attrb == 'transp':
  461. self.nvizClass.UnsetSurfaceTransp(id)
  462. elif attrb == 'emit':
  463. self.nvizClass.UnsetSurfaceEmit(id)
  464. else:
  465. if type(value) == type('') and \
  466. len(value) <= 0: # ignore empty values (TODO: warning)
  467. continue
  468. if attrb == 'topo':
  469. self.nvizClass.SetSurfaceTopo(id, map, str(value))
  470. elif attrb == 'color':
  471. self.nvizClass.SetSurfaceColor(id, map, str(value))
  472. elif attrb == 'mask':
  473. # TODO: invert mask
  474. # TODO: broken in NVIZ
  475. self.nvizClass.SetSurfaceMask(id, False, str(value))
  476. elif attrb == 'transp':
  477. self.nvizClass.SetSurfaceTransp(id, map, str(value))
  478. elif attrb == 'shine':
  479. self.nvizClass.SetSurfaceShine(id, map, str(value))
  480. elif attrb == 'emit':
  481. self.nvizClass.SetSurfaceEmit(id, map, str(value))
  482. self.update.remove('surface:attribute:%s' % attrb)
  483. # draw res
  484. if 'surface:draw:resolution' in self.update:
  485. coarse = data['draw']['resolution']['coarse']
  486. fine = data['draw']['resolution']['fine']
  487. if data['draw']['resolution']['all']:
  488. self.nvizClass.SetSurfaceRes(-1, fine, coarse)
  489. else:
  490. self.nvizClass.SetSurfaceRes(id, fine, coarse)
  491. self.update.remove('surface:draw:resolution')
  492. # draw style
  493. if 'surface:draw:mode' in self.update:
  494. style = data['draw']['mode']['value']
  495. if data['draw']['mode']['all']:
  496. self.nvizClass.SetSurfaceStyle(-1, style)
  497. else:
  498. self.nvizClass.SetSurfaceStyle(id, style)
  499. self.update.remove('surface:draw:mode')
  500. # wire color
  501. if 'surface:draw:wire-color' in self.update:
  502. color = data['draw']['wire-color']['value']
  503. if data['draw']['wire-color']['all']:
  504. self.nvizClass.SetWireColor(-1, str(color))
  505. else:
  506. self.nvizClass.SetWireColor(id, str(color))
  507. self.update.remove('surface:draw:wire-color')
  508. # position
  509. if 'surface:position' in self.update:
  510. x = data['surface']['position']['x']
  511. y = data['surface']['position']['y']
  512. z = data['surface']['position']['z']
  513. self.nvizClass.SetSurfacePosition(id, x, y, z)
  514. self.update.remove('surface:position')
  515. def UpdateVectorProperties(self, id, data):
  516. """Apply changes for vector"""
  517. if 'vector:lines:mode' in self.update:
  518. width = data['lines']['width']
  519. color = data['lines']['color']
  520. if data['lines']['mode']['type'] == 'flat':
  521. flat = True
  522. else:
  523. flat = False
  524. self.nvizClass.SetVectorLineMode(id, color,
  525. width, flat)
  526. self.update.remove('vector:lines:mode')
  527. if 'vector:lines:height' in self.update:
  528. self.nvizClass.SetVectorHeight(id,
  529. data['lines']['height'])
  530. self.update.remove('vector:lines:height')
  531. class NvizToolWindow(wx.Frame):
  532. """Experimental window for Nviz tools
  533. @todo integrate with Map display
  534. """
  535. def __init__(self, parent=None, id=wx.ID_ANY, title=_("Nviz tools"),
  536. pos=wx.DefaultPosition, size=wx.DefaultSize,
  537. style=wx.DEFAULT_FRAME_STYLE, mapWindow=None):
  538. self.parent = parent # MapFrame
  539. self.lmgr = self.parent.gismanager # GMFrame
  540. self.mapWindow = mapWindow
  541. wx.Frame.__init__(self, parent, id, title, pos, size, style)
  542. #
  543. # icon
  544. #
  545. self.SetIcon(wx.Icon(os.path.join(globalvar.ETCDIR, 'grass_nviz.ico'), wx.BITMAP_TYPE_ICO))
  546. #
  547. # dialog body
  548. #
  549. mainSizer = wx.BoxSizer(wx.VERTICAL)
  550. self.win = {} # window ids
  551. #
  552. # notebook
  553. #
  554. self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
  555. self.page = {}
  556. # view page
  557. self.__createViewPage()
  558. self.page['view'] = 0
  559. # surface page
  560. self.__createSurfacePage()
  561. self.page['surface'] = 1
  562. # vector page
  563. self.__createVectorPage()
  564. self.page['vector'] = 2
  565. # settings page
  566. self.__createSettingsPage()
  567. self.page['settings'] = 3
  568. self.UpdatePage('settings')
  569. self.pageChanging = False
  570. mainSizer.Add(item=self.notebook, proportion=1,
  571. flag=wx.EXPAND | wx.ALL, border=5)
  572. #
  573. # bindings
  574. #
  575. self.Bind(wx.EVT_CLOSE, self.OnClose)
  576. #
  577. # layout
  578. #
  579. self.SetSizer(mainSizer)
  580. mainSizer.Fit(self)
  581. def __createViewPage(self):
  582. """Create view settings page"""
  583. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  584. self.notebook.AddPage(page=panel,
  585. text=" %s " % _("View"))
  586. pageSizer = wx.BoxSizer(wx.VERTICAL)
  587. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  588. self.win['view'] = {}
  589. # position
  590. posSizer = wx.GridBagSizer(vgap=3, hgap=3)
  591. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("W")),
  592. pos=(1, 0), flag=wx.ALIGN_CENTER)
  593. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("N")),
  594. pos=(0, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM)
  595. viewPos = ViewPositionWindow(panel, id=wx.ID_ANY, size=(175, 175),
  596. mapwindow=self.mapWindow)
  597. self.win['view']['pos'] = viewPos.GetId()
  598. posSizer.Add(item=viewPos,
  599. pos=(1, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL)
  600. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("S")),
  601. pos=(2, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_TOP)
  602. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("E")),
  603. pos=(1, 2), flag=wx.ALIGN_CENTER)
  604. gridSizer.Add(item=posSizer, pos=(0, 0))
  605. # perspective
  606. range = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
  607. self.CreateControl(panel, dict=self.win['view'], name='persp',
  608. range=(range['min'], range['max']),
  609. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  610. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Perspective:")),
  611. pos=(1, 0), flag=wx.ALIGN_CENTER)
  612. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['slider']), pos=(2, 0))
  613. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['spin']), pos=(3, 0),
  614. flag=wx.ALIGN_CENTER)
  615. # twist
  616. range = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
  617. self.CreateControl(panel, dict=self.win['view'], name='twist',
  618. range=(range['min'], range['max']),
  619. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  620. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Twist:")),
  621. pos=(1, 1), flag=wx.ALIGN_CENTER)
  622. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['slider']), pos=(2, 1))
  623. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['spin']), pos=(3, 1),
  624. flag=wx.ALIGN_CENTER)
  625. # height + z-exag
  626. self.CreateControl(panel, dict=self.win['view'], name='height', sliderHor=False,
  627. range=(self.mapWindow.view['height']['min'], self.mapWindow.view['height']['max']),
  628. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  629. self.CreateControl(panel, dict=self.win['view'], name='z-exag', sliderHor=False,
  630. range=(0, 1),
  631. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  632. heightSizer = wx.GridBagSizer(vgap=3, hgap=3)
  633. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Height:")),
  634. pos=(0, 0), flag=wx.ALIGN_LEFT, span=(1, 2))
  635. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['slider']),
  636. flag=wx.ALIGN_RIGHT, pos=(1, 0))
  637. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['spin']),
  638. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  639. wx.BOTTOM | wx.RIGHT, pos=(1, 1))
  640. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Z-exag:")),
  641. pos=(0, 2), flag=wx.ALIGN_LEFT, span=(1, 2))
  642. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['slider']),
  643. flag=wx.ALIGN_RIGHT, pos=(1, 2))
  644. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['spin']),
  645. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  646. wx.BOTTOM | wx.RIGHT, pos=(1, 3))
  647. gridSizer.Add(item=heightSizer, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  648. # view setup + reset
  649. viewSizer = wx.BoxSizer(wx.HORIZONTAL)
  650. viewSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY,
  651. label=_("Look at:")),
  652. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
  653. viewType = wx.Choice (parent=panel, id=wx.ID_ANY, size=(125, -1),
  654. choices = [_("top"),
  655. _("north"),
  656. _("south"),
  657. _("east"),
  658. _("west"),
  659. _("north-west"),
  660. _("north-east"),
  661. _("south-east"),
  662. _("south-west")])
  663. viewType.SetSelection(0)
  664. viewType.Bind(wx.EVT_CHOICE, self.OnLookAt)
  665. # self.win['lookAt'] = viewType.GetId()
  666. viewSizer.Add(item=viewType, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
  667. border=5)
  668. reset = wx.Button(panel, id=wx.ID_ANY, label=_("Reset"))
  669. reset.SetToolTipString(_("Reset to default view"))
  670. # self.win['reset'] = reset.GetId()
  671. reset.Bind(wx.EVT_BUTTON, self.OnResetView)
  672. viewSizer.Add(item=reset, proportion=1,
  673. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT,
  674. border=5)
  675. gridSizer.AddGrowableCol(3)
  676. gridSizer.Add(item=viewSizer, pos=(4, 0), span=(1, 2),
  677. flag=wx.EXPAND)
  678. # body
  679. pageSizer.Add(item=gridSizer, proportion=1,
  680. flag=wx.EXPAND | wx.ALL,
  681. border=5)
  682. panel.SetSizer(pageSizer)
  683. def __createSurfacePage(self):
  684. """Create view settings page"""
  685. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  686. # panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY)
  687. # panel.SetupScrolling(scroll_x=True, scroll_y=True)
  688. self.notebook.AddPage(page=panel,
  689. text=" %s " % _("Surface"))
  690. pageSizer = wx.BoxSizer(wx.VERTICAL)
  691. self.win['surface'] = {}
  692. #
  693. # surface attributes
  694. #
  695. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  696. label=" %s " % (_("Surface attributes")))
  697. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  698. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  699. # labels
  700. # col = 0
  701. # for type in (_("Attribute"),
  702. # _("Use"),
  703. # _("Map"),
  704. # _("Constant")):
  705. # gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  706. # label=type),
  707. # pos=(0, col))
  708. # col += 1
  709. # type
  710. self.win['surface']['attr'] = {}
  711. row = 0
  712. for code, attrb in (('topo', _("Topography")),
  713. ('color', _("Color")),
  714. ('mask', _("Mask")),
  715. ('transp', _("Transparency")),
  716. ('shine', _("Shininess")),
  717. ('emit', _("Emission"))):
  718. self.win['surface'][code] = {}
  719. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  720. label=attrb + ':'),
  721. pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  722. use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  723. choices = [_("map")])
  724. if code not in ('topo', 'color', 'shine'):
  725. use.Insert(item=_("unset"), pos=0)
  726. self.win['surface'][code]['required'] = False
  727. else:
  728. self.win['surface'][code]['required'] = True
  729. if code != 'mask':
  730. use.Append(item=_('constant'))
  731. self.win['surface'][code]['use'] = use.GetId()
  732. use.Bind(wx.EVT_CHOICE, self.OnSurfaceUse)
  733. gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
  734. pos=(row, 1))
  735. map = gselect.Select(parent=panel, id=wx.ID_ANY,
  736. # size=globalvar.DIALOG_GSELECT_SIZE,
  737. size=(200, -1),
  738. type="raster")
  739. self.win['surface'][code]['map'] = map.GetId() - 1 # FIXME
  740. map.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  741. # changing map topography not allowed
  742. if code == 'topo':
  743. map.Enable(False)
  744. gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
  745. pos=(row, 2))
  746. if code == 'color':
  747. value = csel.ColourSelect(panel, id=wx.ID_ANY,
  748. colour=UserSettings.Get(group='nviz', key='surface',
  749. subkey=['color', 'value']))
  750. value.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceMap)
  751. elif code == 'mask':
  752. value = None
  753. else:
  754. value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  755. initial=0)
  756. if code == 'topo':
  757. value.SetRange(minVal=-1e9, maxVal=1e9)
  758. elif code in ('shine', 'transp', 'emit'):
  759. value.SetRange(minVal=0, maxVal=255)
  760. else:
  761. value.SetRange(minVal=0, maxVal=100)
  762. value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  763. if value:
  764. self.win['surface'][code]['const'] = value.GetId()
  765. value.Enable(False)
  766. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  767. pos=(row, 3))
  768. else:
  769. self.win['surface'][code]['const'] = None
  770. self.SetSurfaceUseMap(code) # -> enable map / disable constant
  771. row += 1
  772. boxSizer.Add(item=gridSizer, proportion=1,
  773. flag=wx.ALL | wx.EXPAND, border=3)
  774. pageSizer.Add(item=boxSizer, proportion=0,
  775. flag=wx.EXPAND | wx.ALL,
  776. border=5)
  777. #
  778. # draw
  779. #
  780. self.win['surface']['draw'] = {}
  781. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  782. label=" %s " % (_("Draw")))
  783. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  784. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  785. gridSizer.AddGrowableCol(4)
  786. # mode
  787. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  788. label=_("Mode:")),
  789. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  790. mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  791. choices = [_("coarse"),
  792. _("fine"),
  793. _("both")])
  794. mode.SetName("selection")
  795. mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  796. self.win['surface']['draw']['mode'] = mode.GetId()
  797. gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
  798. pos=(0, 1))
  799. # resolution (mode)
  800. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  801. label=_("Resolution:")),
  802. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  803. resSizer = wx.BoxSizer(wx.HORIZONTAL)
  804. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  805. label=_("coarse:")),
  806. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  807. resC = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  808. initial=1,
  809. min=1,
  810. max=100)
  811. resC.SetName("value")
  812. self.win['surface']['draw']['res-coarse'] = resC.GetId()
  813. resC.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  814. resSizer.Add(item=resC, flag=wx.ALL, border=3)
  815. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  816. label=_("fine:")),
  817. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  818. resF = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  819. initial=1,
  820. min=1,
  821. max=100)
  822. resF.SetName("value")
  823. self.win['surface']['draw']['res-fine'] = resF.GetId()
  824. resF.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  825. resSizer.Add(item=resF, flag=wx.ALL, border=3)
  826. gridSizer.Add(item=resSizer, pos=(0, 3), span=(1, 2))
  827. # style
  828. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  829. label=_("Coarse style:")),
  830. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  831. style = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  832. choices = [_("wire"),
  833. _("surface")])
  834. style.SetName("selection")
  835. self.win['surface']['draw']['style'] = style.GetId()
  836. style.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  837. gridSizer.Add(item=style, flag=wx.ALIGN_CENTER_VERTICAL,
  838. pos=(1, 1))
  839. # shading
  840. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  841. label=_("Shading:")),
  842. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  843. shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  844. choices = [_("flat"),
  845. _("gouraud")])
  846. shade.SetName("selection")
  847. self.win['surface']['draw']['shading'] = shade.GetId()
  848. shade.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  849. gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
  850. pos=(1, 3))
  851. # color
  852. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  853. label=_("Wire color:")),
  854. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  855. color = csel.ColourSelect(panel, id=wx.ID_ANY)
  856. color.SetName("colour")
  857. color.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceWireColor)
  858. self.win['surface']['draw']['wire-color'] = color.GetId()
  859. gridSizer.Add(item=color, flag=wx.ALIGN_CENTER_VERTICAL,
  860. pos=(2, 1))
  861. boxSizer.Add(item=gridSizer, proportion=1,
  862. flag=wx.ALL | wx.EXPAND, border=3)
  863. pageSizer.Add(item=boxSizer, proportion=0,
  864. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  865. border=5)
  866. all = wx.Button(panel, id=wx.ID_ANY, label=_("All"))
  867. all.SetToolTipString(_("Use for all loaded surfaces"))
  868. # self.win['reset'] = reset.GetId()
  869. all.Bind(wx.EVT_BUTTON, self.OnSurfaceModeAll)
  870. gridSizer.Add(item=all, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
  871. pos=(2, 4))
  872. #
  873. # mask
  874. #
  875. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  876. label=" %s " % (_("Mask")))
  877. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  878. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  879. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  880. label=_("Mask zeros:")),
  881. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  882. elev = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  883. label=_("by elevation"))
  884. elev.Enable(False) # TODO: not implemented yet
  885. gridSizer.Add(item=elev, pos=(0, 1))
  886. color = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  887. label=_("by color"))
  888. color.Enable(False) # TODO: not implemented yet
  889. gridSizer.Add(item=color, pos=(0, 2))
  890. boxSizer.Add(item=gridSizer, proportion=1,
  891. flag=wx.ALL | wx.EXPAND, border=3)
  892. pageSizer.Add(item=boxSizer, proportion=0,
  893. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  894. border=5)
  895. #
  896. # position
  897. #
  898. self.win['surface']['position'] = {}
  899. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  900. label=" %s " % (_("Position")))
  901. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  902. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  903. # position
  904. axis = wx.Choice (parent=panel, id=wx.ID_ANY, size=(75, -1),
  905. choices = ["X",
  906. "Y",
  907. "Z"])
  908. axis.SetSelection(0)
  909. self.win['surface']['position']['axis'] = axis.GetId()
  910. axis.Bind(wx.EVT_CHOICE, self.OnSurfaceAxis)
  911. gridSizer.Add(item=axis, flag=wx.ALIGN_CENTER_VERTICAL,
  912. pos=(0, 0))
  913. value = wx.Slider(parent=panel, id=wx.ID_ANY,
  914. value=0,
  915. minValue=-1e4,
  916. maxValue=1e4,
  917. style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  918. wx.SL_TOP | wx.SL_LABELS,
  919. size=(350, -1))
  920. self.win['surface']['position']['pos'] = value.GetId()
  921. value.Bind(wx.EVT_SCROLL, self.OnSurfacePosition)
  922. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  923. pos=(0, 1))
  924. boxSizer.Add(item=gridSizer, proportion=1,
  925. flag=wx.ALL | wx.EXPAND, border=3)
  926. pageSizer.Add(item=boxSizer, proportion=0,
  927. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  928. border=5)
  929. panel.SetSizer(pageSizer)
  930. def __createVectorPage(self):
  931. """Create view settings page"""
  932. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  933. self.notebook.AddPage(page=panel,
  934. text=" %s " % _("Vector"))
  935. pageSizer = wx.BoxSizer(wx.VERTICAL)
  936. self.win['vector'] = {}
  937. #
  938. # vector lines
  939. #
  940. self.win['vector']['lines'] = {}
  941. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  942. label=" %s " % (_("Vector lines")))
  943. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  944. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  945. # width
  946. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  947. label=_("Width:")),
  948. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  949. width = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  950. initial=1,
  951. min=1,
  952. max=100)
  953. self.win['vector']['lines']['width'] = width.GetId()
  954. width.Bind(wx.EVT_SPINCTRL, self.OnVectorLines)
  955. gridSizer.Add(item=width, pos=(0, 1),
  956. flag=wx.ALIGN_CENTER_VERTICAL)
  957. gridSizer.AddGrowableCol(2)
  958. # color
  959. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  960. label=_("Color:")),
  961. pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL)
  962. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  963. colour=UserSettings.Get(group='nviz', key='vector',
  964. subkey=['lines', 'color']))
  965. self.win['vector']['lines']['color'] = color.GetId()
  966. color.Bind(csel.EVT_COLOURSELECT, self.OnVectorLines)
  967. gridSizer.Add(item=color, pos=(0, 4))
  968. gridSizer.AddGrowableCol(5)
  969. # display
  970. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  971. label=_("Display:")),
  972. pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
  973. display = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  974. choices = [_("on surface"),
  975. _("flat")])
  976. self.win['vector']['lines']['flat'] = display.GetId()
  977. display.Bind(wx.EVT_CHOICE, self.OnVectorDisplay)
  978. gridSizer.Add(item=display, flag=wx.ALIGN_CENTER_VERTICAL,
  979. pos=(0, 7))
  980. surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
  981. style=wx.CB_SIMPLE | wx.CB_READONLY,
  982. choices=[])
  983. self.win['vector']['lines']['surface'] = surface.GetId()
  984. gridSizer.Add(item=surface,
  985. pos=(1, 0), span=(1, 8),
  986. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
  987. # high
  988. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  989. label=_("Hight above surface:")),
  990. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL,
  991. span=(1, 2))
  992. self.CreateControl(panel, dict=self.win['vector']['lines'], name='height', size=300,
  993. range=(0, 1000),
  994. bind=(self.OnVectorHeight, self.OnVectorHeight, self.OnVectorHeight))
  995. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['slider']),
  996. pos=(2, 2), span=(1, 6))
  997. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['spin']),
  998. pos=(3, 4),
  999. flag=wx.ALIGN_CENTER)
  1000. boxSizer.Add(item=gridSizer, proportion=1,
  1001. flag=wx.ALL | wx.EXPAND, border=3)
  1002. pageSizer.Add(item=boxSizer, proportion=0,
  1003. flag=wx.EXPAND | wx.ALL,
  1004. border=5)
  1005. panel.SetSizer(pageSizer)
  1006. def __createSettingsPage(self):
  1007. """Create settings page"""
  1008. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  1009. self.notebook.AddPage(page=panel,
  1010. text=" %s " % _("Settings"))
  1011. pageSizer = wx.BoxSizer(wx.VERTICAL)
  1012. self.win['settings'] = {}
  1013. #
  1014. # general
  1015. #
  1016. self.win['settings']['general'] = {}
  1017. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1018. label=" %s " % (_("General")))
  1019. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1020. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1021. # background color
  1022. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1023. label=_("Background color:")),
  1024. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1025. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  1026. colour=UserSettings.Get(group='nviz', key='settings',
  1027. subkey=['general', 'bgcolor']))
  1028. self.win['settings']['general']['bgcolor'] = color.GetId()
  1029. color.Bind(csel.EVT_COLOURSELECT, self.OnBgColor)
  1030. gridSizer.Add(item=color, pos=(0, 1))
  1031. boxSizer.Add(item=gridSizer, proportion=1,
  1032. flag=wx.ALL | wx.EXPAND, border=3)
  1033. pageSizer.Add(item=boxSizer, proportion=0,
  1034. flag=wx.EXPAND | wx.ALL,
  1035. border=5)
  1036. #
  1037. # view
  1038. #
  1039. self.win['settings']['view'] = {}
  1040. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1041. label=" %s " % (_("View")))
  1042. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1043. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1044. # perspective
  1045. self.win['settings']['view']['persp'] = {}
  1046. pvals = UserSettings.Get(group='nviz', key='view', subkey='persp')
  1047. ipvals = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
  1048. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1049. label=_("Perspective (value):")),
  1050. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1051. pval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1052. initial=pvals['value'],
  1053. min=ipvals['min'],
  1054. max=ipvals['max'])
  1055. self.win['settings']['view']['persp']['value'] = pval.GetId()
  1056. gridSizer.Add(item=pval, pos=(0, 1),
  1057. flag=wx.ALIGN_CENTER_VERTICAL)
  1058. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1059. label=_("(step):")),
  1060. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1061. pstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1062. initial=pvals['step'],
  1063. min=ipvals['min'],
  1064. max=ipvals['max']-1)
  1065. self.win['settings']['view']['persp']['step'] = pstep.GetId()
  1066. gridSizer.Add(item=pstep, pos=(0, 3),
  1067. flag=wx.ALIGN_CENTER_VERTICAL)
  1068. # position
  1069. self.win['settings']['view']['pos'] = {}
  1070. posvals = UserSettings.Get(group='nviz', key='view', subkey='pos')
  1071. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1072. label=_("Position") + " (x):"),
  1073. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1074. px = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1075. initial=posvals['x'] * 100,
  1076. min=0,
  1077. max=100)
  1078. self.win['settings']['view']['pos']['x'] = px.GetId()
  1079. gridSizer.Add(item=px, pos=(1, 1),
  1080. flag=wx.ALIGN_CENTER_VERTICAL)
  1081. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1082. label="(y):"),
  1083. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1084. py = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1085. initial=posvals['y'] * 100,
  1086. min=0,
  1087. max=100)
  1088. self.win['settings']['view']['pos']['y'] = py.GetId()
  1089. gridSizer.Add(item=py, pos=(1, 3),
  1090. flag=wx.ALIGN_CENTER_VERTICAL)
  1091. # height
  1092. self.win['settings']['view']['height'] = {}
  1093. hvals = UserSettings.Get(group='nviz', key='view', subkey='height')
  1094. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1095. label=_("Height") + " (min):"),
  1096. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1097. hmin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1098. initial=hvals['min'],
  1099. min=-1e6,
  1100. max=1e6)
  1101. self.win['settings']['view']['height']['min'] = hmin.GetId()
  1102. gridSizer.Add(item=hmin, pos=(2, 1),
  1103. flag=wx.ALIGN_CENTER_VERTICAL)
  1104. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1105. label="(max):"),
  1106. pos=(2, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1107. hmax = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1108. initial=hvals['max'],
  1109. min=-1e6,
  1110. max=1e6)
  1111. self.win['settings']['view']['height']['max'] = hmax.GetId()
  1112. gridSizer.Add(item=hmax, pos=(2, 3),
  1113. flag=wx.ALIGN_CENTER_VERTICAL)
  1114. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1115. label="(step):"),
  1116. pos=(2, 4), flag=wx.ALIGN_CENTER_VERTICAL)
  1117. hstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1118. initial=hvals['step'],
  1119. min=1,
  1120. max=hvals['max']-1)
  1121. self.win['settings']['view']['height']['step'] = hstep.GetId()
  1122. gridSizer.Add(item=hstep, pos=(2, 5),
  1123. flag=wx.ALIGN_CENTER_VERTICAL)
  1124. # twist
  1125. self.win['settings']['view']['twist'] = {}
  1126. tvals = UserSettings.Get(group='nviz', key='view', subkey='twist')
  1127. itvals = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
  1128. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1129. label=_("Twist (value):")),
  1130. pos=(3, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1131. tval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1132. initial=tvals['value'],
  1133. min=itvals['min'],
  1134. max=itvals['max'])
  1135. self.win['settings']['view']['twist']['value'] = tval.GetId()
  1136. gridSizer.Add(item=tval, pos=(3, 1),
  1137. flag=wx.ALIGN_CENTER_VERTICAL)
  1138. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1139. label=_("(step):")),
  1140. pos=(3, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1141. tstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1142. initial=tvals['step'],
  1143. min=itvals['min'],
  1144. max=itvals['max']-1)
  1145. self.win['settings']['view']['twist']['step'] = tstep.GetId()
  1146. gridSizer.Add(item=tstep, pos=(3, 3),
  1147. flag=wx.ALIGN_CENTER_VERTICAL)
  1148. # z-exag
  1149. self.win['settings']['view']['z-exag'] = {}
  1150. zvals = UserSettings.Get(group='nviz', key='view', subkey='z-exag')
  1151. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1152. label=_("Z-exag (value):")),
  1153. pos=(4, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1154. zval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1155. initial=zvals['value'],
  1156. min=-1e6,
  1157. max=1e6)
  1158. self.win['settings']['view']['z-exag']['value'] = zval.GetId()
  1159. gridSizer.Add(item=zval, pos=(4, 1),
  1160. flag=wx.ALIGN_CENTER_VERTICAL)
  1161. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1162. label=_("(step):")),
  1163. pos=(4, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1164. zstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1165. initial=zvals['step'],
  1166. min=-1e6,
  1167. max=1e6)
  1168. self.win['settings']['view']['z-exag']['step'] = zstep.GetId()
  1169. gridSizer.Add(item=zstep, pos=(4, 3),
  1170. flag=wx.ALIGN_CENTER_VERTICAL)
  1171. boxSizer.Add(item=gridSizer, proportion=1,
  1172. flag=wx.ALL | wx.EXPAND, border=3)
  1173. pageSizer.Add(item=boxSizer, proportion=0,
  1174. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1175. border=5)
  1176. #
  1177. # surface
  1178. #
  1179. self.win['settings']['surface'] = {}
  1180. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1181. label=" %s " % (_("Surface")))
  1182. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1183. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1184. boxSizer.Add(item=gridSizer, proportion=1,
  1185. flag=wx.ALL | wx.EXPAND, border=3)
  1186. pageSizer.Add(item=boxSizer, proportion=0,
  1187. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1188. border=5)
  1189. #
  1190. # vector
  1191. #
  1192. self.win['settings']['vector'] = {}
  1193. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1194. label=" %s " % (_("Vector")))
  1195. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1196. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1197. boxSizer.Add(item=gridSizer, proportion=1,
  1198. flag=wx.ALL | wx.EXPAND, border=3)
  1199. pageSizer.Add(item=boxSizer, proportion=0,
  1200. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1201. border=5)
  1202. #
  1203. # buttons
  1204. #
  1205. btnDefault = wx.Button(panel, wx.ID_CANCEL, label=_("Default"))
  1206. btnSave = wx.Button(panel, wx.ID_SAVE)
  1207. btnApply = wx.Button(panel, wx.ID_APPLY)
  1208. btnDefault.Bind(wx.EVT_BUTTON, self.OnDefault)
  1209. btnDefault.SetToolTipString(_("Restore default settings"))
  1210. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  1211. btnApply.SetToolTipString(_("Apply changes for the current session"))
  1212. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  1213. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  1214. btnSave.SetDefault()
  1215. btnSizer = wx.StdDialogButtonSizer()
  1216. btnSizer.AddButton(btnDefault)
  1217. btnSizer.AddButton(btnApply)
  1218. btnSizer.AddButton(btnSave)
  1219. btnSizer.Realize()
  1220. pageSizer.Add(item=btnSizer, proportion=1,
  1221. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM,
  1222. border=5)
  1223. panel.SetSizer(pageSizer)
  1224. def CreateControl(self, parent, dict, name, range, bind, sliderHor=True, size=200):
  1225. """Add control (Slider + SpinCtrl)"""
  1226. dict[name] = {}
  1227. if sliderHor:
  1228. style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  1229. wx.SL_BOTTOM
  1230. sizeW = (size, -1)
  1231. else:
  1232. style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | \
  1233. wx.SL_BOTTOM | wx.SL_INVERSE
  1234. sizeW = (-1, size)
  1235. try:
  1236. val = self.mapWindow.view[name]['value']
  1237. except KeyError:
  1238. val=-1
  1239. slider = wx.Slider(parent=parent, id=wx.ID_ANY,
  1240. value=val,
  1241. minValue=range[0],
  1242. maxValue=range[1],
  1243. style=style,
  1244. size=sizeW)
  1245. slider.SetName('slider')
  1246. slider.Bind(wx.EVT_SCROLL, bind[0])
  1247. slider.Bind(wx.EVT_SCROLL_CHANGED, bind[1])
  1248. dict[name]['slider'] = slider.GetId()
  1249. spin = wx.SpinCtrl(parent=parent, id=wx.ID_ANY, size=(65, -1),
  1250. initial=val,
  1251. min=range[0],
  1252. max=range[1])
  1253. # spin = wx.SpinButton(parent=parent, id=wx.ID_ANY)
  1254. # spin.SetValue (self.mapWindow.view[name]['value'])
  1255. # spin.SetRange(self.mapWindow.view[name]['min'],
  1256. # self.mapWindow.view[name]['max'])
  1257. # no 'changed' event ... (FIXME)
  1258. spin.SetName('spin')
  1259. spin.Bind(wx.EVT_SPINCTRL, bind[2])
  1260. dict[name]['spin'] = spin.GetId()
  1261. def UpdateSettings(self):
  1262. """Update dialog settings"""
  1263. for control in ('height',
  1264. 'persp',
  1265. 'twist',
  1266. 'z-exag'):
  1267. for win in self.win['view'][control].itervalues():
  1268. if control == 'height':
  1269. value = UserSettings.Get(group='nviz', key='view',
  1270. subkey=['height', 'value'], internal=True)
  1271. else:
  1272. value = self.mapWindow.view[control]['value']
  1273. self.FindWindowById(win).SetValue(value)
  1274. self.FindWindowById(self.win['view']['pos']).Draw()
  1275. self.FindWindowById(self.win['view']['pos']).Refresh(False)
  1276. self.Refresh(False)
  1277. def __GetWindowName(self, dict, id):
  1278. for name in dict.iterkeys():
  1279. if type(dict[name]) is type({}):
  1280. for win in dict[name].itervalues():
  1281. if win == id:
  1282. return name
  1283. else:
  1284. if dict[name] == id:
  1285. return name
  1286. return None
  1287. def OnViewChange(self, event):
  1288. """Change view, render in quick mode"""
  1289. # find control
  1290. winName = self.__GetWindowName(self.win['view'], event.GetId())
  1291. if not winName:
  1292. return
  1293. if winName == 'height':
  1294. view = self.mapWindow.iview # internal
  1295. else:
  1296. view = self.mapWindow.view
  1297. view[winName]['value'] = event.GetInt()
  1298. for win in self.win['view'][winName].itervalues():
  1299. self.FindWindowById(win).SetValue(view[winName]['value'])
  1300. self.mapWindow.update.append('view')
  1301. if winName == 'z-exag':
  1302. self.mapWindow.update.append('z-exag')
  1303. self.mapWindow.render = False
  1304. self.mapWindow.Refresh(False)
  1305. def OnViewChanged(self, event):
  1306. """View changed, render in full resolution"""
  1307. self.mapWindow.render = True
  1308. self.mapWindow.Refresh(False)
  1309. def OnViewChangedSpin(self, event):
  1310. """View changed, render in full resolution"""
  1311. # TODO: use step value instead
  1312. self.OnViewChange(event)
  1313. self.OnViewChanged(None)
  1314. def OnResetView(self, event):
  1315. """Reset to default view (view page)"""
  1316. self.mapWindow.ResetView()
  1317. self.UpdateSettings()
  1318. self.mapWindow.Refresh(False)
  1319. def OnLookAt(self, event):
  1320. """Look at (view page)"""
  1321. sel = event.GetSelection()
  1322. if sel == 0: # top
  1323. self.mapWindow.view['pos']['x'] = 0.5
  1324. self.mapWindow.view['pos']['y'] = 0.5
  1325. elif sel == 1: # north
  1326. self.mapWindow.view['pos']['x'] = 0.5
  1327. self.mapWindow.view['pos']['y'] = 0.0
  1328. elif sel == 2: # south
  1329. self.mapWindow.view['pos']['x'] = 0.5
  1330. self.mapWindow.view['pos']['y'] = 1.0
  1331. elif sel == 3: # east
  1332. self.mapWindow.view['pos']['x'] = 1.0
  1333. self.mapWindow.view['pos']['y'] = 0.5
  1334. elif sel == 4: # west
  1335. self.mapWindow.view['pos']['x'] = 0.0
  1336. self.mapWindow.view['pos']['y'] = 0.5
  1337. elif sel == 5: # north-west
  1338. self.mapWindow.view['pos']['x'] = 0.0
  1339. self.mapWindow.view['pos']['y'] = 0.0
  1340. elif sel == 6: # north-east
  1341. self.mapWindow.view['pos']['x'] = 1.0
  1342. self.mapWindow.view['pos']['y'] = 0.0
  1343. elif sel == 7: # south-east
  1344. self.mapWindow.view['pos']['x'] = 1.0
  1345. self.mapWindow.view['pos']['y'] = 1.0
  1346. elif sel == 8: # south-west
  1347. self.mapWindow.view['pos']['x'] = 0.0
  1348. self.mapWindow.view['pos']['y'] = 1.0
  1349. self.mapWindow.update.append('view')
  1350. self.UpdateSettings()
  1351. self.mapWindow.Refresh(False)
  1352. def OnDefault(self, event):
  1353. """Restore default settings"""
  1354. settings = copy.deepcopy(UserSettings.GetDefaultSettings()['nviz'])
  1355. UserSettings.Set(group='nviz',
  1356. value=settings)
  1357. for subgroup, key in settings.iteritems(): # view, surface, vector...
  1358. if subgroup != 'view':
  1359. continue
  1360. for subkey, value in key.iteritems():
  1361. for subvalue in value.keys():
  1362. win = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue])
  1363. val = settings[subgroup][subkey][subvalue]
  1364. if subkey == 'pos':
  1365. val = int(val * 100)
  1366. win.SetValue(val)
  1367. event.Skip()
  1368. def OnApply(self, event):
  1369. """Apply button pressed"""
  1370. if self.notebook.GetSelection() == self.page['settings']:
  1371. self.ApplySettings()
  1372. if event:
  1373. event.Skip()
  1374. def ApplySettings(self):
  1375. """Apply Nviz settings for current session"""
  1376. settings = UserSettings.Get(group='nviz')
  1377. for subgroup, key in settings.iteritems(): # view, surface, vector...
  1378. if subgroup != 'view':
  1379. continue
  1380. for subkey, value in key.iteritems():
  1381. for subvalue in value.keys():
  1382. value = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue]).GetValue()
  1383. if subkey == 'pos':
  1384. value = float(value) / 100
  1385. settings[subgroup][subkey][subvalue] = value
  1386. def OnSave(self, event):
  1387. """OK button pressed
  1388. Apply changes, update map and save settings of selected layer
  1389. """
  1390. #
  1391. # apply changes
  1392. #
  1393. self.OnApply(None)
  1394. if self.notebook.GetSelection() == self.page['settings']:
  1395. fileSettings = {}
  1396. UserSettings.ReadSettingsFile(settings=fileSettings)
  1397. fileSettings['nviz'] = UserSettings.Get(group='nviz')
  1398. file = UserSettings.SaveToFile(fileSettings)
  1399. self.lmgr.goutput.WriteLog(_('Nviz settings saved to file <%s>.') % file)
  1400. def OnBgColor(self, event):
  1401. """Background color changed"""
  1402. color = event.GetValue()
  1403. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1404. self.mapWindow.nvizClass.SetBgColor(str(color))
  1405. if self.parent.autoRender.IsChecked():
  1406. self.mapWindow.Refresh(False)
  1407. def OnClose(self, event):
  1408. """Close button pressed
  1409. Close dialog
  1410. """
  1411. self.Hide()
  1412. def OnSurfaceUse(self, event):
  1413. """Surface attribute -- use -- map/constant"""
  1414. if not self.mapWindow.init:
  1415. return
  1416. wx.Yield()
  1417. # find attribute row
  1418. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1419. if not attrb:
  1420. return
  1421. selection = event.GetSelection()
  1422. if self.win['surface'][attrb]['required']: # no 'unset'
  1423. selection += 1
  1424. if selection == 0: # unset
  1425. useMap = None
  1426. value = ''
  1427. elif selection == 1: # map
  1428. useMap = True
  1429. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1430. elif selection == 2: # constant
  1431. useMap = False
  1432. if attrb == 'color':
  1433. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1434. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1435. else:
  1436. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1437. self.SetSurfaceUseMap(attrb, useMap)
  1438. self.mapWindow.update.append('surface:attribute:%s' % attrb)
  1439. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1440. data['surface']['attribute'][attrb] = { 'map' : useMap,
  1441. 'value' : str(value),
  1442. }
  1443. self.mapWindow.UpdateLayerProperties()
  1444. if self.parent.autoRender.IsChecked():
  1445. self.mapWindow.Refresh(False)
  1446. def SetSurfaceUseMap(self, attrb, map=None):
  1447. if attrb in ('topo', 'color', 'shine'):
  1448. incSel = -1 # decrement selection (no 'unset')
  1449. else:
  1450. incSel = 0
  1451. if map is True: # map
  1452. if attrb != 'topo': # changing map topography not allowed
  1453. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(True) # FIXME
  1454. if self.win['surface'][attrb]['const']:
  1455. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1456. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(1 + incSel)
  1457. elif map is False: # const
  1458. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1459. if self.win['surface'][attrb]['const']:
  1460. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(True)
  1461. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(2 + incSel)
  1462. else: # unset
  1463. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1464. if self.win['surface'][attrb]['const']:
  1465. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1466. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(0)
  1467. def OnSurfaceMap(self, event):
  1468. """Set surface attribute"""
  1469. if not self.mapWindow.init:
  1470. return
  1471. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1472. if not attrb:
  1473. return
  1474. selection = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  1475. if self.win['surface'][attrb]['required']:
  1476. selection += 1
  1477. if selection == 0: # unset
  1478. map = None
  1479. value = ''
  1480. elif selection == 1: # map
  1481. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1482. map = True
  1483. else: # constant
  1484. if attrb == 'color':
  1485. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1486. # tuple to string
  1487. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1488. else:
  1489. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1490. map = False
  1491. if not self.pageChanging:
  1492. self.mapWindow.update.append('surface:attribute:%s' % attrb)
  1493. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1494. data['surface']['attribute'][attrb] = { 'map' : map,
  1495. 'value' : str(value),
  1496. }
  1497. self.mapWindow.UpdateLayerProperties()
  1498. if self.parent.autoRender.IsChecked():
  1499. self.mapWindow.Refresh(False)
  1500. def OnSurfaceResolution(self, event):
  1501. """Draw resolution changed"""
  1502. self.SetSurfaceResolution()
  1503. if apply and self.parent.autoRender.IsChecked():
  1504. self.mapWindow.Refresh(False)
  1505. def SetSurfaceResolution(self, all=False):
  1506. """Set draw resolution"""
  1507. coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
  1508. fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
  1509. self.mapWindow.update.append('surface:draw:resolution')
  1510. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1511. data['surface']['draw']['resolution'] = { 'coarse' : coarse,
  1512. 'fine' : fine,
  1513. 'all' : all }
  1514. self.mapWindow.UpdateLayerProperties()
  1515. def SetSurfaceMode(self, all=False):
  1516. """Set draw mode
  1517. @param apply allow auto-rendering
  1518. """
  1519. mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
  1520. if mode == 0: # coarse
  1521. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1522. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
  1523. elif mode == 1: # fine
  1524. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
  1525. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1526. else: # both
  1527. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1528. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1529. style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
  1530. shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
  1531. value, desc = self.mapWindow.GetSurfaceMode(mode, style, shade)
  1532. def OnSurfaceMode(self, event):
  1533. """Set draw mode"""
  1534. self.SetSurfaceMode()
  1535. self.mapWindow.update.append('surface:draw:mode')
  1536. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1537. data['surface']['draw']['mode'] = { 'value' : value,
  1538. 'all' : all,
  1539. 'desc' : desc }
  1540. self.mapWindow.UpdateLayerProperties()
  1541. if apply and self.parent.autoRender.IsChecked():
  1542. self.mapWindow.Refresh(False)
  1543. def OnSurfaceModeAll(self, event):
  1544. """Set draw mode (including wire color) for all loaded surfaces"""
  1545. self.SetSurfaceMode(all=True)
  1546. self.SetSurfaceResolution(all=True)
  1547. color = self.FindWindowById(self.win['surface']['draw']['wire-color']).GetColour()
  1548. self.SetSurfaceWireColor(color, all=True)
  1549. if apply and self.parent.autoRender.IsChecked():
  1550. self.mapWindow.Refresh(False)
  1551. def SetSurfaceWireColor(self, color, all=False, apply=True):
  1552. """Set wire color"""
  1553. value = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1554. def OnSurfaceWireColor(self, event):
  1555. """Set wire color"""
  1556. self.SetSurfaceWireColor(event.GetValue())
  1557. self.mapWindow.update.append('surface:draw:wire-color')
  1558. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1559. data['surface']['draw']['wire-color'] = { 'value' : value,
  1560. 'all' : all }
  1561. self.mapWindow.UpdateLayerProperties()
  1562. if self.parent.autoRender.IsChecked():
  1563. self.mapWindow.Refresh(False)
  1564. def OnSurfaceAxis(self, event):
  1565. """Surface position, axis changed"""
  1566. mapLayer = self.mapWindow.GetSelectedLayer()
  1567. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1568. id = data['object']['id']
  1569. axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
  1570. win = self.FindWindowById(self.win['surface']['position']['pos'])
  1571. x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
  1572. if axis == 0: # x
  1573. win.SetRange(-1e4, 1e4)
  1574. win.SetValue(x)
  1575. elif axis == 1: # y
  1576. win.SetRange(-1e4, 1e4)
  1577. win.SetValue(y)
  1578. else: # z
  1579. win.SetRange(-1e3, 1e3)
  1580. win.SetValue(z)
  1581. def OnSurfacePosition(self, event):
  1582. """Surface position"""
  1583. axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
  1584. value = event.GetInt()
  1585. mapLayer = self.mapWindow.GetSelectedLayer()
  1586. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1587. id = data['object']['id']
  1588. x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
  1589. if axis == 0: # x
  1590. x = value
  1591. elif axis == 1: # y
  1592. y = value
  1593. else: # z
  1594. z = value
  1595. self.mapWindow.update.append('surface:position')
  1596. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1597. data['surface']['position']['x'] = x
  1598. data['surface']['position']['y'] = y
  1599. data['surface']['position']['z'] = z
  1600. self.mapWindow.UpdateLayerProperties()
  1601. if self.parent.autoRender.IsChecked():
  1602. self.mapWindow.Refresh(False)
  1603. def OnVectorDisplay(self, event):
  1604. """Display vector lines on surface/flat"""
  1605. if event.GetSelection() == 0: # surface
  1606. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(True)
  1607. # set first found surface
  1608. ### TODO
  1609. else: # flat
  1610. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(False)
  1611. self.OnVectorLines(event)
  1612. event.Skip()
  1613. def OnVectorLines(self, event):
  1614. """Set vector lines mode, apply changes if auto-rendering is enabled"""
  1615. width = self.FindWindowById(self.win['vector']['lines']['width']).GetValue()
  1616. color = self.FindWindowById(self.win['vector']['lines']['color']).GetColour()
  1617. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1618. mode = {}
  1619. if self.FindWindowById(self.win['vector']['lines']['flat']).GetSelection() == 0:
  1620. mode['type'] = 'surface'
  1621. mode['map'] = '' # TODO
  1622. else:
  1623. mode['type'] = 'flat'
  1624. self.mapWindow.update.append('vector:lines:width')
  1625. self.mapWindow.update.append('vector:lines:color')
  1626. self.mapWindow.update.append('vector:lines:mode')
  1627. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1628. data['vector']['lines']['width'] = width
  1629. data['vector']['lines']['color'] = color
  1630. data['vector']['lines']['mode'] = mode
  1631. self.mapWindow.UpdateLayerProperties()
  1632. if self.parent.autoRender.IsChecked():
  1633. self.mapWindow.Refresh(False)
  1634. def OnVectorHeight(self, event):
  1635. value = event.GetInt()
  1636. if type(event) == type(wx.ScrollEvent()):
  1637. # slider
  1638. win = self.FindWindowById(self.win['vector']['lines']['height']['spin'])
  1639. else:
  1640. # spin
  1641. win = self.FindWindowById(self.win['vector']['lines']['height']['slider'])
  1642. win.SetValue(value)
  1643. self.mapWindow.update.append('vector:lines:height')
  1644. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1645. data['vector']['lines']['height'] = value
  1646. self.mapWindow.UpdateLayerProperties()
  1647. if self.parent.autoRender.IsChecked():
  1648. self.mapWindow.Refresh(False)
  1649. def UpdatePage(self, pageId):
  1650. """Update dialog (selected page)"""
  1651. self.pageChanging = True
  1652. layer = self.mapWindow.GetSelectedLayer()
  1653. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1654. if pageId == 'view':
  1655. max = self.mapWindow.view['z-exag']['value'] * 10
  1656. for control in ('spin', 'slider'):
  1657. self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(0,
  1658. max)
  1659. elif pageId == 'surface':
  1660. if data and data.has_key('surface'):
  1661. self.UpdateSurfacePage(layer, data['surface'])
  1662. else:
  1663. self.UpdateSurfacePage(layer, None)
  1664. # disable vector and enable surface page
  1665. self.notebook.GetPage(self.page['surface']).Enable(True)
  1666. self.notebook.GetPage(self.page['vector']).Enable(False)
  1667. elif pageId == 'vector':
  1668. if data and data.has_key('vector'):
  1669. self.UpdateVectorPage(layer, data['vector'])
  1670. else:
  1671. self.UpdateVectorPage(layer, None)
  1672. # disable surface and enable current
  1673. self.notebook.GetPage(self.page['surface']).Enable(False)
  1674. self.notebook.GetPage(self.page['vector']).Enable(True)
  1675. self.pageChanging = False
  1676. def UpdateSurfacePage(self, layer, data):
  1677. #
  1678. # attributes
  1679. #
  1680. for attr in ('topo', 'color'): # required
  1681. if layer and layer.type == 'raster':
  1682. self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
  1683. else:
  1684. self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
  1685. self.SetSurfaceUseMap(attr, True) # -> map
  1686. if data['attribute'].has_key('color'):
  1687. value = data['attribute']['color']['value']
  1688. if data['attribute']['color']['map']:
  1689. self.FindWindowById(self.win['surface']['color']['map']).SetValue(value)
  1690. else: # constant
  1691. color = map(int, value.split(':'))
  1692. self.FindWindowById(self.win['surface']['color']['const']).SetColour(color)
  1693. self.SetSurfaceUseMap(attr, data['attribute']['color']['map'])
  1694. self.SetSurfaceUseMap('shine', data['attribute']['shine']['map'])
  1695. value = data['attribute']['shine']['value']
  1696. self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
  1697. #
  1698. # draw
  1699. #
  1700. for control, dict in data['draw'].iteritems():
  1701. if control == 'resolution':
  1702. self.FindWindowById(self.win['surface']['draw']['res-coarse']).SetValue(dict['coarse'])
  1703. self.FindWindowById(self.win['surface']['draw']['res-fine']).SetValue(dict['fine'])
  1704. continue
  1705. if control == 'mode':
  1706. if dict['desc']['mode'] == 'coarse':
  1707. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(0)
  1708. elif dict['desc']['mode'] == 'fine':
  1709. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(1)
  1710. else: # both
  1711. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(2)
  1712. if dict['desc']['style'] == 'wire':
  1713. self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(0)
  1714. else: # surface
  1715. self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(1)
  1716. if dict['desc']['shading'] == 'flat':
  1717. self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(0)
  1718. else: # gouraud
  1719. self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(1)
  1720. continue
  1721. value = dict['value']
  1722. win = self.FindWindowById(self.win['surface']['draw'][control])
  1723. name = win.GetName()
  1724. if name == "selection":
  1725. win.SetSelection(value)
  1726. elif name == "colour":
  1727. color = map(int, value.split(':'))
  1728. win.SetColour(color)
  1729. else:
  1730. win.SetValue(value)
  1731. # enable/disable res widget + set draw mode
  1732. self.SetSurfaceMode()
  1733. color = self.FindWindowById(self.win['surface']['draw']['wire-color'])
  1734. self.SetSurfaceWireColor(color.GetColour())
  1735. def UpdateVectorPage(self, layer, data):
  1736. #
  1737. # lines
  1738. #
  1739. width = self.FindWindowById(self.win['vector']['lines']['width'])
  1740. width.SetValue(data['lines']['width'])
  1741. color = self.FindWindowById(self.win['vector']['lines']['color'])
  1742. color.SetValue(map(int, data['lines']['color'].split(':')))
  1743. display = self.FindWindowById(self.win['vector']['lines']['flat'])
  1744. if data['lines']['mode']['type'] == 'flat':
  1745. display.SetSelection(1)
  1746. else:
  1747. display.SetSelection(0)
  1748. for type in ('slider', 'spin'):
  1749. win = self.FindWindowById(self.win['vector']['lines']['height'][type])
  1750. win.SetValue(data['lines']['height'])
  1751. def SetPage(self, name):
  1752. """Get named page"""
  1753. self.notebook.SetSelection(self.page[name])
  1754. class ViewPositionWindow(wx.Window):
  1755. """Position control window (for NvizToolWindow)"""
  1756. def __init__(self, parent, id, mapwindow,
  1757. pos=wx.DefaultPosition,
  1758. size=wx.DefaultSize):
  1759. self.mapWindow = mapwindow
  1760. wx.Window.__init__(self, parent, id, pos, size)
  1761. self.SetBackgroundColour("WHITE")
  1762. self.pdc = wx.PseudoDC()
  1763. self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
  1764. self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
  1765. self.Draw()
  1766. self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
  1767. self.Bind(wx.EVT_PAINT, self.OnPaint)
  1768. # self.Bind(wx.EVT_MOTION, self.OnMouse)
  1769. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
  1770. def Draw(self, pos=None):
  1771. w, h = self.GetClientSize()
  1772. if pos is None:
  1773. x = self.mapWindow.view['pos']['x']
  1774. y = self.mapWindow.view['pos']['y']
  1775. x = x * w
  1776. y = y * h
  1777. else:
  1778. x, y = pos
  1779. self.pdc.Clear()
  1780. self.pdc.BeginDrawing()
  1781. self.pdc.DrawLine(w / 2, h / 2, x, y)
  1782. self.pdc.DrawCircle(x, y, 5)
  1783. self.pdc.EndDrawing()
  1784. def OnPaint(self, event):
  1785. dc = wx.BufferedPaintDC(self)
  1786. dc.SetBackground(wx.Brush("White"))
  1787. dc.Clear()
  1788. self.PrepareDC(dc)
  1789. self.pdc.DrawToDC(dc)
  1790. def OnMouse(self, event):
  1791. if event.LeftIsDown():
  1792. x, y = event.GetPosition()
  1793. self.Draw(pos=(x, y))
  1794. self.Refresh(False)
  1795. w, h = self.GetClientSize()
  1796. x = float(x) / w
  1797. y = float(y) / h
  1798. if x >= 0 and x <= 1.0:
  1799. self.mapWindow.view['pos']['x'] = x
  1800. if y >= 0 and y <= 1.0:
  1801. self.mapWindow.view['pos']['y'] = y
  1802. self.mapWindow.update.append('view')
  1803. self.mapWindow.render = False
  1804. self.mapWindow.Refresh(eraseBackground=False)
  1805. elif event.LeftUp():
  1806. self.mapWindow.render = True
  1807. self.mapWindow.Refresh(eraseBackground=False)
  1808. event.Skip()