nviz.py 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556
  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. # view page
  344. self.__createViewPage()
  345. # surface page
  346. self.__createSurfacePage()
  347. self.UpdatePage('surface')
  348. # vector page
  349. self.__createVectorPage()
  350. self.UpdatePage('vector')
  351. # settings page
  352. self.__createSettingsPage()
  353. self.UpdatePage('settings')
  354. mainSizer.Add(item=self.notebook, proportion=1,
  355. flag=wx.EXPAND | wx.ALL, border=5)
  356. #
  357. # button (see menuform)
  358. #
  359. btnCancel = wx.Button(self, wx.ID_CANCEL)
  360. btnApply = wx.Button(self, wx.ID_APPLY)
  361. btnSave = wx.Button(self, wx.ID_SAVE)
  362. btnSave.SetDefault()
  363. # bindings
  364. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  365. btnApply.SetToolTipString(_("Apply changes and update display"))
  366. btnApply.SetDefault()
  367. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  368. btnSave.SetToolTipString(_("Apply changes, update display and save changes to layer settings"))
  369. btnCancel.Bind(wx.EVT_BUTTON, self.OnClose)
  370. btnCancel.SetToolTipString(_("Hide dialog and ignore changes"))
  371. # sizer
  372. btnSizer = wx.StdDialogButtonSizer()
  373. btnSizer.AddButton(btnApply)
  374. btnSizer.AddButton(btnCancel)
  375. btnSizer.AddButton(btnSave)
  376. btnSizer.Realize()
  377. mainSizer.Add(item=btnSizer, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL,
  378. border=5)
  379. #
  380. # bindings
  381. #
  382. self.Bind(wx.EVT_CLOSE, self.OnClose)
  383. #
  384. # layout
  385. #
  386. self.SetSizer(mainSizer)
  387. mainSizer.Fit(self)
  388. def __createViewPage(self):
  389. """Create view settings page"""
  390. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  391. self.notebook.AddPage(page=panel,
  392. text=" %s " % _("View"))
  393. pageSizer = wx.BoxSizer(wx.VERTICAL)
  394. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  395. self.win['view'] = {}
  396. # position
  397. posSizer = wx.GridBagSizer(vgap=3, hgap=3)
  398. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("W")),
  399. pos=(1, 0), flag=wx.ALIGN_CENTER)
  400. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("N")),
  401. pos=(0, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM)
  402. viewPos = ViewPositionWindow(panel, id=wx.ID_ANY, size=(175, 175),
  403. settings=self.settings, mapwindow=self.mapWindow)
  404. self.win['view']['pos'] = viewPos.GetId()
  405. posSizer.Add(item=viewPos,
  406. pos=(1, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL)
  407. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("S")),
  408. pos=(2, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_TOP)
  409. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("E")),
  410. pos=(1, 2), flag=wx.ALIGN_CENTER)
  411. gridSizer.Add(item=posSizer, pos=(0, 0))
  412. # perspective
  413. self.CreateControl(panel, dict=self.win['view'], name='persp')
  414. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Perspective:")),
  415. pos=(1, 0), flag=wx.ALIGN_CENTER)
  416. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['slider']), pos=(2, 0))
  417. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['spin']), pos=(3, 0),
  418. flag=wx.ALIGN_CENTER)
  419. # twist
  420. self.CreateControl(panel, dict=self.win['view'], name='twist')
  421. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Twist:")),
  422. pos=(1, 1), flag=wx.ALIGN_CENTER)
  423. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['slider']), pos=(2, 1))
  424. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['spin']), pos=(3, 1),
  425. flag=wx.ALIGN_CENTER)
  426. # height + z-exag
  427. self.CreateControl(panel, dict=self.win['view'], name='height', sliderHor=False)
  428. self.CreateControl(panel, dict=self.win['view'], name='z-exag', sliderHor=False)
  429. heightSizer = wx.GridBagSizer(vgap=3, hgap=3)
  430. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Height:")),
  431. pos=(0, 0), flag=wx.ALIGN_LEFT, span=(1, 2))
  432. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['slider']),
  433. flag=wx.ALIGN_RIGHT, pos=(1, 0))
  434. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['spin']),
  435. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  436. wx.BOTTOM | wx.RIGHT, pos=(1, 1))
  437. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Z-exag:")),
  438. pos=(0, 2), flag=wx.ALIGN_LEFT, span=(1, 2))
  439. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['slider']),
  440. flag=wx.ALIGN_RIGHT, pos=(1, 2))
  441. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['spin']),
  442. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  443. wx.BOTTOM | wx.RIGHT, pos=(1, 3))
  444. gridSizer.Add(item=heightSizer, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  445. # view setup + reset
  446. viewSizer = wx.BoxSizer(wx.HORIZONTAL)
  447. viewSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY,
  448. label=_("Look at:")),
  449. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
  450. viewType = wx.Choice (parent=panel, id=wx.ID_ANY, size=(125, -1),
  451. choices = [_("top"),
  452. _("north"),
  453. _("south"),
  454. _("east"),
  455. _("west"),
  456. _("north-west"),
  457. _("north-east"),
  458. _("south-east"),
  459. _("south-west")])
  460. viewType.SetSelection(0)
  461. viewType.Bind(wx.EVT_CHOICE, self.OnLookAt)
  462. # self.win['lookAt'] = viewType.GetId()
  463. viewSizer.Add(item=viewType, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
  464. border=5)
  465. reset = wx.Button(panel, id=wx.ID_ANY, label=_("Reset"))
  466. reset.SetToolTipString(_("Reset to default view"))
  467. # self.win['reset'] = reset.GetId()
  468. reset.Bind(wx.EVT_BUTTON, self.OnResetView)
  469. viewSizer.Add(item=reset, proportion=1,
  470. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT,
  471. border=5)
  472. gridSizer.AddGrowableCol(3)
  473. gridSizer.Add(item=viewSizer, pos=(4, 0), span=(1, 2),
  474. flag=wx.EXPAND)
  475. # body
  476. pageSizer.Add(item=gridSizer, proportion=1,
  477. flag=wx.EXPAND | wx.ALL,
  478. border=5)
  479. panel.SetSizer(pageSizer)
  480. def __createSurfacePage(self):
  481. """Create view settings page"""
  482. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  483. # panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY)
  484. # panel.SetupScrolling(scroll_x=True, scroll_y=True)
  485. self.notebook.AddPage(page=panel,
  486. text=" %s " % _("Surface"))
  487. pageSizer = wx.BoxSizer(wx.VERTICAL)
  488. self.win['surface'] = {}
  489. #
  490. # surface attributes
  491. #
  492. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  493. label=" %s " % (_("Surface attributes")))
  494. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  495. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  496. # labels
  497. # col = 0
  498. # for type in (_("Attribute"),
  499. # _("Use"),
  500. # _("Map"),
  501. # _("Constant")):
  502. # gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  503. # label=type),
  504. # pos=(0, col))
  505. # col += 1
  506. # type
  507. self.win['surface']['attr'] = {}
  508. row = 0
  509. for code, attrb in (('topo', _("Topography")),
  510. ('color', _("Color")),
  511. ('mask', _("Mask")),
  512. ('transp', _("Transparency")),
  513. ('shine', _("Shininess")),
  514. ('emit', _("Emission"))):
  515. self.win['surface'][code] = {}
  516. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  517. label=attrb + ':'),
  518. pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  519. use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  520. choices = [_("map")])
  521. if code not in ('topo', 'color', 'shine'):
  522. use.Insert(item=_("unset"), pos=0)
  523. self.win['surface'][code]['required'] = False
  524. else:
  525. self.win['surface'][code]['required'] = True
  526. if code != 'mask':
  527. use.Append(item=_('constant'))
  528. self.win['surface'][code]['use'] = use.GetId()
  529. use.Bind(wx.EVT_CHOICE, self.OnSurfaceUse)
  530. gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
  531. pos=(row, 1))
  532. map = gselect.Select(parent=panel, id=wx.ID_ANY,
  533. # size=globalvar.DIALOG_GSELECT_SIZE,
  534. size=(200, -1),
  535. type="raster")
  536. self.win['surface'][code]['map'] = map.GetId() - 1 # FIXME
  537. map.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  538. # changing map topography not allowed
  539. if code == 'topo':
  540. map.Enable(False)
  541. gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
  542. pos=(row, 2))
  543. if code == 'color':
  544. value = csel.ColourSelect(panel, id=wx.ID_ANY,
  545. colour=UserSettings.Get(group='nviz', key='surface',
  546. subkey=['color', 'value']))
  547. value.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceMap)
  548. elif code == 'mask':
  549. value = None
  550. else:
  551. value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  552. initial=0)
  553. if code == 'topo':
  554. value.SetRange(minVal=-1e9, maxVal=1e9)
  555. elif code in ('shine', 'transp', 'emit'):
  556. value.SetRange(minVal=0, maxVal=255)
  557. else:
  558. value.SetRange(minVal=0, maxVal=100)
  559. value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  560. if value:
  561. self.win['surface'][code]['const'] = value.GetId()
  562. value.Enable(False)
  563. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  564. pos=(row, 3))
  565. else:
  566. self.win['surface'][code]['const'] = None
  567. self.SetSurfaceUseMap(code) # -> enable map / disable constant
  568. row += 1
  569. boxSizer.Add(item=gridSizer, proportion=1,
  570. flag=wx.ALL | wx.EXPAND, border=3)
  571. pageSizer.Add(item=boxSizer, proportion=0,
  572. flag=wx.EXPAND | wx.ALL,
  573. border=5)
  574. #
  575. # draw
  576. #
  577. self.win['surface']['draw'] = {}
  578. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  579. label=" %s " % (_("Draw")))
  580. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  581. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  582. gridSizer.AddGrowableCol(4)
  583. # mode
  584. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  585. label=_("Mode:")),
  586. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  587. mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  588. choices = [_("coarse"),
  589. _("fine"),
  590. _("both")])
  591. mode.SetName("selection")
  592. mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  593. self.win['surface']['draw']['mode'] = mode.GetId()
  594. gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
  595. pos=(0, 1))
  596. # resolution (mode)
  597. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  598. label=_("Resolution:")),
  599. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  600. resSizer = wx.BoxSizer(wx.HORIZONTAL)
  601. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  602. label=_("coarse:")),
  603. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  604. resC = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  605. initial=1,
  606. min=1,
  607. max=100)
  608. resC.SetName("value")
  609. self.win['surface']['draw']['res-coarse'] = resC.GetId()
  610. resC.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  611. resSizer.Add(item=resC, flag=wx.ALL, border=3)
  612. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  613. label=_("fine:")),
  614. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  615. resF = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  616. initial=1,
  617. min=1,
  618. max=100)
  619. resF.SetName("value")
  620. self.win['surface']['draw']['res-fine'] = resF.GetId()
  621. resF.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  622. resSizer.Add(item=resF, flag=wx.ALL, border=3)
  623. gridSizer.Add(item=resSizer, pos=(0, 3), span=(1, 2))
  624. # style
  625. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  626. label=_("Coarse style:")),
  627. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  628. style = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  629. choices = [_("wire"),
  630. _("surface")])
  631. style.SetName("selection")
  632. self.win['surface']['draw']['style'] = style.GetId()
  633. style.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  634. gridSizer.Add(item=style, flag=wx.ALIGN_CENTER_VERTICAL,
  635. pos=(1, 1))
  636. # shading
  637. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  638. label=_("Shading:")),
  639. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  640. shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  641. choices = [_("flat"),
  642. _("gouraud")])
  643. shade.SetName("selection")
  644. self.win['surface']['draw']['shading'] = shade.GetId()
  645. shade.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  646. gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
  647. pos=(1, 3))
  648. # color
  649. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  650. label=_("Wire color:")),
  651. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  652. color = csel.ColourSelect(panel, id=wx.ID_ANY)
  653. color.SetName("colour")
  654. color.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceWireColor)
  655. self.win['surface']['draw']['color'] = color.GetId()
  656. gridSizer.Add(item=color, flag=wx.ALIGN_CENTER_VERTICAL,
  657. pos=(2, 1))
  658. boxSizer.Add(item=gridSizer, proportion=1,
  659. flag=wx.ALL | wx.EXPAND, border=3)
  660. pageSizer.Add(item=boxSizer, proportion=0,
  661. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  662. border=5)
  663. all = wx.Button(panel, id=wx.ID_ANY, label=_("All"))
  664. all.SetToolTipString(_("Use for all loaded surfaces"))
  665. # self.win['reset'] = reset.GetId()
  666. all.Bind(wx.EVT_BUTTON, self.OnSurfaceModeAll)
  667. gridSizer.Add(item=all, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
  668. pos=(2, 4))
  669. #
  670. # mask
  671. #
  672. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  673. label=" %s " % (_("Mask")))
  674. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  675. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  676. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  677. label=_("Mask zeros:")),
  678. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  679. elev = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  680. label=_("by elevation"))
  681. elev.Enable(False) # TODO: not implemented yet
  682. gridSizer.Add(item=elev, pos=(0, 1))
  683. color = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  684. label=_("by color"))
  685. color.Enable(False) # TODO: not implemented yet
  686. gridSizer.Add(item=color, pos=(0, 2))
  687. boxSizer.Add(item=gridSizer, proportion=1,
  688. flag=wx.ALL | wx.EXPAND, border=3)
  689. pageSizer.Add(item=boxSizer, proportion=0,
  690. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  691. border=5)
  692. #
  693. # position
  694. #
  695. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  696. label=" %s " % (_("Position")))
  697. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  698. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  699. # position
  700. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  701. label="X:"),
  702. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  703. x = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  704. initial=0,
  705. min=0,
  706. max=100)
  707. x.Enable(False) # TODO: not implemented yet
  708. gridSizer.Add(item=x, pos=(0, 1))
  709. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  710. label="X:"),
  711. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  712. y = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  713. initial=0,
  714. min=0,
  715. max=100)
  716. y.Enable(False) # TODO: not implemented yet
  717. gridSizer.Add(item=y, pos=(0, 3))
  718. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  719. label="X:"),
  720. pos=(0, 4), flag=wx.ALIGN_CENTER_VERTICAL)
  721. z = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  722. initial=0,
  723. min=0,
  724. max=100)
  725. z.Enable(False) # TODO: not implemented yet
  726. gridSizer.Add(item=z, pos=(0, 5))
  727. boxSizer.Add(item=gridSizer, proportion=1,
  728. flag=wx.ALL | wx.EXPAND, border=3)
  729. pageSizer.Add(item=boxSizer, proportion=0,
  730. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  731. border=5)
  732. panel.SetSizer(pageSizer)
  733. def __createVectorPage(self):
  734. """Create view settings page"""
  735. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  736. self.notebook.AddPage(page=panel,
  737. text=" %s " % _("Vector"))
  738. pageSizer = wx.BoxSizer(wx.VERTICAL)
  739. self.win['vector'] = {}
  740. #
  741. # vector lines
  742. #
  743. self.win['vector']['lines'] = {}
  744. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  745. label=" %s " % (_("Vector lines")))
  746. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  747. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  748. # width
  749. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  750. label=_("Width:")),
  751. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  752. width = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  753. initial=1,
  754. min=1,
  755. max=100) # TODO
  756. # width.SetName("value")
  757. # self.win['vector']['lines']['width'] = width.GetId()
  758. # width.Bind(wx.EVT_SPINCTRL, self.OnVectorWidth)
  759. gridSizer.Add(item=width, pos=(0, 1),
  760. flag=wx.ALIGN_CENTER_VERTICAL)
  761. gridSizer.AddGrowableCol(2)
  762. # color
  763. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  764. label=_("Color:")),
  765. pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL)
  766. color = csel.ColourSelect(panel, id=wx.ID_ANY)
  767. gridSizer.Add(item=color, pos=(0, 4))
  768. gridSizer.AddGrowableCol(5)
  769. # display
  770. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  771. label=_("Display:")),
  772. pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
  773. display = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  774. choices = [_("on surface"),
  775. _("flat")])
  776. display.SetSelection(0)
  777. display.Bind(wx.EVT_CHOICE, self.OnVectorDisplay)
  778. gridSizer.Add(item=display, flag=wx.ALIGN_CENTER_VERTICAL,
  779. pos=(0, 7))
  780. surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
  781. style=wx.CB_SIMPLE | wx.CB_READONLY,
  782. choices=[])
  783. self.win['vector']['lines']['surface'] = surface.GetId()
  784. gridSizer.Add(item=surface,
  785. pos=(1, 0), span=(1, 8),
  786. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
  787. # high
  788. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  789. label=_("Hight above surface:")),
  790. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL,
  791. span=(1, 2))
  792. self.CreateControl(panel, dict=self.win['vector']['lines'], name='height', size=300)
  793. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['slider']),
  794. pos=(2, 2), span=(1, 6))
  795. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['spin']),
  796. pos=(3, 4),
  797. flag=wx.ALIGN_CENTER)
  798. boxSizer.Add(item=gridSizer, proportion=1,
  799. flag=wx.ALL | wx.EXPAND, border=3)
  800. pageSizer.Add(item=boxSizer, proportion=0,
  801. flag=wx.EXPAND | wx.ALL,
  802. border=5)
  803. panel.SetSizer(pageSizer)
  804. def __createSettingsPage(self):
  805. """Create settings page"""
  806. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  807. self.notebook.AddPage(page=panel,
  808. text=" %s " % _("Settings"))
  809. pageSizer = wx.BoxSizer(wx.VERTICAL)
  810. self.win['settings'] = {}
  811. panel.SetSizer(pageSizer)
  812. def CreateControl(self, parent, dict, name, sliderHor=True, size=200):
  813. """Add control (Slider + SpinCtrl)"""
  814. dict[name] = {}
  815. if sliderHor:
  816. style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  817. wx.SL_BOTTOM
  818. sizeW = (size, -1)
  819. else:
  820. style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | \
  821. wx.SL_BOTTOM | wx.SL_INVERSE
  822. sizeW = (-1, size)
  823. slider = wx.Slider(parent=parent, id=wx.ID_ANY,
  824. value=self.settings[name]['value'],
  825. minValue=self.settings[name]['min'],
  826. maxValue=self.settings[name]['max'],
  827. style=style,
  828. size=sizeW)
  829. slider.Bind(wx.EVT_SCROLL, self.OnViewChange)
  830. slider.Bind(wx.EVT_SCROLL_CHANGED, self.OnViewChanged)
  831. dict[name]['slider'] = slider.GetId()
  832. spin = wx.SpinCtrl(parent=parent, id=wx.ID_ANY, size=(65, -1),
  833. initial=self.settings[name]['value'],
  834. min=self.settings[name]['min'],
  835. max=self.settings[name]['max'])
  836. # spin = wx.SpinButton(parent=parent, id=wx.ID_ANY)
  837. # spin.SetValue (self.settings[name]['value'])
  838. # spin.SetRange(self.settings[name]['min'],
  839. # self.settings[name]['max'])
  840. # no 'changed' event ... (FIXME)
  841. spin.Bind(wx.EVT_SPINCTRL, self.OnViewChangedSpin)
  842. dict[name]['spin'] = spin.GetId()
  843. def UpdateSettings(self):
  844. """Update dialog settings"""
  845. for control in ('height',
  846. 'persp',
  847. 'twist',
  848. 'z-exag'):
  849. for win in self.win['view'][control].itervalues():
  850. self.FindWindowById(win).SetValue(int(self.settings[control]['value']))
  851. self.FindWindowById(self.win['view']['pos']).Draw()
  852. self.FindWindowById(self.win['view']['pos']).Refresh(False)
  853. self.Refresh(False)
  854. def __GetWindowName(self, dict, id):
  855. for name in dict.iterkeys():
  856. if type(dict[name]) is type({}):
  857. for win in dict[name].itervalues():
  858. if win == id:
  859. return name
  860. else:
  861. if dict[name] == id:
  862. return name
  863. return None
  864. def OnViewChange(self, event):
  865. """Change view, render in quick mode"""
  866. # find control
  867. winName = self.__GetWindowName(self.win['view'], event.GetId())
  868. if not winName:
  869. return
  870. self.settings[winName]['value'] = event.GetInt()
  871. for win in self.win['view'][winName].itervalues():
  872. self.FindWindowById(win).SetValue(self.settings[winName]['value'])
  873. if winName in ('pos', 'height', 'twist', 'persp'):
  874. self.mapWindow.update['view'] = None
  875. else:
  876. self.mapWindow.update[winName] = None
  877. self.mapWindow.render = False
  878. self.mapWindow.Refresh(False)
  879. def OnViewChanged(self, event):
  880. """View changed, render in full resolution"""
  881. self.mapWindow.render = True
  882. self.mapWindow.Refresh(False)
  883. def OnViewChangedSpin(self, event):
  884. """View changed, render in full resolution"""
  885. self.OnViewChange(event)
  886. self.mapWindow.render = True
  887. self.mapWindow.Refresh(False)
  888. def OnResetView(self, event):
  889. """Reset to default view (view page)"""
  890. self.mapWindow.ResetView()
  891. self.UpdateSettings()
  892. self.mapWindow.Refresh(False)
  893. def OnLookAt(self, event):
  894. """Look at (view page)"""
  895. sel = event.GetSelection()
  896. if sel == 0: # top
  897. self.settings['pos']['x'] = 0.5
  898. self.settings['pos']['y'] = 0.5
  899. elif sel == 1: # north
  900. self.settings['pos']['x'] = 0.5
  901. self.settings['pos']['y'] = 0.0
  902. elif sel == 2: # south
  903. self.settings['pos']['x'] = 0.5
  904. self.settings['pos']['y'] = 1.0
  905. elif sel == 3: # east
  906. self.settings['pos']['x'] = 1.0
  907. self.settings['pos']['y'] = 0.5
  908. elif sel == 4: # west
  909. self.settings['pos']['x'] = 0.0
  910. self.settings['pos']['y'] = 0.5
  911. elif sel == 5: # north-west
  912. self.settings['pos']['x'] = 0.0
  913. self.settings['pos']['y'] = 0.0
  914. elif sel == 6: # north-east
  915. self.settings['pos']['x'] = 1.0
  916. self.settings['pos']['y'] = 0.0
  917. elif sel == 7: # south-east
  918. self.settings['pos']['x'] = 1.0
  919. self.settings['pos']['y'] = 1.0
  920. elif sel == 8: # south-west
  921. self.settings['pos']['x'] = 0.0
  922. self.settings['pos']['y'] = 1.0
  923. self.mapWindow.update['view'] = None
  924. self.UpdateSettings()
  925. self.mapWindow.Refresh(False)
  926. def OnSave(self, event):
  927. """OK button pressed
  928. Apply changes, update map and save settings of selected layer
  929. """
  930. #
  931. # apply changes
  932. #
  933. self.OnApply(None)
  934. #
  935. # save settings
  936. #
  937. type = self.mapWindow.GetSelectedLayer().type
  938. data = self.mapWindow.GetSelectedLayer(nviz=True)
  939. if data is None: # no settings
  940. data = {}
  941. if type == 'raster': # -> surface
  942. #
  943. # surface attributes
  944. #
  945. data['attribute'] = {}
  946. for attrb in ('topo', 'color', 'mask',
  947. 'transp', 'shine', 'emit'):
  948. use = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  949. if self.win['surface'][attrb]['required']: # map, constant
  950. if use == 0: # map
  951. map = True
  952. elif use == 1: # constant
  953. map = False
  954. else: # unset, map, constant
  955. if use == 0: # unset
  956. map = None
  957. elif use == 1: # map
  958. map = True
  959. elif use == 2: # constant
  960. map = False
  961. if map is None:
  962. continue
  963. if map:
  964. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  965. else:
  966. if attrb == 'color':
  967. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetColour()
  968. else:
  969. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  970. data['attribute'][attrb] = {}
  971. data['attribute'][attrb]['map'] = map
  972. data['attribute'][attrb]['value'] = value
  973. #
  974. # draw
  975. #
  976. data['draw'] = {}
  977. for control in ('mode', 'shading', 'style'):
  978. data['draw'][control] = self.FindWindowById(self.win['surface']['draw'][control]).GetSelection()
  979. for control in ('res-coarse', 'res-fine'):
  980. data['draw'][control] = self.FindWindowById(self.win['surface']['draw'][control]).GetValue()
  981. self.mapWindow.SetLayerSettings(data)
  982. def OnApply(self, event):
  983. """Apply button pressed
  984. Apply changes, update map
  985. """
  986. layer = self.mapWindow.GetSelectedLayer()
  987. id = self.mapWindow.GetMapObjId(layer)
  988. #
  989. # surface
  990. #
  991. # surface attributes
  992. for attrb in ('topo', 'color', 'mask',
  993. 'transp', 'shine', 'emit'):
  994. if self.mapWindow.update.has_key(attrb):
  995. map, value = self.mapWindow.update[attrb]
  996. if map is None: # unset
  997. # only optional attributes
  998. if attrb == 'mask':
  999. # TODO: invert mask
  1000. # TODO: broken in NVIZ
  1001. self.mapWindow.nvizClass.UnsetSurfaceMask(id)
  1002. elif attrb == 'transp':
  1003. self.mapWindow.nvizClass.UnsetSurfaceTransp(id)
  1004. elif attrb == 'emit':
  1005. self.mapWindow.nvizClass.UnsetSurfaceEmit(id)
  1006. else:
  1007. if len(value) <= 0: # ignore empty values (TODO: warning)
  1008. continue
  1009. if attrb == 'topo':
  1010. self.mapWindow.nvizClass.SetSurfaceTopo(id, map, str(value))
  1011. elif attrb == 'color':
  1012. self.mapWindow.nvizClass.SetSurfaceColor(id, map, str(value))
  1013. elif attrb == 'mask':
  1014. # TODO: invert mask
  1015. # TODO: broken in NVIZ
  1016. self.mapWindow.nvizClass.SetSurfaceMask(id, False, str(value))
  1017. elif attrb == 'transp':
  1018. self.mapWindow.nvizClass.SetSurfaceTransp(id, map, str(value))
  1019. elif attrb == 'shine':
  1020. self.mapWindow.nvizClass.SetSurfaceShine(id, map, str(value))
  1021. elif attrb == 'emit':
  1022. self.mapWindow.nvizClass.SetSurfaceEmit(id, map, str(value))
  1023. del self.mapWindow.update[attrb]
  1024. # draw res
  1025. if self.mapWindow.update.has_key('draw-res'):
  1026. coarse, fine, all = self.mapWindow.update['draw-res']
  1027. if all:
  1028. self.mapWindow.nvizClass.SetSurfaceRes(-1, fine, coarse)
  1029. else:
  1030. self.mapWindow.nvizClass.SetSurfaceRes(id, fine, coarse)
  1031. # draw style
  1032. if self.mapWindow.update.has_key('draw-style'):
  1033. style, all = self.mapWindow.update['draw-style']
  1034. if all:
  1035. self.mapWindow.nvizClass.SetSurfaceStyle(-1, style)
  1036. else:
  1037. self.mapWindow.nvizClass.SetSurfaceStyle(id, style)
  1038. # wire color
  1039. if self.mapWindow.update.has_key('draw-color'):
  1040. color, all = self.mapWindow.update['draw-color']
  1041. if all:
  1042. self.mapWindow.nvizClass.SetWireColor(id, str(color))
  1043. else:
  1044. self.mapWindow.nvizClass.SetWireColor(-1, str(color))
  1045. self.mapWindow.Refresh(False)
  1046. def OnClose(self, event):
  1047. """Close button pressed
  1048. Close dialog
  1049. """
  1050. self.Hide()
  1051. def OnSurfaceUse(self, event):
  1052. """Surface attribute -- use -- map/constant"""
  1053. if not self.mapWindow.init:
  1054. return
  1055. # find attribute row
  1056. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1057. if not attrb:
  1058. return
  1059. selection = event.GetSelection()
  1060. if self.win['surface'][attrb]['required']: # no 'unset'
  1061. selection += 1
  1062. if selection == 0: # unset
  1063. useMap = None
  1064. value = ''
  1065. elif selection == 1: # map
  1066. useMap = True
  1067. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1068. elif selection == 2: # constant
  1069. useMap = False
  1070. if attrb == 'color':
  1071. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1072. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1073. else:
  1074. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1075. self.SetSurfaceUseMap(attrb, useMap)
  1076. self.mapWindow.update[attrb] = (useMap, str(value))
  1077. if self.parent.autoRender.IsChecked():
  1078. self.OnApply(None)
  1079. def SetSurfaceUseMap(self, attrb, map=None):
  1080. if attrb in ('topo', 'color', 'shine'):
  1081. incSel = -1 # decrement selection (no 'unset')
  1082. else:
  1083. incSel = 0
  1084. if map is True: # map
  1085. if attrb != 'topo': # changing map topography not allowed
  1086. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(True) # FIXME
  1087. if self.win['surface'][attrb]['const']:
  1088. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1089. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(1 + incSel)
  1090. elif map is False: # const
  1091. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1092. if self.win['surface'][attrb]['const']:
  1093. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(True)
  1094. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(2 + incSel)
  1095. else: # unset
  1096. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1097. if self.win['surface'][attrb]['const']:
  1098. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1099. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(0)
  1100. def OnSurfaceMap(self, event):
  1101. """Set surface attribute"""
  1102. if not self.mapWindow.init:
  1103. return
  1104. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1105. if not attrb:
  1106. return
  1107. selection = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  1108. if self.win['surface'][attrb]['required']:
  1109. selection += 1
  1110. if selection == 0: # unset
  1111. map = None
  1112. value = ''
  1113. elif selection == 1: # map
  1114. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1115. map = True
  1116. else: # constant
  1117. if attrb == 'color':
  1118. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1119. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1120. else:
  1121. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1122. map = False
  1123. self.mapWindow.update[attrb] = (map, str(value))
  1124. if self.parent.autoRender.IsChecked():
  1125. self.OnApply(None)
  1126. def OnSurfaceResolution(self, event):
  1127. """Draw resolution changed"""
  1128. self.SetSurfaceResolution()
  1129. def SetSurfaceResolution(self, all=False, apply=True):
  1130. """Set draw resolution"""
  1131. coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
  1132. fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
  1133. self.mapWindow.update['draw-res'] = (coarse, fine, all)
  1134. if apply and self.parent.autoRender.IsChecked():
  1135. self.OnApply(None)
  1136. def SetSurfaceMode(self, apply=True, all=False):
  1137. """Set draw mode
  1138. @param apply allow auto-rendering
  1139. """
  1140. value = 0
  1141. mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
  1142. if mode == 0: # coarse
  1143. value |= wxnviz.DM_WIRE
  1144. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1145. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
  1146. elif mode == 1: # fine
  1147. value |= wxnviz.DM_POLY
  1148. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
  1149. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1150. else: # both
  1151. value |= wxnviz.DM_WIRE_POLY
  1152. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1153. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1154. style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
  1155. if style == 0: # wire
  1156. value |= wxnviz.DM_GRID_WIRE
  1157. else: # surface
  1158. value |= wxnviz.DM_GRID_SURF
  1159. shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
  1160. if shade == 0:
  1161. value |= wxnviz.DM_FLAT
  1162. else: # surface
  1163. value |= wxnviz.DM_GOURAUD
  1164. self.mapWindow.update['draw-style'] = (value, all)
  1165. if apply and self.parent.autoRender.IsChecked():
  1166. self.OnApply(None)
  1167. def OnSurfaceMode(self, event):
  1168. """Set draw mode"""
  1169. self.SetSurfaceMode()
  1170. def OnSurfaceModeAll(self, event):
  1171. """Set draw mode (including wire color) for all loaded surfaces"""
  1172. self.SetSurfaceMode(apply=False, all=True)
  1173. self.SetSurfaceResolution(apply=False, all=True)
  1174. color = self.FindWindowById(self.win['surface']['draw']['color']).GetColour()
  1175. self.SetSurfaceWireColor(color, all=True)
  1176. def SetSurfaceWireColor(self, color, all=False):
  1177. """Set wire color"""
  1178. value = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1179. self.mapWindow.update['draw-color'] = (value, all)
  1180. if self.parent.autoRender.IsChecked():
  1181. self.OnApply(None)
  1182. def OnSurfaceWireColor(self, event):
  1183. """Set wire color"""
  1184. self.SetSurfaceWireColor(event.GetValue())
  1185. def OnVectorDisplay(self, event):
  1186. """Display vector lines on surface/flat"""
  1187. if event.GetSelection() == 0: # surface
  1188. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(True)
  1189. # set first found surface
  1190. ### TODO
  1191. else: # flat
  1192. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(False)
  1193. event.Skip()
  1194. def UpdatePage(self, pageId):
  1195. """Update dialog (selected page)"""
  1196. layer = self.mapWindow.GetSelectedLayer()
  1197. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1198. if pageId == 'view':
  1199. max = self.settings['z-exag']['value'] * 10
  1200. for control in ('spin', 'slider'):
  1201. self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(0,
  1202. max)
  1203. elif pageId == 'surface':
  1204. if data is None: # use default values
  1205. #
  1206. # attributes
  1207. #
  1208. for attr in ('topo', 'color'):
  1209. self.SetSurfaceUseMap(attr, True) # -> map
  1210. if layer and layer.type == 'raster':
  1211. self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
  1212. else:
  1213. self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
  1214. if UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'map']) is False:
  1215. self.SetSurfaceUseMap('shine', False)
  1216. value = UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'value'])
  1217. self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
  1218. #
  1219. # draw
  1220. #
  1221. for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
  1222. win = self.FindWindowById(self.win['surface']['draw'][control])
  1223. name = win.GetName()
  1224. if name == "selection":
  1225. win.SetSelection(value)
  1226. elif name == "colour":
  1227. win.SetColour(value)
  1228. else:
  1229. win.SetValue(value)
  1230. # enable/disable res widget + set draw mode
  1231. self.SetSurfaceMode()
  1232. color = self.FindWindowById(self.win['surface']['draw']['color'])
  1233. self.SetSurfaceWireColor(color.GetColour())
  1234. elif layer.type == 'raster':
  1235. # surface attributes
  1236. for attr in data['attr']:
  1237. if attr['map']:
  1238. win = self.FindWindowById(self.win['surface'][attr]['map'])
  1239. else:
  1240. win = self.FindWindowById(self.win['surface'][attr]['const'])
  1241. win.SetValue(data['value'])
  1242. def SetPage(self, name):
  1243. """Get named page"""
  1244. if name == 'surface':
  1245. self.notebook.SetSelection(1)
  1246. class ViewPositionWindow(wx.Window):
  1247. """Position control window (for NvizToolWindow)"""
  1248. def __init__(self, parent, id, mapwindow,
  1249. pos=wx.DefaultPosition,
  1250. size=wx.DefaultSize, settings={}):
  1251. self.settings = settings
  1252. self.mapWindow = mapwindow
  1253. wx.Window.__init__(self, parent, id, pos, size)
  1254. self.SetBackgroundColour("WHITE")
  1255. self.pdc = wx.PseudoDC()
  1256. self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
  1257. self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
  1258. self.Draw()
  1259. self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
  1260. self.Bind(wx.EVT_PAINT, self.OnPaint)
  1261. # self.Bind(wx.EVT_MOTION, self.OnMouse)
  1262. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
  1263. def Draw(self, pos=None):
  1264. w, h = self.GetClientSize()
  1265. if pos is None:
  1266. x = self.settings['pos']['x']
  1267. y = self.settings['pos']['y']
  1268. x = x * w
  1269. y = y * h
  1270. else:
  1271. x, y = pos
  1272. self.pdc.Clear()
  1273. self.pdc.BeginDrawing()
  1274. self.pdc.DrawLine(w / 2, h / 2, x, y)
  1275. self.pdc.DrawCircle(x, y, 5)
  1276. self.pdc.EndDrawing()
  1277. def OnPaint(self, event):
  1278. dc = wx.BufferedPaintDC(self)
  1279. dc.SetBackground(wx.Brush("White"))
  1280. dc.Clear()
  1281. self.PrepareDC(dc)
  1282. self.pdc.DrawToDC(dc)
  1283. def OnMouse(self, event):
  1284. if event.LeftIsDown():
  1285. x, y = event.GetPosition()
  1286. self.Draw(pos=(x, y))
  1287. self.Refresh(False)
  1288. w, h = self.GetClientSize()
  1289. x = float(x) / w
  1290. y = float(y) / h
  1291. self.settings['pos']['x'] = x
  1292. self.settings['pos']['y'] = y
  1293. self.mapWindow.update['view'] = None
  1294. self.mapWindow.render = False
  1295. if event.LeftUp():
  1296. self.mapWindow.render = True
  1297. self.mapWindow.Refresh(eraseBackground=False)