nviz.py 50 KB

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