nviz.py 49 KB

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