nviz.py 83 KB

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