nviz.py 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338
  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'] < 0:
  139. self.view['persp']['value'] = 0
  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 for this session"))
  312. btnApply.SetDefault()
  313. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  314. btnSave.SetToolTipString(_("Close dialog and save changes to user settings file"))
  315. btnCancel.Bind(wx.EVT_BUTTON, self.OnClose)
  316. btnCancel.SetToolTipString(_("Close 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. spin.Bind(wx.EVT_SPINCTRL, self.OnViewChange)
  694. self.win['view'][name]['spin'] = spin.GetId()
  695. def UpdateSettings(self):
  696. """Update dialog settings"""
  697. for control in ('height',
  698. 'persp',
  699. 'twist',
  700. 'z-exag'):
  701. for win in self.win['view'][control].itervalues():
  702. self.FindWindowById(win).SetValue(int(self.settings[control]['value']))
  703. self.FindWindowById(self.win['view']['pos']).Draw()
  704. self.FindWindowById(self.win['view']['pos']).Refresh(False)
  705. self.Refresh(False)
  706. def __GetWindowName(self, dict, id):
  707. for name in dict.iterkeys():
  708. if type(dict[name]) is type({}):
  709. for win in dict[name].itervalues():
  710. if win == id:
  711. return name
  712. else:
  713. if dict[name] == id:
  714. return name
  715. return None
  716. def OnViewChange(self, event):
  717. """Change view, render in quick mode"""
  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.render = False
  730. self.mapWindow.Refresh(False)
  731. def OnViewChanged(self, event):
  732. """View changed, render in full resolution"""
  733. print '#'
  734. self.mapWindow.render = True
  735. self.mapWindow.Refresh(False)
  736. def OnResetView(self, event):
  737. """Reset to default view (view page)"""
  738. self.mapWindow.ResetView()
  739. self.UpdateSettings()
  740. self.mapWindow.Refresh(False)
  741. def OnLookAt(self, event):
  742. """Look at (view page)"""
  743. sel = event.GetSelection()
  744. if sel == 0: # top
  745. self.settings['pos']['x'] = 0.5
  746. self.settings['pos']['y'] = 0.5
  747. elif sel == 1: # north
  748. self.settings['pos']['x'] = 0.5
  749. self.settings['pos']['y'] = 0.0
  750. elif sel == 2: # south
  751. self.settings['pos']['x'] = 0.5
  752. self.settings['pos']['y'] = 1.0
  753. elif sel == 3: # east
  754. self.settings['pos']['x'] = 1.0
  755. self.settings['pos']['y'] = 0.5
  756. elif sel == 4: # west
  757. self.settings['pos']['x'] = 0.0
  758. self.settings['pos']['y'] = 0.5
  759. elif sel == 5: # north-west
  760. self.settings['pos']['x'] = 0.0
  761. self.settings['pos']['y'] = 0.0
  762. elif sel == 6: # north-east
  763. self.settings['pos']['x'] = 1.0
  764. self.settings['pos']['y'] = 0.0
  765. elif sel == 7: # south-east
  766. self.settings['pos']['x'] = 1.0
  767. self.settings['pos']['y'] = 1.0
  768. elif sel == 8: # south-west
  769. self.settings['pos']['x'] = 0.0
  770. self.settings['pos']['y'] = 1.0
  771. self.mapWindow.update['view'] = None
  772. self.UpdateSettings()
  773. self.mapWindow.Refresh(False)
  774. def OnSave(self, event):
  775. """OK button pressed
  776. Apply changes, update map and save settings of selected layer
  777. """
  778. #
  779. # apply changes
  780. #
  781. self.OnApply(None)
  782. #
  783. # save settings
  784. #
  785. type = self.mapWindow.GetSelectedLayer().type
  786. data = self.mapWindow.GetSelectedLayer(nviz=True)
  787. if data is None: # no settings
  788. data = {}
  789. if type == 'raster': # -> surface
  790. #
  791. # surface attributes
  792. #
  793. data['attribute'] = {}
  794. for attrb in ('topo', 'color', 'mask',
  795. 'transp', 'shine', 'emit'):
  796. use = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  797. if self.win['surface'][attrb]['required']: # map, constant
  798. if use == 0: # map
  799. map = True
  800. elif use == 1: # constant
  801. map = False
  802. else: # unset, map, constant
  803. if use == 0: # unset
  804. map = None
  805. elif use == 1: # map
  806. map = True
  807. elif use == 2: # constant
  808. map = False
  809. if map is None:
  810. continue
  811. if map:
  812. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  813. else:
  814. if attrb == 'color':
  815. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetColour()
  816. else:
  817. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  818. data['attribute'][attrb] = {}
  819. data['attribute'][attrb]['map'] = map
  820. data['attribute'][attrb]['value'] = value
  821. #
  822. # draw
  823. #
  824. data['draw'] = {}
  825. for control in ('mode', 'shading', 'style'):
  826. data['draw'][control] = self.FindWindowById(self.win['surface']['draw'][control]).GetSelection()
  827. for control in ('res-coarse', 'res-fine'):
  828. data['draw'][control] = self.FindWindowById(self.win['surface']['draw'][control]).GetValue()
  829. self.mapWindow.SetLayerSettings(data)
  830. def OnApply(self, event):
  831. """Apply button pressed
  832. Apply changes, update map
  833. """
  834. layer = self.mapWindow.GetSelectedLayer()
  835. id = self.mapWindow.GetMapObjId(layer)
  836. print self.mapWindow.update
  837. #
  838. # surface
  839. #
  840. # surface attributes
  841. for attrb in ('topo', 'color', 'mask',
  842. 'transp', 'shine', 'emit'):
  843. if self.mapWindow.update.has_key(attrb):
  844. map, value = self.mapWindow.update[attrb]
  845. if map is None: # unset
  846. # only optional attributes
  847. if attrb == 'mask':
  848. # TODO: invert mask
  849. # TODO: broken in NVIZ
  850. self.mapWindow.nvizClass.UnsetSurfaceMask(id)
  851. elif attrb == 'transp':
  852. self.mapWindow.nvizClass.UnsetSurfaceTransp(id)
  853. elif attrb == 'emit':
  854. self.mapWindow.nvizClass.UnsetSurfaceEmit(id)
  855. else:
  856. if len(value) <= 0: # ignore empty values (TODO: warning)
  857. continue
  858. if attrb == 'topo':
  859. self.mapWindow.nvizClass.SetSurfaceTopo(id, map, str(value))
  860. elif attrb == 'color':
  861. self.mapWindow.nvizClass.SetSurfaceColor(id, map, str(value))
  862. elif attrb == 'mask':
  863. # TODO: invert mask
  864. # TODO: broken in NVIZ
  865. self.mapWindow.nvizClass.SetSurfaceMask(id, False, str(value))
  866. elif attrb == 'transp':
  867. self.mapWindow.nvizClass.SetSurfaceTransp(id, map, str(value))
  868. elif attrb == 'shine':
  869. self.mapWindow.nvizClass.SetSurfaceShine(id, map, str(value))
  870. elif attrb == 'emit':
  871. self.mapWindow.nvizClass.SetSurfaceEmit(id, map, str(value))
  872. del self.mapWindow.update[attrb]
  873. # draw res
  874. if self.mapWindow.update.has_key('draw-res'):
  875. coarse, fine = self.mapWindow.update['draw-res']
  876. self.mapWindow.nvizClass.SetSurfaceRes(id, fine, coarse)
  877. # draw style
  878. if self.mapWindow.update.has_key('draw-style'):
  879. self.mapWindow.nvizClass.SetSurfaceStyle(id, self.mapWindow.update['draw-style'])
  880. # wire color
  881. if self.mapWindow.update.has_key('draw-color'):
  882. self.mapWindow.nvizClass.SetWireColor(id, str(self.mapWindow.update['draw-color']))
  883. self.mapWindow.Refresh(False)
  884. def OnClose(self, event):
  885. """Close button pressed
  886. Close dialog
  887. """
  888. self.Hide()
  889. def OnSurfaceUse(self, event):
  890. """Surface attribute -- use -- map/constant"""
  891. if not self.mapWindow.init:
  892. return
  893. # find attribute row
  894. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  895. if not attrb:
  896. return
  897. selection = event.GetSelection()
  898. if self.win['surface'][attrb]['required']: # no 'unset'
  899. selection += 1
  900. if selection == 0: # unset
  901. useMap = None
  902. value = ''
  903. elif selection == 1: # map
  904. useMap = True
  905. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  906. elif selection == 2: # constant
  907. useMap = False
  908. if attrb == 'color':
  909. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  910. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  911. else:
  912. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  913. self.SetSurfaceUseMap(attrb, useMap)
  914. self.mapWindow.update[attrb] = (useMap, str(value))
  915. if self.parent.autoRender.IsChecked():
  916. self.OnApply(None)
  917. def SetSurfaceUseMap(self, attrb, map=None):
  918. if attrb in ('topo', 'color', 'shine'):
  919. incSel = -1 # decrement selection (no 'unset')
  920. else:
  921. incSel = 0
  922. if map is True: # map
  923. if attrb != 'topo': # changing map topography not allowed
  924. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(True) # FIXME
  925. if self.win['surface'][attrb]['const']:
  926. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  927. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(1 + incSel)
  928. elif map is False: # const
  929. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  930. if self.win['surface'][attrb]['const']:
  931. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(True)
  932. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(2 + incSel)
  933. else: # unset
  934. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  935. if self.win['surface'][attrb]['const']:
  936. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  937. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(0)
  938. def OnSurfaceMap(self, event):
  939. """Set surface attribute"""
  940. if not self.mapWindow.init:
  941. return
  942. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  943. if not attrb:
  944. return
  945. selection = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  946. if self.win['surface'][attrb]['required']:
  947. selection += 1
  948. if selection == 0: # unset
  949. map = None
  950. value = ''
  951. elif selection == 1: # map
  952. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  953. map = True
  954. else: # constant
  955. if attrb == 'color':
  956. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  957. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  958. else:
  959. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  960. map = False
  961. self.mapWindow.update[attrb] = (map, str(value))
  962. if self.parent.autoRender.IsChecked():
  963. self.OnApply(None)
  964. def OnSurfaceResolution(self, event):
  965. """Draw resolution changed"""
  966. coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
  967. fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
  968. self.mapWindow.update['draw-res'] = (coarse, fine)
  969. if self.parent.autoRender.IsChecked():
  970. self.OnApply(None)
  971. def SetSurfaceMode(self):
  972. """Set draw mode"""
  973. value = 0
  974. mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
  975. if mode == 0: # coarse
  976. value |= wxnviz.DM_WIRE
  977. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  978. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
  979. elif mode == 1: # fine
  980. value |= wxnviz.DM_POLY
  981. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
  982. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  983. else: # both
  984. value |= wxnviz.DM_WIRE_POLY
  985. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  986. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  987. style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
  988. if style == 0: # wire
  989. value |= wxnviz.DM_GRID_WIRE
  990. else: # surface
  991. value |= wxnviz.DM_GRID_SURF
  992. shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
  993. if shade == 0:
  994. value |= wxnviz.DM_FLAT
  995. else: # surface
  996. value |= wxnviz.DM_GOURAUD
  997. self.mapWindow.update['draw-style'] = value
  998. if self.parent.autoRender.IsChecked():
  999. self.OnApply(None)
  1000. def OnSurfaceMode(self, event):
  1001. """Set draw mode"""
  1002. self.SetSurfaceMode()
  1003. def SetSurfaceWireColor(self, color):
  1004. """Set wire color"""
  1005. value = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1006. self.mapWindow.update['draw-color'] = value
  1007. if self.parent.autoRender.IsChecked():
  1008. self.OnApply(None)
  1009. def OnSurfaceWireColor(self, event):
  1010. """Set wire color"""
  1011. self.SetSurfaceWireColor(event.GetValue())
  1012. def UpdatePage(self, pageId):
  1013. """Update dialog (selected page)"""
  1014. layer = self.mapWindow.GetSelectedLayer()
  1015. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1016. if pageId == 'view':
  1017. max = self.settings['z-exag']['value'] * 10
  1018. for control in ('spin', 'slider'):
  1019. self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(0,
  1020. max)
  1021. elif pageId == 'surface':
  1022. if data is None: # use default values
  1023. #
  1024. # attributes
  1025. #
  1026. for attr in ('topo', 'color'):
  1027. self.SetSurfaceUseMap(attr, True) # -> map
  1028. if layer.type == 'raster':
  1029. self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
  1030. else:
  1031. self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
  1032. if UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'map']) is False:
  1033. self.SetSurfaceUseMap('shine', False)
  1034. value = UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'value'])
  1035. self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
  1036. #
  1037. # draw
  1038. #
  1039. for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
  1040. win = self.FindWindowById(self.win['surface']['draw'][control])
  1041. name = win.GetName()
  1042. if name == "selection":
  1043. win.SetSelection(value)
  1044. elif name == "colour":
  1045. win.SetColour(value)
  1046. else:
  1047. win.SetValue(value)
  1048. # enable/disable res widget + set draw mode
  1049. self.SetSurfaceMode()
  1050. color = self.FindWindowById(self.win['surface']['draw']['color'])
  1051. self.SetSurfaceWireColor(color.GetColour())
  1052. elif layer.type == 'raster':
  1053. # surface attributes
  1054. for attr in data['attr']:
  1055. if attr['map']:
  1056. win = self.FindWindowById(self.win['surface'][attr]['map'])
  1057. else:
  1058. win = self.FindWindowById(self.win['surface'][attr]['const'])
  1059. win.SetValue(data['value'])
  1060. def SetPage(self, name):
  1061. """Get named page"""
  1062. if name == 'surface':
  1063. self.notebook.SetSelection(1)
  1064. class ViewPositionWindow(wx.Window):
  1065. """Position control window (for NvizToolWindow)"""
  1066. def __init__(self, parent, id, mapwindow,
  1067. pos=wx.DefaultPosition,
  1068. size=wx.DefaultSize, settings={}):
  1069. self.settings = settings
  1070. self.mapWindow = mapwindow
  1071. wx.Window.__init__(self, parent, id, pos, size)
  1072. self.SetBackgroundColour("WHITE")
  1073. self.pdc = wx.PseudoDC()
  1074. self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
  1075. self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
  1076. self.Draw()
  1077. self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
  1078. self.Bind(wx.EVT_PAINT, self.OnPaint)
  1079. # self.Bind(wx.EVT_MOTION, self.OnMouse)
  1080. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
  1081. def Draw(self, pos=None):
  1082. w, h = self.GetClientSize()
  1083. if pos is None:
  1084. x = self.settings['pos']['x']
  1085. y = self.settings['pos']['y']
  1086. x = x * w
  1087. y = y * h
  1088. else:
  1089. x, y = pos
  1090. self.pdc.Clear()
  1091. self.pdc.BeginDrawing()
  1092. self.pdc.DrawLine(w / 2, h / 2, x, y)
  1093. self.pdc.DrawCircle(x, y, 5)
  1094. self.pdc.EndDrawing()
  1095. def OnPaint(self, event):
  1096. dc = wx.BufferedPaintDC(self)
  1097. dc.SetBackground(wx.Brush("White"))
  1098. dc.Clear()
  1099. self.PrepareDC(dc)
  1100. self.pdc.DrawToDC(dc)
  1101. def OnMouse(self, event):
  1102. print event.LeftIsDown(), event.LeftUp()
  1103. if event.LeftIsDown():
  1104. x, y = event.GetPosition()
  1105. self.Draw(pos=(x, y))
  1106. self.Refresh(False)
  1107. w, h = self.GetClientSize()
  1108. x = float(x) / w
  1109. y = float(y) / h
  1110. self.settings['pos']['x'] = x
  1111. self.settings['pos']['y'] = y
  1112. self.mapWindow.update['view'] = None
  1113. self.mapWindow.render = False
  1114. if event.LeftUp():
  1115. self.mapWindow.render = True
  1116. self.mapWindow.Refresh(eraseBackground=False)