nviz.py 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646
  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. from threading import Thread
  18. import wx
  19. import wx.lib.colourselect as csel
  20. import wx.lib.scrolledpanel as scrolled
  21. try:
  22. from wx import glcanvas
  23. haveGLCanvas = True
  24. except ImportError:
  25. haveGLCanvas = False
  26. try:
  27. from OpenGL.GL import *
  28. from OpenGL.GLUT import *
  29. haveOpenGL = True
  30. except ImportError:
  31. haveOpenGL = False
  32. import globalvar
  33. import gcmd
  34. import gselect
  35. from debug import Debug as Debug
  36. from mapdisp import MapWindow as MapWindow
  37. from preferences import globalSettings as UserSettings
  38. try:
  39. nvizPath = os.path.join(globalvar.ETCWXDIR, "nviz")
  40. sys.path.append(nvizPath)
  41. import grass7_wxnviz as wxnviz
  42. haveNviz = True
  43. except ImportError:
  44. haveNviz = False
  45. class GLWindow(MapWindow, glcanvas.GLCanvas):
  46. """OpenGL canvas for Map Display Window"""
  47. def __init__(self, parent, id,
  48. pos=wx.DefaultPosition,
  49. size=wx.DefaultSize,
  50. style=wx.NO_FULL_REPAINT_ON_RESIZE,
  51. Map=None, tree=None, gismgr=None):
  52. self.parent = parent # MapFrame
  53. self.Map = Map
  54. self.tree = tree
  55. self.gismgr = gismgr
  56. glcanvas.GLCanvas.__init__(self, parent, id)
  57. MapWindow.__init__(self, parent, id, pos, size, style,
  58. Map, tree, gismgr)
  59. self.parent = parent # MapFrame
  60. # attribList=[wx.WX_GL_RGBA, wx.GLX_RED_SIZE, 1,
  61. # wx.GLX_GREEN_SIZE, 1,
  62. # wx.GLX_BLUE_SIZE, 1,
  63. # wx.GLX_DEPTH_SIZE, 1,
  64. # None])
  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 = UserSettings.Get(group='nviz', key='view') # reference
  88. self.update = {} # update view/controls
  89. self.object = {} # loaded data objects (layer index / gsurf id)
  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.view['z-exag']['value'], \
  117. self.view['height']['value'] = self.nvizClass.SetViewDefault()
  118. if hasattr(self.parent, "nvizToolWin"):
  119. self.parent.nvizToolWin.UpdatePage('view')
  120. self.parent.nvizToolWin.UpdateSettings()
  121. self.init = True
  122. self.UpdateMap()
  123. def OnMouseAction(self, event):
  124. # change position
  125. if event.Dragging() and event.LeftIsDown():
  126. self.lastX = self.lastY = self.x = self.y
  127. self.x, self.y = event.GetPosition()
  128. self.Refresh(False)
  129. # change perspective with mouse wheel
  130. wheel = event.GetWheelRotation()
  131. if wheel != 0:
  132. current = event.GetPositionTuple()[:]
  133. Debug.msg (5, "GLWindow.OnMouseMotion(): wheel=%d" % wheel)
  134. if wheel > 0:
  135. value = -1 * self.view['persp']['step']
  136. else:
  137. value = self.view['persp']['step']
  138. self.view['persp']['value'] += value
  139. if self.view['persp']['value'] < 1:
  140. self.view['persp']['value'] = 1
  141. elif self.view['persp']['value'] > 100:
  142. self.view['persp']['value'] = 100
  143. if hasattr(self.parent, "nvizToolWin"):
  144. self.parent.nvizToolWin.UpdateSettings()
  145. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  146. self.view['height']['value'],
  147. self.view['persp']['value'],
  148. self.view['twist']['value'])
  149. # redraw map
  150. self.OnPaint(None)
  151. # update statusbar
  152. ### self.parent.StatusbarUpdate()
  153. def OnLeftDown(self, event):
  154. self.CaptureMouse()
  155. self.x, self.y = self.lastX, self.lastY = event.GetPosition()
  156. def OnLeftUp(self, event):
  157. self.ReleaseMouse()
  158. def UpdateMap(self, render=True):
  159. """
  160. Updates the canvas anytime there is a change to the
  161. underlaying images or to the geometry of the canvas.
  162. @param render re-render map composition
  163. """
  164. start = time.clock()
  165. self.resize = False
  166. # if self.size is None:
  167. # self.size = self.GetClientSize()
  168. # w, h = self.size
  169. # w = float(max(w, 1.0))
  170. # h = float(max(h, 1.0))
  171. # d = float(min(w, h))
  172. # xScale = d / w
  173. # yScale = d / h
  174. # print w, h, d, xScale, yScale
  175. # print self.y, self.lastY, self.x, self.lastX
  176. # print (self.y - self.lastY) * yScale, (self.x - self.lastX) * xScale
  177. # print self.x * xScale
  178. #glRotatef((self.y - self.lastY) * yScale, 1.0, 0.0, 0.0);
  179. #glRotatef((self.x - self.lastX) * xScale, 0.0, 1.0, 0.0);
  180. self.parent.onRenderGauge.Show()
  181. if self.parent.onRenderGauge.GetRange() > 0:
  182. self.parent.onRenderGauge.SetValue(1)
  183. self.parent.onRenderTimer.Start(100)
  184. self.parent.onRenderCounter = 0
  185. if 'view' in self.update.keys():
  186. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  187. self.view['height']['value'],
  188. self.view['persp']['value'],
  189. self.view['twist']['value'])
  190. del self.update['view']
  191. if 'z-exag' in self.update.keys():
  192. self.nvizClass.SetZExag(self.view['z-exag']['value'])
  193. del self.update['z-exag']
  194. if self.render is True:
  195. self.nvizClass.Draw(False)
  196. else:
  197. self.nvizClass.Draw(True) # quick
  198. self.SwapBuffers()
  199. stop = time.clock()
  200. #
  201. # hide process bar
  202. #
  203. if self.parent.onRenderGauge.GetRange() > 0:
  204. self.parent.onRenderTimer.Stop()
  205. self.parent.onRenderGauge.Hide()
  206. #
  207. # update statusbar
  208. #
  209. ### self.Map.SetRegion()
  210. # self.parent.StatusbarUpdate()
  211. Debug.msg(3, "GLWindow.UpdateMap(): render=%s, -> time=%g" % \
  212. (self.render, (stop-start)))
  213. def EraseMap(self):
  214. """
  215. Erase the canvas
  216. """
  217. self.nvizClass.EraseMap()
  218. self.SwapBuffers()
  219. def LoadDataLayers(self):
  220. """Load raster/vector from current layer tree
  221. @todo volumes
  222. """
  223. # load raster maps
  224. for layer in self.Map.GetListOfLayers(l_type='raster', l_active=True):
  225. self.LoadRaster(layer)
  226. # load vector maps
  227. for layer in self.Map.GetListOfLayers(l_type='vector', l_active=True):
  228. self.LoadVector(layer)
  229. def LoadRaster(self, layer):
  230. """Load raster map -> surface"""
  231. if layer.type != 'raster':
  232. return
  233. id = self.nvizClass.LoadSurface(str(layer.name), None, None)
  234. if id < 0:
  235. raise gcmd.NvizError(parent=self.parent,
  236. message=_("Unable to load raster map <%s>" % layer.name))
  237. # set resolution
  238. res = UserSettings.Get(group='nviz', key='surface',
  239. subkey=['draw', 'res-fine'])
  240. wire = UserSettings.Get(group='nviz', key='surface',
  241. subkey=['draw', 'res-coarse'])
  242. self.nvizClass.SetSurfaceRes(id, res, wire)
  243. self.object[self.Map.GetLayerIndex(layer)] = id ### FIXME layer index is not fixed id!
  244. def UnloadRaster(self, layer):
  245. """Unload raster map"""
  246. if layer.type != 'raster':
  247. return
  248. idx = self.Map.GetLayerIndex(layer) ### FIXME layer index is not fixed id!
  249. if not self.object.has_key(idx):
  250. return
  251. if layer.type == 'raster':
  252. if self.nvizClass.UnloadSurface(self.object[idx]) == 0:
  253. raise gcmd.NvizError(parent=self.parent,
  254. message=_("Unable to unload raster map <%s>" % layer.name))
  255. def LoadVector(self, layer):
  256. """Load vector map overlay"""
  257. if layer.type != 'vector':
  258. return
  259. id = self.nvizClass.LoadVector(str(layer.name))
  260. if id < 0:
  261. raise gcmd.NvizError(parent=self.parent,
  262. message=_("Unable to load vector map <%s>" % layer.name))
  263. self.object[self.Map.GetLayerIndex(layer)] = id ### FIXME layer index is not fixed id!
  264. def UnloadVector(self, layer):
  265. """Unload vector map overlay"""
  266. if layer.type != 'vector':
  267. return
  268. idx = self.Map.GetLayerIndex(layer) ### FIXME layer index is not fixed id!
  269. if not self.object.has_key(idx):
  270. return
  271. if layer.type == 'vector':
  272. if self.nvizClass.UnloadVector(self.object[idx]) == 0:
  273. raise gcmd.NvizError(parent=self.parent,
  274. message=_("Unable to unload vector map <%s>" % layer.name))
  275. def Reset(self):
  276. """Reset (unload data)"""
  277. self.nvizClass.Reset()
  278. self.init = False
  279. def OnZoomToMap(self, event):
  280. """
  281. Set display extents to match selected raster
  282. or vector map or volume.
  283. @todo vector, volume
  284. """
  285. layer = self.GetSelectedLayer()
  286. if layer is None:
  287. return
  288. Debug.msg (3, "GLWindow.OnZoomToMap(): layer=%s, type=%s" % \
  289. (layer.name, layer.type))
  290. self.nvizClass.SetViewportDefault()
  291. def ResetView(self):
  292. """Reset to default view"""
  293. self.view['pos']['x'] = wxnviz.VIEW_DEFAULT_POS_X
  294. self.view['pos']['y'] = wxnviz.VIEW_DEFAULT_POS_Y
  295. self.view['z-exag']['value'], \
  296. self.view['height']['value'] = self.nvizClass.SetViewDefault()
  297. self.view['persp']['value'] = wxnviz.VIEW_DEFAULT_PERSP
  298. self.view['twist']['value'] = wxnviz.VIEW_DEFAULT_TWIST
  299. self.update['view'] = None
  300. self.update['z-exag'] = None
  301. def GetMapObjId(self, layer):
  302. """Get map object id of given map layer (2D)
  303. @param layer MapLayer instance
  304. """
  305. index = self.Map.GetLayerIndex(layer)
  306. try:
  307. return self.object[index]
  308. except:
  309. return -1
  310. def SetLayerSettings(self, data):
  311. """Set settings for selected layer
  312. @param data settings
  313. @return 1 on success
  314. @return 0 on failure
  315. """
  316. # get currently selected map layer
  317. if not self.tree or not self.tree.GetSelection():
  318. return 0
  319. item = self.tree.GetSelection()
  320. try:
  321. self.tree.SetPyData(item)[0]['nviz'] = data
  322. except:
  323. return 0
  324. return 1
  325. class NvizToolWindow(wx.Frame):
  326. """Experimental window for Nviz tools
  327. @todo integrate with Map display
  328. """
  329. def __init__(self, parent=None, id=wx.ID_ANY, title=_("Nviz tools"),
  330. pos=wx.DefaultPosition, size=wx.DefaultSize,
  331. style=wx.DEFAULT_FRAME_STYLE, mapWindow=None):
  332. self.parent = parent # MapFrame
  333. self.mapWindow = mapWindow
  334. self.settings = mapWindow.view # GLWindow.view
  335. wx.Frame.__init__(self, parent, id, title, pos, size, style)
  336. # dialog body
  337. mainSizer = wx.BoxSizer(wx.VERTICAL)
  338. self.win = {} # window ids
  339. #
  340. # notebook
  341. #
  342. self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
  343. self.page = {}
  344. # view page
  345. self.__createViewPage()
  346. self.page['view'] = 0
  347. # surface page
  348. self.__createSurfacePage()
  349. self.page['surface'] = 1
  350. # vector page
  351. self.__createVectorPage()
  352. self.page['vector'] = 2
  353. # settings page
  354. self.__createSettingsPage()
  355. self.page['settings'] = 3
  356. self.UpdatePage('surface')
  357. self.UpdatePage('vector')
  358. self.UpdatePage('settings')
  359. mainSizer.Add(item=self.notebook, proportion=1,
  360. flag=wx.EXPAND | wx.ALL, border=5)
  361. #
  362. # button (see menuform)
  363. #
  364. btnCancel = wx.Button(self, wx.ID_CANCEL)
  365. btnApply = wx.Button(self, wx.ID_APPLY)
  366. btnSave = wx.Button(self, wx.ID_SAVE)
  367. btnSave.SetDefault()
  368. # bindings
  369. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  370. btnApply.SetToolTipString(_("Apply changes and update display"))
  371. btnApply.SetDefault()
  372. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  373. btnSave.SetToolTipString(_("Apply changes, update display and save changes to layer settings"))
  374. btnCancel.Bind(wx.EVT_BUTTON, self.OnClose)
  375. btnCancel.SetToolTipString(_("Hide dialog and ignore changes"))
  376. # sizer
  377. btnSizer = wx.StdDialogButtonSizer()
  378. btnSizer.AddButton(btnApply)
  379. btnSizer.AddButton(btnCancel)
  380. btnSizer.AddButton(btnSave)
  381. btnSizer.Realize()
  382. mainSizer.Add(item=btnSizer, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL,
  383. border=5)
  384. #
  385. # bindings
  386. #
  387. self.Bind(wx.EVT_CLOSE, self.OnClose)
  388. #
  389. # layout
  390. #
  391. self.SetSizer(mainSizer)
  392. mainSizer.Fit(self)
  393. def __createViewPage(self):
  394. """Create view settings page"""
  395. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  396. self.notebook.AddPage(page=panel,
  397. text=" %s " % _("View"))
  398. pageSizer = wx.BoxSizer(wx.VERTICAL)
  399. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  400. self.win['view'] = {}
  401. # position
  402. posSizer = wx.GridBagSizer(vgap=3, hgap=3)
  403. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("W")),
  404. pos=(1, 0), flag=wx.ALIGN_CENTER)
  405. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("N")),
  406. pos=(0, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM)
  407. viewPos = ViewPositionWindow(panel, id=wx.ID_ANY, size=(175, 175),
  408. settings=self.settings, mapwindow=self.mapWindow)
  409. self.win['view']['pos'] = viewPos.GetId()
  410. posSizer.Add(item=viewPos,
  411. pos=(1, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL)
  412. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("S")),
  413. pos=(2, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_TOP)
  414. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("E")),
  415. pos=(1, 2), flag=wx.ALIGN_CENTER)
  416. gridSizer.Add(item=posSizer, pos=(0, 0))
  417. # perspective
  418. self.CreateControl(panel, dict=self.win['view'], name='persp')
  419. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Perspective:")),
  420. pos=(1, 0), flag=wx.ALIGN_CENTER)
  421. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['slider']), pos=(2, 0))
  422. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['spin']), pos=(3, 0),
  423. flag=wx.ALIGN_CENTER)
  424. # twist
  425. self.CreateControl(panel, dict=self.win['view'], name='twist')
  426. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Twist:")),
  427. pos=(1, 1), flag=wx.ALIGN_CENTER)
  428. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['slider']), pos=(2, 1))
  429. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['spin']), pos=(3, 1),
  430. flag=wx.ALIGN_CENTER)
  431. # height + z-exag
  432. self.CreateControl(panel, dict=self.win['view'], name='height', sliderHor=False)
  433. self.CreateControl(panel, dict=self.win['view'], name='z-exag', sliderHor=False)
  434. heightSizer = wx.GridBagSizer(vgap=3, hgap=3)
  435. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Height:")),
  436. pos=(0, 0), flag=wx.ALIGN_LEFT, span=(1, 2))
  437. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['slider']),
  438. flag=wx.ALIGN_RIGHT, pos=(1, 0))
  439. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['spin']),
  440. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  441. wx.BOTTOM | wx.RIGHT, pos=(1, 1))
  442. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Z-exag:")),
  443. pos=(0, 2), flag=wx.ALIGN_LEFT, span=(1, 2))
  444. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['slider']),
  445. flag=wx.ALIGN_RIGHT, pos=(1, 2))
  446. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['spin']),
  447. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  448. wx.BOTTOM | wx.RIGHT, pos=(1, 3))
  449. gridSizer.Add(item=heightSizer, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  450. # view setup + reset
  451. viewSizer = wx.BoxSizer(wx.HORIZONTAL)
  452. viewSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY,
  453. label=_("Look at:")),
  454. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
  455. viewType = wx.Choice (parent=panel, id=wx.ID_ANY, size=(125, -1),
  456. choices = [_("top"),
  457. _("north"),
  458. _("south"),
  459. _("east"),
  460. _("west"),
  461. _("north-west"),
  462. _("north-east"),
  463. _("south-east"),
  464. _("south-west")])
  465. viewType.SetSelection(0)
  466. viewType.Bind(wx.EVT_CHOICE, self.OnLookAt)
  467. # self.win['lookAt'] = viewType.GetId()
  468. viewSizer.Add(item=viewType, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
  469. border=5)
  470. reset = wx.Button(panel, id=wx.ID_ANY, label=_("Reset"))
  471. reset.SetToolTipString(_("Reset to default view"))
  472. # self.win['reset'] = reset.GetId()
  473. reset.Bind(wx.EVT_BUTTON, self.OnResetView)
  474. viewSizer.Add(item=reset, proportion=1,
  475. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT,
  476. border=5)
  477. gridSizer.AddGrowableCol(3)
  478. gridSizer.Add(item=viewSizer, pos=(4, 0), span=(1, 2),
  479. flag=wx.EXPAND)
  480. # body
  481. pageSizer.Add(item=gridSizer, proportion=1,
  482. flag=wx.EXPAND | wx.ALL,
  483. border=5)
  484. panel.SetSizer(pageSizer)
  485. def __createSurfacePage(self):
  486. """Create view settings page"""
  487. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  488. # panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY)
  489. # panel.SetupScrolling(scroll_x=True, scroll_y=True)
  490. self.notebook.AddPage(page=panel,
  491. text=" %s " % _("Surface"))
  492. pageSizer = wx.BoxSizer(wx.VERTICAL)
  493. self.win['surface'] = {}
  494. #
  495. # surface attributes
  496. #
  497. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  498. label=" %s " % (_("Surface attributes")))
  499. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  500. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  501. # labels
  502. # col = 0
  503. # for type in (_("Attribute"),
  504. # _("Use"),
  505. # _("Map"),
  506. # _("Constant")):
  507. # gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  508. # label=type),
  509. # pos=(0, col))
  510. # col += 1
  511. # type
  512. self.win['surface']['attr'] = {}
  513. row = 0
  514. for code, attrb in (('topo', _("Topography")),
  515. ('color', _("Color")),
  516. ('mask', _("Mask")),
  517. ('transp', _("Transparency")),
  518. ('shine', _("Shininess")),
  519. ('emit', _("Emission"))):
  520. self.win['surface'][code] = {}
  521. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  522. label=attrb + ':'),
  523. pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  524. use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  525. choices = [_("map")])
  526. if code not in ('topo', 'color', 'shine'):
  527. use.Insert(item=_("unset"), pos=0)
  528. self.win['surface'][code]['required'] = False
  529. else:
  530. self.win['surface'][code]['required'] = True
  531. if code != 'mask':
  532. use.Append(item=_('constant'))
  533. self.win['surface'][code]['use'] = use.GetId()
  534. use.Bind(wx.EVT_CHOICE, self.OnSurfaceUse)
  535. gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
  536. pos=(row, 1))
  537. map = gselect.Select(parent=panel, id=wx.ID_ANY,
  538. # size=globalvar.DIALOG_GSELECT_SIZE,
  539. size=(200, -1),
  540. type="raster")
  541. self.win['surface'][code]['map'] = map.GetId() - 1 # FIXME
  542. map.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  543. # changing map topography not allowed
  544. if code == 'topo':
  545. map.Enable(False)
  546. gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
  547. pos=(row, 2))
  548. if code == 'color':
  549. value = csel.ColourSelect(panel, id=wx.ID_ANY,
  550. colour=UserSettings.Get(group='nviz', key='surface',
  551. subkey=['color', 'value']))
  552. value.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceMap)
  553. elif code == 'mask':
  554. value = None
  555. else:
  556. value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  557. initial=0)
  558. if code == 'topo':
  559. value.SetRange(minVal=-1e9, maxVal=1e9)
  560. elif code in ('shine', 'transp', 'emit'):
  561. value.SetRange(minVal=0, maxVal=255)
  562. else:
  563. value.SetRange(minVal=0, maxVal=100)
  564. value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  565. if value:
  566. self.win['surface'][code]['const'] = value.GetId()
  567. value.Enable(False)
  568. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  569. pos=(row, 3))
  570. else:
  571. self.win['surface'][code]['const'] = None
  572. self.SetSurfaceUseMap(code) # -> enable map / disable constant
  573. row += 1
  574. boxSizer.Add(item=gridSizer, proportion=1,
  575. flag=wx.ALL | wx.EXPAND, border=3)
  576. pageSizer.Add(item=boxSizer, proportion=0,
  577. flag=wx.EXPAND | wx.ALL,
  578. border=5)
  579. #
  580. # draw
  581. #
  582. self.win['surface']['draw'] = {}
  583. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  584. label=" %s " % (_("Draw")))
  585. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  586. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  587. gridSizer.AddGrowableCol(4)
  588. # mode
  589. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  590. label=_("Mode:")),
  591. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  592. mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  593. choices = [_("coarse"),
  594. _("fine"),
  595. _("both")])
  596. mode.SetName("selection")
  597. mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  598. self.win['surface']['draw']['mode'] = mode.GetId()
  599. gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
  600. pos=(0, 1))
  601. # resolution (mode)
  602. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  603. label=_("Resolution:")),
  604. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  605. resSizer = wx.BoxSizer(wx.HORIZONTAL)
  606. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  607. label=_("coarse:")),
  608. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  609. resC = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  610. initial=1,
  611. min=1,
  612. max=100)
  613. resC.SetName("value")
  614. self.win['surface']['draw']['res-coarse'] = resC.GetId()
  615. resC.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  616. resSizer.Add(item=resC, flag=wx.ALL, border=3)
  617. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  618. label=_("fine:")),
  619. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  620. resF = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  621. initial=1,
  622. min=1,
  623. max=100)
  624. resF.SetName("value")
  625. self.win['surface']['draw']['res-fine'] = resF.GetId()
  626. resF.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  627. resSizer.Add(item=resF, flag=wx.ALL, border=3)
  628. gridSizer.Add(item=resSizer, pos=(0, 3), span=(1, 2))
  629. # style
  630. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  631. label=_("Coarse style:")),
  632. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  633. style = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  634. choices = [_("wire"),
  635. _("surface")])
  636. style.SetName("selection")
  637. self.win['surface']['draw']['style'] = style.GetId()
  638. style.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  639. gridSizer.Add(item=style, flag=wx.ALIGN_CENTER_VERTICAL,
  640. pos=(1, 1))
  641. # shading
  642. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  643. label=_("Shading:")),
  644. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  645. shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  646. choices = [_("flat"),
  647. _("gouraud")])
  648. shade.SetName("selection")
  649. self.win['surface']['draw']['shading'] = shade.GetId()
  650. shade.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  651. gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
  652. pos=(1, 3))
  653. # color
  654. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  655. label=_("Wire color:")),
  656. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  657. color = csel.ColourSelect(panel, id=wx.ID_ANY)
  658. color.SetName("colour")
  659. color.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceWireColor)
  660. self.win['surface']['draw']['color'] = color.GetId()
  661. gridSizer.Add(item=color, flag=wx.ALIGN_CENTER_VERTICAL,
  662. pos=(2, 1))
  663. boxSizer.Add(item=gridSizer, proportion=1,
  664. flag=wx.ALL | wx.EXPAND, border=3)
  665. pageSizer.Add(item=boxSizer, proportion=0,
  666. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  667. border=5)
  668. all = wx.Button(panel, id=wx.ID_ANY, label=_("All"))
  669. all.SetToolTipString(_("Use for all loaded surfaces"))
  670. # self.win['reset'] = reset.GetId()
  671. all.Bind(wx.EVT_BUTTON, self.OnSurfaceModeAll)
  672. gridSizer.Add(item=all, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
  673. pos=(2, 4))
  674. #
  675. # mask
  676. #
  677. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  678. label=" %s " % (_("Mask")))
  679. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  680. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  681. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  682. label=_("Mask zeros:")),
  683. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  684. elev = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  685. label=_("by elevation"))
  686. elev.Enable(False) # TODO: not implemented yet
  687. gridSizer.Add(item=elev, pos=(0, 1))
  688. color = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  689. label=_("by color"))
  690. color.Enable(False) # TODO: not implemented yet
  691. gridSizer.Add(item=color, pos=(0, 2))
  692. boxSizer.Add(item=gridSizer, proportion=1,
  693. flag=wx.ALL | wx.EXPAND, border=3)
  694. pageSizer.Add(item=boxSizer, proportion=0,
  695. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  696. border=5)
  697. #
  698. # position
  699. #
  700. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  701. label=" %s " % (_("Position")))
  702. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  703. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  704. # position
  705. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  706. label="X:"),
  707. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  708. x = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  709. initial=0,
  710. min=0,
  711. max=100)
  712. x.Enable(False) # TODO: not implemented yet
  713. gridSizer.Add(item=x, pos=(0, 1))
  714. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  715. label="X:"),
  716. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  717. y = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  718. initial=0,
  719. min=0,
  720. max=100)
  721. y.Enable(False) # TODO: not implemented yet
  722. gridSizer.Add(item=y, pos=(0, 3))
  723. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  724. label="X:"),
  725. pos=(0, 4), flag=wx.ALIGN_CENTER_VERTICAL)
  726. z = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  727. initial=0,
  728. min=0,
  729. max=100)
  730. z.Enable(False) # TODO: not implemented yet
  731. gridSizer.Add(item=z, pos=(0, 5))
  732. boxSizer.Add(item=gridSizer, proportion=1,
  733. flag=wx.ALL | wx.EXPAND, border=3)
  734. pageSizer.Add(item=boxSizer, proportion=0,
  735. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  736. border=5)
  737. panel.SetSizer(pageSizer)
  738. def __createVectorPage(self):
  739. """Create view settings page"""
  740. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  741. self.notebook.AddPage(page=panel,
  742. text=" %s " % _("Vector"))
  743. pageSizer = wx.BoxSizer(wx.VERTICAL)
  744. self.win['vector'] = {}
  745. #
  746. # vector lines
  747. #
  748. self.win['vector']['lines'] = {}
  749. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  750. label=" %s " % (_("Vector lines")))
  751. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  752. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  753. # width
  754. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  755. label=_("Width:")),
  756. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  757. width = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  758. initial=1,
  759. min=1,
  760. max=100)
  761. width.SetValue(UserSettings.Get(group='nviz', key='vector',
  762. subkey=['lines', 'width']))
  763. self.win['vector']['lines']['width'] = width.GetId()
  764. width.Bind(wx.EVT_SPINCTRL, self.OnVectorLines)
  765. gridSizer.Add(item=width, pos=(0, 1),
  766. flag=wx.ALIGN_CENTER_VERTICAL)
  767. gridSizer.AddGrowableCol(2)
  768. # color
  769. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  770. label=_("Color:")),
  771. pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL)
  772. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  773. colour=UserSettings.Get(group='nviz', key='vector',
  774. subkey=['lines', 'color']))
  775. self.win['vector']['lines']['color'] = color.GetId()
  776. color.Bind(csel.EVT_COLOURSELECT, self.OnVectorLines)
  777. gridSizer.Add(item=color, pos=(0, 4))
  778. gridSizer.AddGrowableCol(5)
  779. # display
  780. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  781. label=_("Display:")),
  782. pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
  783. display = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  784. choices = [_("on surface"),
  785. _("flat")])
  786. if UserSettings.Get(group='nviz', key='vector',
  787. subkey=['lines', 'flat']):
  788. display.SetSelection(1)
  789. else:
  790. display.SetSelection(0)
  791. self.win['vector']['lines']['flat'] = display.GetId()
  792. display.Bind(wx.EVT_CHOICE, self.OnVectorDisplay)
  793. gridSizer.Add(item=display, flag=wx.ALIGN_CENTER_VERTICAL,
  794. pos=(0, 7))
  795. surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
  796. style=wx.CB_SIMPLE | wx.CB_READONLY,
  797. choices=[])
  798. self.win['vector']['lines']['surface'] = surface.GetId()
  799. gridSizer.Add(item=surface,
  800. pos=(1, 0), span=(1, 8),
  801. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
  802. # high
  803. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  804. label=_("Hight above surface:")),
  805. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL,
  806. span=(1, 2))
  807. self.CreateControl(panel, dict=self.win['vector']['lines'], name='height', size=300)
  808. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['slider']),
  809. pos=(2, 2), span=(1, 6))
  810. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['spin']),
  811. pos=(3, 4),
  812. flag=wx.ALIGN_CENTER)
  813. boxSizer.Add(item=gridSizer, proportion=1,
  814. flag=wx.ALL | wx.EXPAND, border=3)
  815. pageSizer.Add(item=boxSizer, proportion=0,
  816. flag=wx.EXPAND | wx.ALL,
  817. border=5)
  818. panel.SetSizer(pageSizer)
  819. def __createSettingsPage(self):
  820. """Create settings page"""
  821. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  822. self.notebook.AddPage(page=panel,
  823. text=" %s " % _("Settings"))
  824. pageSizer = wx.BoxSizer(wx.VERTICAL)
  825. self.win['settings'] = {}
  826. #
  827. # general
  828. #
  829. self.win['settings']['general'] = {}
  830. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  831. label=" %s " % (_("General")))
  832. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  833. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  834. # background color
  835. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  836. label=_("Background color:")),
  837. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  838. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  839. colour=UserSettings.Get(group='nviz', key='settings',
  840. subkey=['general', 'bgcolor']))
  841. self.win['settings']['general']['bgcolor'] = color.GetId()
  842. color.Bind(csel.EVT_COLOURSELECT, self.OnSettings)
  843. gridSizer.Add(item=color, pos=(0, 1))
  844. boxSizer.Add(item=gridSizer, proportion=1,
  845. flag=wx.ALL | wx.EXPAND, border=3)
  846. pageSizer.Add(item=boxSizer, proportion=0,
  847. flag=wx.EXPAND | wx.ALL,
  848. border=5)
  849. panel.SetSizer(pageSizer)
  850. panel.SetSizer(pageSizer)
  851. def CreateControl(self, parent, dict, name, sliderHor=True, size=200):
  852. """Add control (Slider + SpinCtrl)"""
  853. dict[name] = {}
  854. if sliderHor:
  855. style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  856. wx.SL_BOTTOM
  857. sizeW = (size, -1)
  858. else:
  859. style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | \
  860. wx.SL_BOTTOM | wx.SL_INVERSE
  861. sizeW = (-1, size)
  862. slider = wx.Slider(parent=parent, id=wx.ID_ANY,
  863. value=self.settings[name]['value'],
  864. minValue=self.settings[name]['min'],
  865. maxValue=self.settings[name]['max'],
  866. style=style,
  867. size=sizeW)
  868. slider.Bind(wx.EVT_SCROLL, self.OnViewChange)
  869. slider.Bind(wx.EVT_SCROLL_CHANGED, self.OnViewChanged)
  870. dict[name]['slider'] = slider.GetId()
  871. spin = wx.SpinCtrl(parent=parent, id=wx.ID_ANY, size=(65, -1),
  872. initial=self.settings[name]['value'],
  873. min=self.settings[name]['min'],
  874. max=self.settings[name]['max'])
  875. # spin = wx.SpinButton(parent=parent, id=wx.ID_ANY)
  876. # spin.SetValue (self.settings[name]['value'])
  877. # spin.SetRange(self.settings[name]['min'],
  878. # self.settings[name]['max'])
  879. # no 'changed' event ... (FIXME)
  880. spin.Bind(wx.EVT_SPINCTRL, self.OnViewChangedSpin)
  881. dict[name]['spin'] = spin.GetId()
  882. def UpdateSettings(self):
  883. """Update dialog settings"""
  884. for control in ('height',
  885. 'persp',
  886. 'twist',
  887. 'z-exag'):
  888. for win in self.win['view'][control].itervalues():
  889. self.FindWindowById(win).SetValue(int(self.settings[control]['value']))
  890. self.FindWindowById(self.win['view']['pos']).Draw()
  891. self.FindWindowById(self.win['view']['pos']).Refresh(False)
  892. self.Refresh(False)
  893. def __GetWindowName(self, dict, id):
  894. for name in dict.iterkeys():
  895. if type(dict[name]) is type({}):
  896. for win in dict[name].itervalues():
  897. if win == id:
  898. return name
  899. else:
  900. if dict[name] == id:
  901. return name
  902. return None
  903. def OnViewChange(self, event):
  904. """Change view, render in quick mode"""
  905. # find control
  906. winName = self.__GetWindowName(self.win['view'], event.GetId())
  907. if not winName:
  908. return
  909. self.settings[winName]['value'] = event.GetInt()
  910. for win in self.win['view'][winName].itervalues():
  911. self.FindWindowById(win).SetValue(self.settings[winName]['value'])
  912. if winName in ('pos', 'height', 'twist', 'persp'):
  913. self.mapWindow.update['view'] = None
  914. else:
  915. self.mapWindow.update[winName] = None
  916. self.mapWindow.render = False
  917. self.mapWindow.Refresh(False)
  918. def OnViewChanged(self, event):
  919. """View changed, render in full resolution"""
  920. self.mapWindow.render = True
  921. self.mapWindow.Refresh(False)
  922. def OnViewChangedSpin(self, event):
  923. """View changed, render in full resolution"""
  924. self.OnViewChange(event)
  925. self.mapWindow.render = True
  926. self.mapWindow.Refresh(False)
  927. def OnResetView(self, event):
  928. """Reset to default view (view page)"""
  929. self.mapWindow.ResetView()
  930. self.UpdateSettings()
  931. self.mapWindow.Refresh(False)
  932. def OnLookAt(self, event):
  933. """Look at (view page)"""
  934. sel = event.GetSelection()
  935. if sel == 0: # top
  936. self.settings['pos']['x'] = 0.5
  937. self.settings['pos']['y'] = 0.5
  938. elif sel == 1: # north
  939. self.settings['pos']['x'] = 0.5
  940. self.settings['pos']['y'] = 0.0
  941. elif sel == 2: # south
  942. self.settings['pos']['x'] = 0.5
  943. self.settings['pos']['y'] = 1.0
  944. elif sel == 3: # east
  945. self.settings['pos']['x'] = 1.0
  946. self.settings['pos']['y'] = 0.5
  947. elif sel == 4: # west
  948. self.settings['pos']['x'] = 0.0
  949. self.settings['pos']['y'] = 0.5
  950. elif sel == 5: # north-west
  951. self.settings['pos']['x'] = 0.0
  952. self.settings['pos']['y'] = 0.0
  953. elif sel == 6: # north-east
  954. self.settings['pos']['x'] = 1.0
  955. self.settings['pos']['y'] = 0.0
  956. elif sel == 7: # south-east
  957. self.settings['pos']['x'] = 1.0
  958. self.settings['pos']['y'] = 1.0
  959. elif sel == 8: # south-west
  960. self.settings['pos']['x'] = 0.0
  961. self.settings['pos']['y'] = 1.0
  962. self.mapWindow.update['view'] = None
  963. self.UpdateSettings()
  964. self.mapWindow.Refresh(False)
  965. def OnSave(self, event):
  966. """OK button pressed
  967. Apply changes, update map and save settings of selected layer
  968. """
  969. #
  970. # apply changes
  971. #
  972. self.OnApply(None)
  973. #
  974. # save settings
  975. #
  976. type = self.mapWindow.GetSelectedLayer().type
  977. data = self.mapWindow.GetSelectedLayer(nviz=True)
  978. if data is None: # no settings
  979. data = {}
  980. if type == 'raster': # -> surface
  981. #
  982. # surface attributes
  983. #
  984. data['attribute'] = {}
  985. for attrb in ('topo', 'color', 'mask',
  986. 'transp', 'shine', 'emit'):
  987. use = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  988. if self.win['surface'][attrb]['required']: # map, constant
  989. if use == 0: # map
  990. map = True
  991. elif use == 1: # constant
  992. map = False
  993. else: # unset, map, constant
  994. if use == 0: # unset
  995. map = None
  996. elif use == 1: # map
  997. map = True
  998. elif use == 2: # constant
  999. map = False
  1000. if map is None:
  1001. continue
  1002. if map:
  1003. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1004. else:
  1005. if attrb == 'color':
  1006. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetColour()
  1007. else:
  1008. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1009. data['attribute'][attrb] = {}
  1010. data['attribute'][attrb]['map'] = map
  1011. data['attribute'][attrb]['value'] = value
  1012. #
  1013. # draw
  1014. #
  1015. data['draw'] = {}
  1016. for control in ('mode', 'shading', 'style'):
  1017. data['draw'][control] = self.FindWindowById(self.win['surface']['draw'][control]).GetSelection()
  1018. for control in ('res-coarse', 'res-fine'):
  1019. data['draw'][control] = self.FindWindowById(self.win['surface']['draw'][control]).GetValue()
  1020. self.mapWindow.SetLayerSettings(data)
  1021. def OnApply(self, event):
  1022. """Apply button pressed
  1023. Apply changes, update map
  1024. """
  1025. layer = self.mapWindow.GetSelectedLayer()
  1026. id = self.mapWindow.GetMapObjId(layer)
  1027. if layer.type == 'raster':
  1028. self.ApplySurface(id)
  1029. elif layer.type == 'vector':
  1030. self.ApplyVector(id)
  1031. self.ApplySettings()
  1032. self.mapWindow.Refresh(False)
  1033. def ApplySurface(self, id):
  1034. """Apply changes for surfaces"""
  1035. # surface attributes
  1036. for attrb in ('topo', 'color', 'mask',
  1037. 'transp', 'shine', 'emit'):
  1038. if self.mapWindow.update.has_key(attrb):
  1039. map, value = self.mapWindow.update[attrb]
  1040. if map is None: # unset
  1041. # only optional attributes
  1042. if attrb == 'mask':
  1043. # TODO: invert mask
  1044. # TODO: broken in NVIZ
  1045. self.mapWindow.nvizClass.UnsetSurfaceMask(id)
  1046. elif attrb == 'transp':
  1047. self.mapWindow.nvizClass.UnsetSurfaceTransp(id)
  1048. elif attrb == 'emit':
  1049. self.mapWindow.nvizClass.UnsetSurfaceEmit(id)
  1050. else:
  1051. if len(value) <= 0: # ignore empty values (TODO: warning)
  1052. continue
  1053. if attrb == 'topo':
  1054. self.mapWindow.nvizClass.SetSurfaceTopo(id, map, str(value))
  1055. elif attrb == 'color':
  1056. self.mapWindow.nvizClass.SetSurfaceColor(id, map, str(value))
  1057. elif attrb == 'mask':
  1058. # TODO: invert mask
  1059. # TODO: broken in NVIZ
  1060. self.mapWindow.nvizClass.SetSurfaceMask(id, False, str(value))
  1061. elif attrb == 'transp':
  1062. self.mapWindow.nvizClass.SetSurfaceTransp(id, map, str(value))
  1063. elif attrb == 'shine':
  1064. self.mapWindow.nvizClass.SetSurfaceShine(id, map, str(value))
  1065. elif attrb == 'emit':
  1066. self.mapWindow.nvizClass.SetSurfaceEmit(id, map, str(value))
  1067. del self.mapWindow.update[attrb]
  1068. # draw res
  1069. if self.mapWindow.update.has_key('draw-res'):
  1070. coarse, fine, all = self.mapWindow.update['draw-res']
  1071. if all:
  1072. self.mapWindow.nvizClass.SetSurfaceRes(-1, fine, coarse)
  1073. else:
  1074. self.mapWindow.nvizClass.SetSurfaceRes(id, fine, coarse)
  1075. # draw style
  1076. if self.mapWindow.update.has_key('draw-style'):
  1077. style, all = self.mapWindow.update['draw-style']
  1078. if all:
  1079. self.mapWindow.nvizClass.SetSurfaceStyle(-1, style)
  1080. else:
  1081. self.mapWindow.nvizClass.SetSurfaceStyle(id, style)
  1082. # wire color
  1083. if self.mapWindow.update.has_key('draw-color'):
  1084. color, all = self.mapWindow.update['draw-color']
  1085. if all:
  1086. self.mapWindow.nvizClass.SetWireColor(id, str(color))
  1087. else:
  1088. self.mapWindow.nvizClass.SetWireColor(-1, str(color))
  1089. def ApplyVector(self, id):
  1090. """Apply changes for vector"""
  1091. width = self.FindWindowById(self.win['vector']['lines']['width']).GetValue()
  1092. color = self.FindWindowById(self.win['vector']['lines']['color']).GetColour()
  1093. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1094. if self.FindWindowById(self.win['vector']['lines']['flat']).GetSelection() == 0:
  1095. flat = False
  1096. else:
  1097. flat = True
  1098. self.mapWindow.nvizClass.SetVectorLineMode(id, str(color), width, flat)
  1099. def ApplySettings(self):
  1100. """Apply changes in settings"""
  1101. # bgcolor
  1102. color = self.FindWindowById(self.win['settings']['general']['bgcolor']).GetColour()
  1103. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1104. self.mapWindow.nvizClass.SetBgColor(str(color))
  1105. def OnClose(self, event):
  1106. """Close button pressed
  1107. Close dialog
  1108. """
  1109. self.Hide()
  1110. def OnSurfaceUse(self, event):
  1111. """Surface attribute -- use -- map/constant"""
  1112. if not self.mapWindow.init:
  1113. return
  1114. # find attribute row
  1115. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1116. if not attrb:
  1117. return
  1118. selection = event.GetSelection()
  1119. if self.win['surface'][attrb]['required']: # no 'unset'
  1120. selection += 1
  1121. if selection == 0: # unset
  1122. useMap = None
  1123. value = ''
  1124. elif selection == 1: # map
  1125. useMap = True
  1126. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1127. elif selection == 2: # constant
  1128. useMap = False
  1129. if attrb == 'color':
  1130. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1131. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1132. else:
  1133. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1134. self.SetSurfaceUseMap(attrb, useMap)
  1135. self.mapWindow.update[attrb] = (useMap, str(value))
  1136. if self.parent.autoRender.IsChecked():
  1137. self.OnApply(None)
  1138. def SetSurfaceUseMap(self, attrb, map=None):
  1139. if attrb in ('topo', 'color', 'shine'):
  1140. incSel = -1 # decrement selection (no 'unset')
  1141. else:
  1142. incSel = 0
  1143. if map is True: # map
  1144. if attrb != 'topo': # changing map topography not allowed
  1145. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(True) # FIXME
  1146. if self.win['surface'][attrb]['const']:
  1147. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1148. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(1 + incSel)
  1149. elif map is False: # const
  1150. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1151. if self.win['surface'][attrb]['const']:
  1152. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(True)
  1153. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(2 + incSel)
  1154. else: # unset
  1155. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1156. if self.win['surface'][attrb]['const']:
  1157. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1158. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(0)
  1159. def OnSurfaceMap(self, event):
  1160. """Set surface attribute"""
  1161. if not self.mapWindow.init:
  1162. return
  1163. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1164. if not attrb:
  1165. return
  1166. selection = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  1167. if self.win['surface'][attrb]['required']:
  1168. selection += 1
  1169. if selection == 0: # unset
  1170. map = None
  1171. value = ''
  1172. elif selection == 1: # map
  1173. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1174. map = True
  1175. else: # constant
  1176. if attrb == 'color':
  1177. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1178. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1179. else:
  1180. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1181. map = False
  1182. self.mapWindow.update[attrb] = (map, str(value))
  1183. if self.parent.autoRender.IsChecked():
  1184. self.OnApply(None)
  1185. def OnSurfaceResolution(self, event):
  1186. """Draw resolution changed"""
  1187. self.SetSurfaceResolution()
  1188. def SetSurfaceResolution(self, all=False, apply=True):
  1189. """Set draw resolution"""
  1190. coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
  1191. fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
  1192. self.mapWindow.update['draw-res'] = (coarse, fine, all)
  1193. if apply and self.parent.autoRender.IsChecked():
  1194. self.OnApply(None)
  1195. def SetSurfaceMode(self, apply=True, all=False):
  1196. """Set draw mode
  1197. @param apply allow auto-rendering
  1198. """
  1199. value = 0
  1200. mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
  1201. if mode == 0: # coarse
  1202. value |= wxnviz.DM_WIRE
  1203. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1204. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
  1205. elif mode == 1: # fine
  1206. value |= wxnviz.DM_POLY
  1207. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
  1208. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1209. else: # both
  1210. value |= wxnviz.DM_WIRE_POLY
  1211. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1212. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1213. style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
  1214. if style == 0: # wire
  1215. value |= wxnviz.DM_GRID_WIRE
  1216. else: # surface
  1217. value |= wxnviz.DM_GRID_SURF
  1218. shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
  1219. if shade == 0:
  1220. value |= wxnviz.DM_FLAT
  1221. else: # surface
  1222. value |= wxnviz.DM_GOURAUD
  1223. self.mapWindow.update['draw-style'] = (value, all)
  1224. if apply and self.parent.autoRender.IsChecked():
  1225. self.OnApply(None)
  1226. def OnSurfaceMode(self, event):
  1227. """Set draw mode"""
  1228. self.SetSurfaceMode()
  1229. def OnSurfaceModeAll(self, event):
  1230. """Set draw mode (including wire color) for all loaded surfaces"""
  1231. self.SetSurfaceMode(apply=False, all=True)
  1232. self.SetSurfaceResolution(apply=False, all=True)
  1233. color = self.FindWindowById(self.win['surface']['draw']['color']).GetColour()
  1234. self.SetSurfaceWireColor(color, all=True)
  1235. def SetSurfaceWireColor(self, color, all=False):
  1236. """Set wire color"""
  1237. value = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1238. self.mapWindow.update['draw-color'] = (value, all)
  1239. if self.parent.autoRender.IsChecked():
  1240. self.OnApply(None)
  1241. def OnSurfaceWireColor(self, event):
  1242. """Set wire color"""
  1243. self.SetSurfaceWireColor(event.GetValue())
  1244. def OnVectorDisplay(self, event):
  1245. """Display vector lines on surface/flat"""
  1246. if event.GetSelection() == 0: # surface
  1247. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(True)
  1248. # set first found surface
  1249. ### TODO
  1250. else: # flat
  1251. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(False)
  1252. self.OnVectorLines(event)
  1253. event.Skip()
  1254. def OnVectorLines(self, event):
  1255. """Set vector lines mode, apply changes if auto-rendering is enabled"""
  1256. if self.parent.autoRender.IsChecked():
  1257. self.OnApply(None)
  1258. def OnSettings(self, event):
  1259. """Update settings, apply changes if auto-rendering is enabled"""
  1260. if self.parent.autoRender.IsChecked():
  1261. self.OnApply(None)
  1262. def UpdatePage(self, pageId):
  1263. """Update dialog (selected page)"""
  1264. layer = self.mapWindow.GetSelectedLayer()
  1265. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1266. if pageId == 'view':
  1267. max = self.settings['z-exag']['value'] * 10
  1268. for control in ('spin', 'slider'):
  1269. self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(0,
  1270. max)
  1271. elif pageId == 'surface':
  1272. if data is None: # use default values
  1273. #
  1274. # attributes
  1275. #
  1276. for attr in ('topo', 'color'):
  1277. self.SetSurfaceUseMap(attr, True) # -> map
  1278. if layer and layer.type == 'raster':
  1279. self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
  1280. else:
  1281. self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
  1282. if UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'map']) is False:
  1283. self.SetSurfaceUseMap('shine', False)
  1284. value = UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'value'])
  1285. self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
  1286. #
  1287. # draw
  1288. #
  1289. for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
  1290. win = self.FindWindowById(self.win['surface']['draw'][control])
  1291. name = win.GetName()
  1292. if name == "selection":
  1293. win.SetSelection(value)
  1294. elif name == "colour":
  1295. win.SetColour(value)
  1296. else:
  1297. win.SetValue(value)
  1298. # enable/disable res widget + set draw mode
  1299. self.SetSurfaceMode()
  1300. color = self.FindWindowById(self.win['surface']['draw']['color'])
  1301. self.SetSurfaceWireColor(color.GetColour())
  1302. elif layer.type == 'raster':
  1303. # surface attributes
  1304. for attr in data['attr']:
  1305. if attr['map']:
  1306. win = self.FindWindowById(self.win['surface'][attr]['map'])
  1307. else:
  1308. win = self.FindWindowById(self.win['surface'][attr]['const'])
  1309. win.SetValue(data['value'])
  1310. elif pageId == 'vector':
  1311. pass
  1312. def SetPage(self, name):
  1313. """Get named page"""
  1314. self.notebook.SetSelection(self.page[name])
  1315. class ViewPositionWindow(wx.Window):
  1316. """Position control window (for NvizToolWindow)"""
  1317. def __init__(self, parent, id, mapwindow,
  1318. pos=wx.DefaultPosition,
  1319. size=wx.DefaultSize, settings={}):
  1320. self.settings = settings
  1321. self.mapWindow = mapwindow
  1322. wx.Window.__init__(self, parent, id, pos, size)
  1323. self.SetBackgroundColour("WHITE")
  1324. self.pdc = wx.PseudoDC()
  1325. self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
  1326. self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
  1327. self.Draw()
  1328. self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
  1329. self.Bind(wx.EVT_PAINT, self.OnPaint)
  1330. # self.Bind(wx.EVT_MOTION, self.OnMouse)
  1331. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
  1332. def Draw(self, pos=None):
  1333. w, h = self.GetClientSize()
  1334. if pos is None:
  1335. x = self.settings['pos']['x']
  1336. y = self.settings['pos']['y']
  1337. x = x * w
  1338. y = y * h
  1339. else:
  1340. x, y = pos
  1341. self.pdc.Clear()
  1342. self.pdc.BeginDrawing()
  1343. self.pdc.DrawLine(w / 2, h / 2, x, y)
  1344. self.pdc.DrawCircle(x, y, 5)
  1345. self.pdc.EndDrawing()
  1346. def OnPaint(self, event):
  1347. dc = wx.BufferedPaintDC(self)
  1348. dc.SetBackground(wx.Brush("White"))
  1349. dc.Clear()
  1350. self.PrepareDC(dc)
  1351. self.pdc.DrawToDC(dc)
  1352. def OnMouse(self, event):
  1353. if event.LeftIsDown():
  1354. x, y = event.GetPosition()
  1355. self.Draw(pos=(x, y))
  1356. self.Refresh(False)
  1357. w, h = self.GetClientSize()
  1358. x = float(x) / w
  1359. y = float(y) / h
  1360. self.settings['pos']['x'] = x
  1361. self.settings['pos']['y'] = y
  1362. self.mapWindow.update['view'] = None
  1363. self.mapWindow.render = False
  1364. if event.LeftUp():
  1365. self.mapWindow.render = True
  1366. self.mapWindow.Refresh(eraseBackground=False)