nviz.py 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239
  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. import copy
  18. from threading import Thread
  19. import wx
  20. import wx.lib.colourselect as csel
  21. import wx.lib.scrolledpanel as scrolled
  22. errorMsg = ''
  23. try:
  24. from wx import glcanvas
  25. haveGLCanvas = True
  26. except ImportError, e:
  27. haveGLCanvas = False
  28. errorMsg = e
  29. try:
  30. from OpenGL.GL import *
  31. from OpenGL.GLUT import *
  32. haveOpenGL = True
  33. except ImportError, e:
  34. haveOpenGL = False
  35. errorMsg = e
  36. import globalvar
  37. import gcmd
  38. import gselect
  39. from debug import Debug as Debug
  40. from mapdisp import MapWindow as MapWindow
  41. from preferences import globalSettings as UserSettings
  42. try:
  43. nvizPath = os.path.join(globalvar.ETCWXDIR, "nviz")
  44. sys.path.append(nvizPath)
  45. import grass7_wxnviz as wxnviz
  46. haveNviz = True
  47. except ImportError, e:
  48. haveNviz = False
  49. errorMsg = e
  50. class GLWindow(MapWindow, glcanvas.GLCanvas):
  51. """OpenGL canvas for Map Display Window"""
  52. def __init__(self, parent, id,
  53. pos=wx.DefaultPosition,
  54. size=wx.DefaultSize,
  55. style=wx.NO_FULL_REPAINT_ON_RESIZE,
  56. Map=None, tree=None, gismgr=None):
  57. self.parent = parent # MapFrame
  58. self.Map = Map
  59. self.tree = tree
  60. self.gismgr = gismgr
  61. glcanvas.GLCanvas.__init__(self, parent, id)
  62. MapWindow.__init__(self, parent, id, pos, size, style,
  63. Map, tree, gismgr)
  64. self.parent = parent # MapFrame
  65. self.init = False
  66. self.render = True # render in full resolution
  67. #
  68. # create nviz instance
  69. #
  70. self.nvizClass = wxnviz.Nviz()
  71. #
  72. # set current display
  73. #
  74. self.nvizClass.SetDisplay(self)
  75. #
  76. # initialize mouse position
  77. #
  78. self.lastX = self.x = 30
  79. self.lastY = self.y = 30
  80. #
  81. # default values
  82. #
  83. self.view = copy.deepcopy(UserSettings.Get(group='nviz', key='view')) # copy
  84. self.iview = UserSettings.Get(group='nviz', key='view', internal=True)
  85. self.update = [] # list of properties to be updated
  86. self.size = None
  87. self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
  88. self.Bind(wx.EVT_SIZE, self.OnSize)
  89. self.Bind(wx.EVT_PAINT, self.OnPaint)
  90. self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
  91. self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
  92. self.Bind(wx.EVT_MOTION, self.OnMouseAction)
  93. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseAction)
  94. def OnEraseBackground(self, event):
  95. pass # do nothing, to avoid flashing on MSW
  96. def OnSize(self, event):
  97. self.size = self.parent.GetClientSize()
  98. if self.GetContext():
  99. Debug.msg(3, "GLCanvas.OnPaint(): w=%d, h=%d" % \
  100. (self.size.width, self.size.height))
  101. self.SetCurrent()
  102. self.nvizClass.ResizeWindow(self.size.width,
  103. self.size.height)
  104. event.Skip()
  105. def OnPaint(self, event):
  106. Debug.msg(3, "GLCanvas.OnPaint()")
  107. dc = wx.PaintDC(self)
  108. self.SetCurrent()
  109. if not self.init:
  110. self.nvizClass.InitView()
  111. self.LoadDataLayers()
  112. self.ResetView()
  113. if hasattr(self.parent, "nvizToolWin"):
  114. self.parent.nvizToolWin.UpdatePage('view')
  115. layer = self.GetSelectedLayer()
  116. if layer:
  117. if layer.type == 'raster':
  118. self.parent.nvizToolWin.UpdatePage('surface')
  119. elif layer.type == 'vector':
  120. self.parent.nvizToolWin.UpdatePage('vector')
  121. self.parent.nvizToolWin.UpdateSettings()
  122. self.init = True
  123. self.UpdateMap()
  124. def OnMouseAction(self, event):
  125. # change position
  126. if event.Dragging() and event.LeftIsDown():
  127. self.lastX = self.lastY = self.x = self.y
  128. self.x, self.y = event.GetPosition()
  129. self.Refresh(False)
  130. # change perspective with mouse wheel
  131. wheel = event.GetWheelRotation()
  132. if wheel != 0:
  133. current = event.GetPositionTuple()[:]
  134. Debug.msg (5, "GLWindow.OnMouseMotion(): wheel=%d" % wheel)
  135. prev_value = self.view['persp']['value']
  136. if wheel > 0:
  137. value = -1 * self.view['persp']['step']
  138. else:
  139. value = self.view['persp']['step']
  140. self.view['persp']['value'] += value
  141. if self.view['persp']['value'] < 1:
  142. self.view['persp']['value'] = 1
  143. elif self.view['persp']['value'] > 100:
  144. self.view['persp']['value'] = 100
  145. if prev_value != self.view['persp']['value']:
  146. if hasattr(self.parent, "nvizToolWin"):
  147. self.parent.nvizToolWin.UpdateSettings()
  148. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  149. self.iview['height']['value'],
  150. self.view['persp']['value'],
  151. self.view['twist']['value'])
  152. # redraw map
  153. self.OnPaint(None)
  154. # update statusbar
  155. ### self.parent.StatusbarUpdate()
  156. def OnLeftDown(self, event):
  157. self.CaptureMouse()
  158. self.x, self.y = self.lastX, self.lastY = event.GetPosition()
  159. def OnLeftUp(self, event):
  160. self.ReleaseMouse()
  161. def UpdateMap(self, render=True):
  162. """
  163. Updates the canvas anytime there is a change to the
  164. underlaying images or to the geometry of the canvas.
  165. @param render re-render map composition
  166. """
  167. start = time.clock()
  168. self.resize = False
  169. # if self.size is None:
  170. # self.size = self.GetClientSize()
  171. # w, h = self.size
  172. # w = float(max(w, 1.0))
  173. # h = float(max(h, 1.0))
  174. # d = float(min(w, h))
  175. # xScale = d / w
  176. # yScale = d / h
  177. # print w, h, d, xScale, yScale
  178. # print self.y, self.lastY, self.x, self.lastX
  179. # print (self.y - self.lastY) * yScale, (self.x - self.lastX) * xScale
  180. # print self.x * xScale
  181. #glRotatef((self.y - self.lastY) * yScale, 1.0, 0.0, 0.0);
  182. #glRotatef((self.x - self.lastX) * xScale, 0.0, 1.0, 0.0);
  183. if self.render:
  184. self.parent.onRenderGauge.Show()
  185. self.parent.onRenderGauge.SetRange(2)
  186. self.parent.onRenderGauge.SetValue(0)
  187. if 'view' in self.update:
  188. if 'z-exag' in self.update:
  189. self.nvizClass.SetZExag(self.view['z-exag']['value'])
  190. self.update.remove('z-exag')
  191. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  192. self.iview['height']['value'],
  193. self.view['persp']['value'],
  194. self.view['twist']['value'])
  195. self.update.remove('view')
  196. if self.render is True:
  197. self.parent.onRenderGauge.SetValue(1)
  198. wx.Yield()
  199. self.nvizClass.Draw(False)
  200. else:
  201. self.nvizClass.Draw(True) # quick
  202. self.SwapBuffers()
  203. stop = time.clock()
  204. if self.render:
  205. self.parent.onRenderGauge.SetValue(2)
  206. # hide process bar
  207. self.parent.onRenderGauge.Hide()
  208. #
  209. # update statusbar
  210. #
  211. # self.parent.StatusbarUpdate()
  212. Debug.msg(3, "GLWindow.UpdateMap(): render=%s, -> time=%g" % \
  213. (self.render, (stop-start)))
  214. # print stop-start
  215. def EraseMap(self):
  216. """
  217. Erase the canvas
  218. """
  219. self.nvizClass.EraseMap()
  220. self.SwapBuffers()
  221. def IsLoaded(self, layer):
  222. """Check if layer (item) is already loaded"""
  223. data = self.tree.GetPyData(layer)[0]['nviz']
  224. if not data or not data.has_key('object'):
  225. return 0
  226. return 1
  227. def LoadDataLayers(self):
  228. """Load raster/vector from current layer tree
  229. @todo volumes
  230. """
  231. listOfItems = []
  232. # load raster & vector maps
  233. item = self.tree.GetFirstChild(self.tree.root)[0]
  234. while item and item.IsOk():
  235. type = self.tree.GetPyData(item)[0]['type']
  236. if type not in ('raster', 'vector'):
  237. continue
  238. listOfItems.append(item)
  239. item = self.tree.GetNextSibling(item)
  240. start = time.time()
  241. while(len(listOfItems) > 0):
  242. item = listOfItems.pop()
  243. type = self.tree.GetPyData(item)[0]['type']
  244. mapLayer = self.tree.GetPyData(item)[0]['maplayer']
  245. if type == 'raster':
  246. id = self.LoadRaster(mapLayer)
  247. elif type == 'vector':
  248. id = self.LoadVector(mapLayer)
  249. if type == 'raster' or type == 'vector':
  250. self.SetLayerData(item, id)
  251. self.UpdateLayerProperties(item)
  252. # print self.tree.GetPyData(item)[0]['nviz']
  253. # print self.update
  254. stop = time.time()
  255. Debug.msg(3, "GLWindow.LoadDataLayers(): time=%f" % (stop-start))
  256. # print stop - start
  257. def SetLayerData(self, item, id):
  258. """Set map object properties"""
  259. type = self.tree.GetPyData(item)[0]['maplayer'].type
  260. data = self.tree.GetPyData(item)[0]['nviz']
  261. # init layer data properties
  262. if data is None:
  263. self.tree.GetPyData(item)[0]['nviz'] = {}
  264. data = self.tree.GetPyData(item)[0]['nviz']
  265. if type == 'raster':
  266. data['surface'] = {}
  267. for sec in ('attribute', 'draw', 'mask', 'position'):
  268. data['surface'][sec] = {}
  269. self.SetSurfaceDefaultProp(data['surface'])
  270. elif type == 'vector':
  271. data['vector'] = {}
  272. for sec in ('lines', ):
  273. data['vector'][sec] = {}
  274. self.SetVectorDefaultProp(data['vector'])
  275. # set updates
  276. else:
  277. for sec in data.keys():
  278. for sec1 in data[sec].keys():
  279. for sec2 in data[sec][sec1].keys():
  280. self.update.append('%s:%s:%s' % (sec, sec1, sec2))
  281. # associate with map object id
  282. if not data.has_key('object'):
  283. data['object'] = { 'id' : id,
  284. 'init' : False }
  285. if not data.has_key('view'):
  286. data['view'] = None
  287. def LoadRaster(self, layer):
  288. """Load raster map -> surface"""
  289. if layer.type != 'raster':
  290. return
  291. id = self.nvizClass.LoadSurface(str(layer.name), None, None)
  292. if id < 0:
  293. raise gcmd.NvizError(parent=self.parent,
  294. message=_("Unable to load raster map <%s>" % layer.name))
  295. return id
  296. def UnloadRaster(self, id):
  297. """Unload raster map"""
  298. if self.nvizClass.UnloadSurface(id) == 0:
  299. raise gcmd.NvizError(parent=self.parent,
  300. message=_("Unable to unload raster map <%s>" % layer.name))
  301. def GetSurfaceMode(self, mode, style, shade, string=False):
  302. """Determine surface draw mode"""
  303. value = 0
  304. desc = {}
  305. if string:
  306. if mode == 'coarse':
  307. value |= wxnviz.DM_WIRE
  308. elif mode == 'fine':
  309. value |= wxnviz.DM_POLY
  310. else: # both
  311. value |= wxnviz.DM_WIRE_POLY
  312. if style == 'wire':
  313. value |= wxnviz.DM_GRID_WIRE
  314. else: # surface
  315. value |= wxnviz.DM_GRID_SURF
  316. if shade == 'flat':
  317. value |= wxnviz.DM_FLAT
  318. else: # surface
  319. value |= wxnviz.DM_GOURAUD
  320. return value
  321. # -> string is False
  322. if mode == 0: # coarse
  323. value |= wxnviz.DM_WIRE
  324. desc['mode'] = 'coarse'
  325. elif mode == 1: # fine
  326. value |= wxnviz.DM_POLY
  327. desc['mode'] = 'fine'
  328. else: # both
  329. value |= wxnviz.DM_WIRE_POLY
  330. desc['mode'] = 'both'
  331. if style == 0: # wire
  332. value |= wxnviz.DM_GRID_WIRE
  333. desc['style'] = 'wire'
  334. else: # surface
  335. value |= wxnviz.DM_GRID_SURF
  336. desc['style'] = 'surface'
  337. if shade == 0:
  338. value |= wxnviz.DM_FLAT
  339. desc['shading'] = 'flat'
  340. else: # surface
  341. value |= wxnviz.DM_GOURAUD
  342. desc['shading'] = 'gouraud'
  343. return (value, desc)
  344. def SetSurfaceDefaultProp(self, data):
  345. """Set default surface properties"""
  346. #
  347. # attributes
  348. #
  349. data['attribute']['shine'] = {}
  350. data['attribute']['shine']['map'] = \
  351. UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'map'])
  352. data['attribute']['shine']['value'] = \
  353. UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'value'])
  354. self.update.append('surface:attribute:shine')
  355. #
  356. # draw
  357. #
  358. for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
  359. if control[:3] == 'res':
  360. if 'surface:draw:%s' % 'resolution' not in self.update:
  361. self.update.append('surface:draw:%s' % 'resolution')
  362. data['draw']['resolution'] = { 'all' : False,
  363. control[4:] : value }
  364. else:
  365. data['draw']['resolution'][control[4:]] = value
  366. continue
  367. else:
  368. self.update.append('surface:draw:%s' % control)
  369. if control == 'wire-color':
  370. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  371. elif control in ('mode', 'style', 'shading'):
  372. if not data['draw'].has_key('mode'):
  373. data['draw']['mode'] = {}
  374. continue
  375. data['draw'][control] = { 'value' : value,
  376. 'all' : False }
  377. value, desc = self.GetSurfaceMode(UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'mode']),
  378. UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'style']),
  379. UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading']))
  380. data['draw']['mode'] = { 'value' : value,
  381. 'desc' : desc,
  382. 'all' : False }
  383. def LoadVector(self, layer):
  384. """Load vector map overlay"""
  385. if layer.type != 'vector':
  386. return
  387. id = self.nvizClass.LoadVector(str(layer.name))
  388. if id < 0:
  389. raise gcmd.NvizError(parent=self.parent,
  390. message=_("Unable to load vector map <%s>" % layer.name))
  391. return id
  392. def UnloadVector(self, id):
  393. """Unload vector map overlay"""
  394. if self.nvizClass.UnloadVector(id) == 0:
  395. raise gcmd.NvizError(parent=self.parent,
  396. message=_("Unable to unload vector map <%s>" % layer.name))
  397. def SetVectorDefaultProp(self, data):
  398. """Set default vector properties"""
  399. #
  400. # lines
  401. #
  402. # width
  403. data['lines']['width'] = \
  404. UserSettings.Get(group='nviz', key='vector',
  405. subkey=['lines', 'width'])
  406. self.update.append('vector:lines:width')
  407. # color
  408. value = UserSettings.Get(group='nviz', key='vector',
  409. subkey=['lines', 'color'])
  410. color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  411. data['lines']['color'] = color
  412. self.update.append('vector:lines:color')
  413. # mode
  414. if UserSettings.Get(group='nviz', key='vector',
  415. subkey=['lines', 'flat']):
  416. type = 'flat'
  417. map = None
  418. else:
  419. type = 'surface'
  420. map = '' # TODO
  421. data['lines']['mode'] = {}
  422. data['lines']['mode']['type'] = type
  423. if map:
  424. data['lines']['mode']['map'] = map
  425. self.update.append('vector:lines:mode')
  426. # height
  427. data['lines']['height'] = UserSettings.Get(group='nviz', key='vector',
  428. subkey=['lines', 'height'])
  429. self.update.append('vector:lines:height')
  430. def Reset(self):
  431. """Reset (unload data)"""
  432. self.nvizClass.Reset()
  433. self.init = False
  434. def OnZoomToMap(self, event):
  435. """
  436. Set display extents to match selected raster
  437. or vector map or volume.
  438. @todo vector, volume
  439. """
  440. layer = self.GetSelectedLayer()
  441. if layer is None:
  442. return
  443. Debug.msg (3, "GLWindow.OnZoomToMap(): layer=%s, type=%s" % \
  444. (layer.name, layer.type))
  445. self.nvizClass.SetViewportDefault()
  446. def ResetView(self):
  447. """Reset to default view"""
  448. self.view['z-exag']['value'], \
  449. self.iview['height']['value'] = self.nvizClass.SetViewDefault()
  450. self.view['pos']['x'] = UserSettings.Get(group='nviz', key='view',
  451. subkey=('pos', 'x'))
  452. self.view['pos']['y'] = UserSettings.Get(group='nviz', key='view',
  453. subkey=('pos', 'x'))
  454. self.view['persp']['value'] = UserSettings.Get(group='nviz', key='view',
  455. subkey=('persp', 'value'))
  456. self.view['twist']['value'] = UserSettings.Get(group='nviz', key='view',
  457. subkey=('twist', 'value'))
  458. self.update.append('view')
  459. def UpdateLayerProperties(self, layer=None):
  460. """Update data layer properties
  461. @param layer layer item or None (for selected item)
  462. """
  463. if not layer:
  464. mapLayer = self.GetSelectedLayer()
  465. data = self.GetSelectedLayer(nviz=True)
  466. else:
  467. mapLayer = self.tree.GetPyData(layer)[0]['maplayer']
  468. data = self.tree.GetPyData(layer)[0]['nviz']
  469. id = data['object']['id']
  470. if mapLayer.type == 'raster':
  471. self.UpdateRasterProperties(id, data['surface'])
  472. elif mapLayer.type == 'vector':
  473. self.UpdateVectorProperties(id, data['vector'])
  474. # -> initialized
  475. data['object']['init'] = True
  476. def UpdateRasterProperties(self, id, data):
  477. """Apply changes for surfaces"""
  478. # surface attributes
  479. for attrb in ('topo', 'color', 'mask',
  480. 'transp', 'shine', 'emit'):
  481. if 'surface:attribute:%s' % attrb in self.update:
  482. map = data['attribute'][attrb]['map']
  483. value = data['attribute'][attrb]['value']
  484. if map is None: # unset
  485. # only optional attributes
  486. if attrb == 'mask':
  487. # TODO: invert mask
  488. # TODO: broken in NVIZ
  489. self.nvizClass.UnsetSurfaceMask(id)
  490. elif attrb == 'transp':
  491. self.nvizClass.UnsetSurfaceTransp(id)
  492. elif attrb == 'emit':
  493. self.nvizClass.UnsetSurfaceEmit(id)
  494. else:
  495. if type(value) == type('') and \
  496. len(value) <= 0: # ignore empty values (TODO: warning)
  497. continue
  498. if attrb == 'topo':
  499. self.nvizClass.SetSurfaceTopo(id, map, str(value))
  500. elif attrb == 'color':
  501. self.nvizClass.SetSurfaceColor(id, map, str(value))
  502. elif attrb == 'mask':
  503. # TODO: invert mask
  504. # TODO: broken in NVIZ
  505. self.nvizClass.SetSurfaceMask(id, False, str(value))
  506. elif attrb == 'transp':
  507. self.nvizClass.SetSurfaceTransp(id, map, str(value))
  508. elif attrb == 'shine':
  509. self.nvizClass.SetSurfaceShine(id, map, str(value))
  510. elif attrb == 'emit':
  511. self.nvizClass.SetSurfaceEmit(id, map, str(value))
  512. self.update.remove('surface:attribute:%s' % attrb)
  513. # draw res
  514. if 'surface:draw:resolution' in self.update:
  515. coarse = data['draw']['resolution']['coarse']
  516. fine = data['draw']['resolution']['fine']
  517. if data['draw']['resolution']['all']:
  518. self.nvizClass.SetSurfaceRes(-1, fine, coarse)
  519. else:
  520. self.nvizClass.SetSurfaceRes(id, fine, coarse)
  521. self.update.remove('surface:draw:resolution')
  522. # draw style
  523. if 'surface:draw:mode' in self.update:
  524. if data['draw']['mode']['value'] < 0: # need to calculate
  525. data['draw']['mode']['value'] = \
  526. self.GetSurfaceMode(mode=data['draw']['mode']['desc']['mode'],
  527. style=data['draw']['mode']['desc']['style'],
  528. shade=data['draw']['mode']['desc']['shading'],
  529. string=True)
  530. style = data['draw']['mode']['value']
  531. if data['draw']['mode']['all']:
  532. self.nvizClass.SetSurfaceStyle(-1, style)
  533. else:
  534. self.nvizClass.SetSurfaceStyle(id, style)
  535. self.update.remove('surface:draw:mode')
  536. # wire color
  537. if 'surface:draw:wire-color' in self.update:
  538. color = data['draw']['wire-color']['value']
  539. if data['draw']['wire-color']['all']:
  540. self.nvizClass.SetWireColor(-1, str(color))
  541. else:
  542. self.nvizClass.SetWireColor(id, str(color))
  543. self.update.remove('surface:draw:wire-color')
  544. # position
  545. if 'surface:position' in self.update:
  546. x = data['position']['x']
  547. y = data['position']['y']
  548. z = data['position']['z']
  549. self.nvizClass.SetSurfacePosition(id, x, y, z)
  550. self.update.remove('surface:position')
  551. def UpdateVectorProperties(self, id, data):
  552. """Apply changes for vector"""
  553. if 'vector:lines:mode' in self.update:
  554. width = data['lines']['width']
  555. color = data['lines']['color']
  556. if data['lines']['mode']['type'] == 'flat':
  557. flat = True
  558. else:
  559. flat = False
  560. self.nvizClass.SetVectorLineMode(id, color,
  561. width, flat)
  562. self.update.remove('vector:lines:mode')
  563. if 'vector:lines:height' in self.update:
  564. self.nvizClass.SetVectorHeight(id,
  565. data['lines']['height'])
  566. self.update.remove('vector:lines:height')
  567. class NvizToolWindow(wx.Frame):
  568. """Experimental window for Nviz tools
  569. @todo integrate with Map display
  570. """
  571. def __init__(self, parent=None, id=wx.ID_ANY, title=_("Nviz tools"),
  572. pos=wx.DefaultPosition, size=wx.DefaultSize,
  573. style=wx.DEFAULT_FRAME_STYLE, mapWindow=None):
  574. self.parent = parent # MapFrame
  575. self.lmgr = self.parent.gismanager # GMFrame
  576. self.mapWindow = mapWindow
  577. wx.Frame.__init__(self, parent, id, title, pos, size, style)
  578. #
  579. # icon
  580. #
  581. self.SetIcon(wx.Icon(os.path.join(globalvar.ETCDIR, 'grass_nviz.ico'), wx.BITMAP_TYPE_ICO))
  582. #
  583. # dialog body
  584. #
  585. mainSizer = wx.BoxSizer(wx.VERTICAL)
  586. self.win = {} # window ids
  587. #
  588. # notebook
  589. #
  590. self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
  591. self.page = {}
  592. # view page
  593. self.__createViewPage()
  594. self.page['view'] = 0
  595. # surface page
  596. self.__createSurfacePage()
  597. self.page['surface'] = 1
  598. # vector page
  599. self.__createVectorPage()
  600. self.page['vector'] = 2
  601. # settings page
  602. self.__createSettingsPage()
  603. self.page['settings'] = 3
  604. self.UpdatePage('settings')
  605. self.pageChanging = False
  606. mainSizer.Add(item=self.notebook, proportion=1,
  607. flag=wx.EXPAND | wx.ALL, border=5)
  608. #
  609. # bindings
  610. #
  611. self.Bind(wx.EVT_CLOSE, self.OnClose)
  612. #
  613. # layout
  614. #
  615. self.SetSizer(mainSizer)
  616. mainSizer.Fit(self)
  617. def __createViewPage(self):
  618. """Create view settings page"""
  619. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  620. self.notebook.AddPage(page=panel,
  621. text=" %s " % _("View"))
  622. pageSizer = wx.BoxSizer(wx.VERTICAL)
  623. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  624. self.win['view'] = {}
  625. # position
  626. posSizer = wx.GridBagSizer(vgap=3, hgap=3)
  627. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("W")),
  628. pos=(1, 0), flag=wx.ALIGN_CENTER)
  629. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("N")),
  630. pos=(0, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM)
  631. viewPos = ViewPositionWindow(panel, id=wx.ID_ANY, size=(175, 175),
  632. mapwindow=self.mapWindow)
  633. self.win['view']['pos'] = viewPos.GetId()
  634. posSizer.Add(item=viewPos,
  635. pos=(1, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL)
  636. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("S")),
  637. pos=(2, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_TOP)
  638. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("E")),
  639. pos=(1, 2), flag=wx.ALIGN_CENTER)
  640. gridSizer.Add(item=posSizer, pos=(0, 0))
  641. # perspective
  642. range = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
  643. self.CreateControl(panel, dict=self.win['view'], name='persp',
  644. range=(range['min'], range['max']),
  645. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  646. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Perspective:")),
  647. pos=(1, 0), flag=wx.ALIGN_CENTER)
  648. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['slider']), pos=(2, 0))
  649. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['spin']), pos=(3, 0),
  650. flag=wx.ALIGN_CENTER)
  651. # twist
  652. range = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
  653. self.CreateControl(panel, dict=self.win['view'], name='twist',
  654. range=(range['min'], range['max']),
  655. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  656. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Twist:")),
  657. pos=(1, 1), flag=wx.ALIGN_CENTER)
  658. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['slider']), pos=(2, 1))
  659. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['spin']), pos=(3, 1),
  660. flag=wx.ALIGN_CENTER)
  661. # height + z-exag
  662. self.CreateControl(panel, dict=self.win['view'], name='height', sliderHor=False,
  663. range=(self.mapWindow.view['height']['min'], self.mapWindow.view['height']['max']),
  664. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  665. self.CreateControl(panel, dict=self.win['view'], name='z-exag', sliderHor=False,
  666. range=(0, 1),
  667. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  668. heightSizer = wx.GridBagSizer(vgap=3, hgap=3)
  669. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Height:")),
  670. pos=(0, 0), flag=wx.ALIGN_LEFT, span=(1, 2))
  671. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['slider']),
  672. flag=wx.ALIGN_RIGHT, pos=(1, 0))
  673. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['spin']),
  674. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  675. wx.BOTTOM | wx.RIGHT, pos=(1, 1))
  676. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Z-exag:")),
  677. pos=(0, 2), flag=wx.ALIGN_LEFT, span=(1, 2))
  678. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['slider']),
  679. flag=wx.ALIGN_RIGHT, pos=(1, 2))
  680. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['spin']),
  681. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  682. wx.BOTTOM | wx.RIGHT, pos=(1, 3))
  683. gridSizer.Add(item=heightSizer, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  684. # view setup + reset
  685. viewSizer = wx.BoxSizer(wx.HORIZONTAL)
  686. viewSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY,
  687. label=_("Look at:")),
  688. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
  689. viewType = wx.Choice (parent=panel, id=wx.ID_ANY, size=(125, -1),
  690. choices = [_("top"),
  691. _("north"),
  692. _("south"),
  693. _("east"),
  694. _("west"),
  695. _("north-west"),
  696. _("north-east"),
  697. _("south-east"),
  698. _("south-west")])
  699. viewType.SetSelection(0)
  700. viewType.Bind(wx.EVT_CHOICE, self.OnLookAt)
  701. # self.win['lookAt'] = viewType.GetId()
  702. viewSizer.Add(item=viewType, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
  703. border=5)
  704. reset = wx.Button(panel, id=wx.ID_ANY, label=_("Reset"))
  705. reset.SetToolTipString(_("Reset to default view"))
  706. # self.win['reset'] = reset.GetId()
  707. reset.Bind(wx.EVT_BUTTON, self.OnResetView)
  708. viewSizer.Add(item=reset, proportion=1,
  709. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT,
  710. border=5)
  711. gridSizer.AddGrowableCol(3)
  712. gridSizer.Add(item=viewSizer, pos=(4, 0), span=(1, 2),
  713. flag=wx.EXPAND)
  714. # body
  715. pageSizer.Add(item=gridSizer, proportion=1,
  716. flag=wx.EXPAND | wx.ALL,
  717. border=5)
  718. panel.SetSizer(pageSizer)
  719. def __createSurfacePage(self):
  720. """Create view settings page"""
  721. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  722. # panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY)
  723. # panel.SetupScrolling(scroll_x=True, scroll_y=True)
  724. self.notebook.AddPage(page=panel,
  725. text=" %s " % _("Surface"))
  726. pageSizer = wx.BoxSizer(wx.VERTICAL)
  727. self.win['surface'] = {}
  728. #
  729. # surface attributes
  730. #
  731. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  732. label=" %s " % (_("Surface attributes")))
  733. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  734. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  735. # labels
  736. # col = 0
  737. # for type in (_("Attribute"),
  738. # _("Use"),
  739. # _("Map"),
  740. # _("Constant")):
  741. # gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  742. # label=type),
  743. # pos=(0, col))
  744. # col += 1
  745. # type
  746. self.win['surface']['attr'] = {}
  747. row = 0
  748. for code, attrb in (('topo', _("Topography")),
  749. ('color', _("Color")),
  750. ('mask', _("Mask")),
  751. ('transp', _("Transparency")),
  752. ('shine', _("Shininess")),
  753. ('emit', _("Emission"))):
  754. self.win['surface'][code] = {}
  755. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  756. label=attrb + ':'),
  757. pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  758. use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  759. choices = [_("map")])
  760. if code not in ('topo', 'color', 'shine'):
  761. use.Insert(item=_("unset"), pos=0)
  762. self.win['surface'][code]['required'] = False
  763. else:
  764. self.win['surface'][code]['required'] = True
  765. if code != 'mask':
  766. use.Append(item=_('constant'))
  767. self.win['surface'][code]['use'] = use.GetId()
  768. use.Bind(wx.EVT_CHOICE, self.OnSurfaceUse)
  769. gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
  770. pos=(row, 1))
  771. map = gselect.Select(parent=panel, id=wx.ID_ANY,
  772. # size=globalvar.DIALOG_GSELECT_SIZE,
  773. size=(200, -1),
  774. type="raster")
  775. self.win['surface'][code]['map'] = map.GetId() - 1 # FIXME
  776. map.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  777. # changing map topography not allowed
  778. if code == 'topo':
  779. map.Enable(False)
  780. gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
  781. pos=(row, 2))
  782. if code == 'color':
  783. value = csel.ColourSelect(panel, id=wx.ID_ANY,
  784. colour=UserSettings.Get(group='nviz', key='surface',
  785. subkey=['color', 'value']))
  786. value.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceMap)
  787. elif code == 'mask':
  788. value = None
  789. else:
  790. value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  791. initial=0)
  792. if code == 'topo':
  793. value.SetRange(minVal=-1e9, maxVal=1e9)
  794. elif code in ('shine', 'transp', 'emit'):
  795. value.SetRange(minVal=0, maxVal=255)
  796. else:
  797. value.SetRange(minVal=0, maxVal=100)
  798. value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  799. if value:
  800. self.win['surface'][code]['const'] = value.GetId()
  801. value.Enable(False)
  802. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  803. pos=(row, 3))
  804. else:
  805. self.win['surface'][code]['const'] = None
  806. self.SetSurfaceUseMap(code) # -> enable map / disable constant
  807. row += 1
  808. boxSizer.Add(item=gridSizer, proportion=1,
  809. flag=wx.ALL | wx.EXPAND, border=3)
  810. pageSizer.Add(item=boxSizer, proportion=0,
  811. flag=wx.EXPAND | wx.ALL,
  812. border=5)
  813. #
  814. # draw
  815. #
  816. self.win['surface']['draw'] = {}
  817. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  818. label=" %s " % (_("Draw")))
  819. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  820. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  821. gridSizer.AddGrowableCol(4)
  822. # mode
  823. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  824. label=_("Mode:")),
  825. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  826. mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  827. choices = [_("coarse"),
  828. _("fine"),
  829. _("both")])
  830. mode.SetSelection(0)
  831. mode.SetName("selection")
  832. mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  833. self.win['surface']['draw']['mode'] = mode.GetId()
  834. gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
  835. pos=(0, 1))
  836. # resolution (mode)
  837. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  838. label=_("Resolution:")),
  839. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  840. resSizer = wx.BoxSizer(wx.HORIZONTAL)
  841. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  842. label=_("coarse:")),
  843. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  844. resC = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  845. initial=1,
  846. min=1,
  847. max=100)
  848. resC.SetName("value")
  849. self.win['surface']['draw']['res-coarse'] = resC.GetId()
  850. resC.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  851. resSizer.Add(item=resC, flag=wx.ALL, border=3)
  852. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  853. label=_("fine:")),
  854. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  855. resF = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  856. initial=1,
  857. min=1,
  858. max=100)
  859. resF.SetName("value")
  860. self.win['surface']['draw']['res-fine'] = resF.GetId()
  861. resF.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  862. resSizer.Add(item=resF, flag=wx.ALL, border=3)
  863. gridSizer.Add(item=resSizer, pos=(0, 3), span=(1, 2))
  864. # style
  865. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  866. label=_("Coarse style:")),
  867. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  868. style = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  869. choices = [_("wire"),
  870. _("surface")])
  871. style.SetName("selection")
  872. self.win['surface']['draw']['style'] = style.GetId()
  873. style.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  874. gridSizer.Add(item=style, flag=wx.ALIGN_CENTER_VERTICAL,
  875. pos=(1, 1))
  876. # shading
  877. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  878. label=_("Shading:")),
  879. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  880. shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  881. choices = [_("flat"),
  882. _("gouraud")])
  883. shade.SetName("selection")
  884. self.win['surface']['draw']['shading'] = shade.GetId()
  885. shade.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  886. gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
  887. pos=(1, 3))
  888. # color
  889. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  890. label=_("Wire color:")),
  891. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  892. color = csel.ColourSelect(panel, id=wx.ID_ANY)
  893. color.SetName("colour")
  894. color.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceWireColor)
  895. self.win['surface']['draw']['wire-color'] = color.GetId()
  896. gridSizer.Add(item=color, flag=wx.ALIGN_CENTER_VERTICAL,
  897. pos=(2, 1))
  898. boxSizer.Add(item=gridSizer, proportion=1,
  899. flag=wx.ALL | wx.EXPAND, border=3)
  900. pageSizer.Add(item=boxSizer, proportion=0,
  901. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  902. border=5)
  903. all = wx.Button(panel, id=wx.ID_ANY, label=_("All"))
  904. all.SetToolTipString(_("Use for all loaded surfaces"))
  905. # self.win['reset'] = reset.GetId()
  906. all.Bind(wx.EVT_BUTTON, self.OnSurfaceModeAll)
  907. gridSizer.Add(item=all, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
  908. pos=(2, 4))
  909. #
  910. # mask
  911. #
  912. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  913. label=" %s " % (_("Mask")))
  914. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  915. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  916. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  917. label=_("Mask zeros:")),
  918. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  919. elev = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  920. label=_("by elevation"))
  921. elev.Enable(False) # TODO: not implemented yet
  922. gridSizer.Add(item=elev, pos=(0, 1))
  923. color = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  924. label=_("by color"))
  925. color.Enable(False) # TODO: not implemented yet
  926. gridSizer.Add(item=color, pos=(0, 2))
  927. boxSizer.Add(item=gridSizer, proportion=1,
  928. flag=wx.ALL | wx.EXPAND, border=3)
  929. pageSizer.Add(item=boxSizer, proportion=0,
  930. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  931. border=5)
  932. #
  933. # position
  934. #
  935. self.win['surface']['position'] = {}
  936. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  937. label=" %s " % (_("Position")))
  938. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  939. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  940. # position
  941. axis = wx.Choice (parent=panel, id=wx.ID_ANY, size=(75, -1),
  942. choices = ["X",
  943. "Y",
  944. "Z"])
  945. axis.SetSelection(0)
  946. self.win['surface']['position']['axis'] = axis.GetId()
  947. axis.Bind(wx.EVT_CHOICE, self.OnSurfaceAxis)
  948. gridSizer.Add(item=axis, flag=wx.ALIGN_CENTER_VERTICAL,
  949. pos=(0, 0))
  950. value = wx.Slider(parent=panel, id=wx.ID_ANY,
  951. value=0,
  952. minValue=-1e4,
  953. maxValue=1e4,
  954. style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  955. wx.SL_TOP | wx.SL_LABELS,
  956. size=(350, -1))
  957. self.win['surface']['position']['pos'] = value.GetId()
  958. value.Bind(wx.EVT_SCROLL, self.OnSurfacePosition)
  959. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  960. pos=(0, 1))
  961. boxSizer.Add(item=gridSizer, proportion=1,
  962. flag=wx.ALL | wx.EXPAND, border=3)
  963. pageSizer.Add(item=boxSizer, proportion=0,
  964. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  965. border=5)
  966. panel.SetSizer(pageSizer)
  967. def __createVectorPage(self):
  968. """Create view settings page"""
  969. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  970. self.notebook.AddPage(page=panel,
  971. text=" %s " % _("Vector"))
  972. pageSizer = wx.BoxSizer(wx.VERTICAL)
  973. self.win['vector'] = {}
  974. #
  975. # vector lines
  976. #
  977. self.win['vector']['lines'] = {}
  978. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  979. label=" %s " % (_("Vector lines")))
  980. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  981. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  982. # width
  983. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  984. label=_("Width:")),
  985. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  986. width = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  987. initial=1,
  988. min=1,
  989. max=100)
  990. self.win['vector']['lines']['width'] = width.GetId()
  991. width.Bind(wx.EVT_SPINCTRL, self.OnVectorLines)
  992. gridSizer.Add(item=width, pos=(0, 1),
  993. flag=wx.ALIGN_CENTER_VERTICAL)
  994. gridSizer.AddGrowableCol(2)
  995. # color
  996. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  997. label=_("Color:")),
  998. pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL)
  999. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  1000. colour=UserSettings.Get(group='nviz', key='vector',
  1001. subkey=['lines', 'color']))
  1002. self.win['vector']['lines']['color'] = color.GetId()
  1003. color.Bind(csel.EVT_COLOURSELECT, self.OnVectorLines)
  1004. gridSizer.Add(item=color, pos=(0, 4))
  1005. gridSizer.AddGrowableCol(5)
  1006. # display
  1007. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1008. label=_("Display:")),
  1009. pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
  1010. display = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  1011. choices = [_("on surface"),
  1012. _("flat")])
  1013. self.win['vector']['lines']['flat'] = display.GetId()
  1014. display.Bind(wx.EVT_CHOICE, self.OnVectorDisplay)
  1015. gridSizer.Add(item=display, flag=wx.ALIGN_CENTER_VERTICAL,
  1016. pos=(0, 7))
  1017. surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
  1018. style=wx.CB_SIMPLE | wx.CB_READONLY,
  1019. choices=[])
  1020. self.win['vector']['lines']['surface'] = surface.GetId()
  1021. gridSizer.Add(item=surface,
  1022. pos=(1, 0), span=(1, 8),
  1023. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
  1024. # high
  1025. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1026. label=_("Hight above surface:")),
  1027. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL,
  1028. span=(1, 2))
  1029. self.CreateControl(panel, dict=self.win['vector']['lines'], name='height', size=300,
  1030. range=(0, 1000),
  1031. bind=(self.OnVectorHeight, self.OnVectorHeight, self.OnVectorHeight))
  1032. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['slider']),
  1033. pos=(2, 2), span=(1, 6))
  1034. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['spin']),
  1035. pos=(3, 4),
  1036. flag=wx.ALIGN_CENTER)
  1037. boxSizer.Add(item=gridSizer, proportion=1,
  1038. flag=wx.ALL | wx.EXPAND, border=3)
  1039. pageSizer.Add(item=boxSizer, proportion=0,
  1040. flag=wx.EXPAND | wx.ALL,
  1041. border=5)
  1042. panel.SetSizer(pageSizer)
  1043. def __createSettingsPage(self):
  1044. """Create settings page"""
  1045. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  1046. self.notebook.AddPage(page=panel,
  1047. text=" %s " % _("Settings"))
  1048. pageSizer = wx.BoxSizer(wx.VERTICAL)
  1049. self.win['settings'] = {}
  1050. #
  1051. # general
  1052. #
  1053. self.win['settings']['general'] = {}
  1054. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1055. label=" %s " % (_("General")))
  1056. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1057. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1058. # background color
  1059. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1060. label=_("Background color:")),
  1061. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1062. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  1063. colour=UserSettings.Get(group='nviz', key='settings',
  1064. subkey=['general', 'bgcolor']))
  1065. self.win['settings']['general']['bgcolor'] = color.GetId()
  1066. color.Bind(csel.EVT_COLOURSELECT, self.OnBgColor)
  1067. gridSizer.Add(item=color, pos=(0, 1))
  1068. boxSizer.Add(item=gridSizer, proportion=1,
  1069. flag=wx.ALL | wx.EXPAND, border=3)
  1070. pageSizer.Add(item=boxSizer, proportion=0,
  1071. flag=wx.EXPAND | wx.ALL,
  1072. border=5)
  1073. #
  1074. # view
  1075. #
  1076. self.win['settings']['view'] = {}
  1077. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1078. label=" %s " % (_("View")))
  1079. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1080. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1081. # perspective
  1082. self.win['settings']['view']['persp'] = {}
  1083. pvals = UserSettings.Get(group='nviz', key='view', subkey='persp')
  1084. ipvals = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
  1085. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1086. label=_("Perspective (value):")),
  1087. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1088. pval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1089. initial=pvals['value'],
  1090. min=ipvals['min'],
  1091. max=ipvals['max'])
  1092. self.win['settings']['view']['persp']['value'] = pval.GetId()
  1093. gridSizer.Add(item=pval, pos=(0, 1),
  1094. flag=wx.ALIGN_CENTER_VERTICAL)
  1095. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1096. label=_("(step):")),
  1097. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1098. pstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1099. initial=pvals['step'],
  1100. min=ipvals['min'],
  1101. max=ipvals['max']-1)
  1102. self.win['settings']['view']['persp']['step'] = pstep.GetId()
  1103. gridSizer.Add(item=pstep, pos=(0, 3),
  1104. flag=wx.ALIGN_CENTER_VERTICAL)
  1105. # position
  1106. self.win['settings']['view']['pos'] = {}
  1107. posvals = UserSettings.Get(group='nviz', key='view', subkey='pos')
  1108. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1109. label=_("Position") + " (x):"),
  1110. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1111. px = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1112. initial=posvals['x'] * 100,
  1113. min=0,
  1114. max=100)
  1115. self.win['settings']['view']['pos']['x'] = px.GetId()
  1116. gridSizer.Add(item=px, pos=(1, 1),
  1117. flag=wx.ALIGN_CENTER_VERTICAL)
  1118. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1119. label="(y):"),
  1120. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1121. py = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1122. initial=posvals['y'] * 100,
  1123. min=0,
  1124. max=100)
  1125. self.win['settings']['view']['pos']['y'] = py.GetId()
  1126. gridSizer.Add(item=py, pos=(1, 3),
  1127. flag=wx.ALIGN_CENTER_VERTICAL)
  1128. # height
  1129. self.win['settings']['view']['height'] = {}
  1130. hvals = UserSettings.Get(group='nviz', key='view', subkey='height')
  1131. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1132. label=_("Height") + " (min):"),
  1133. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1134. hmin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1135. initial=hvals['min'],
  1136. min=-1e6,
  1137. max=1e6)
  1138. self.win['settings']['view']['height']['min'] = hmin.GetId()
  1139. gridSizer.Add(item=hmin, pos=(2, 1),
  1140. flag=wx.ALIGN_CENTER_VERTICAL)
  1141. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1142. label="(max):"),
  1143. pos=(2, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1144. hmax = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1145. initial=hvals['max'],
  1146. min=-1e6,
  1147. max=1e6)
  1148. self.win['settings']['view']['height']['max'] = hmax.GetId()
  1149. gridSizer.Add(item=hmax, pos=(2, 3),
  1150. flag=wx.ALIGN_CENTER_VERTICAL)
  1151. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1152. label="(step):"),
  1153. pos=(2, 4), flag=wx.ALIGN_CENTER_VERTICAL)
  1154. hstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1155. initial=hvals['step'],
  1156. min=1,
  1157. max=hvals['max']-1)
  1158. self.win['settings']['view']['height']['step'] = hstep.GetId()
  1159. gridSizer.Add(item=hstep, pos=(2, 5),
  1160. flag=wx.ALIGN_CENTER_VERTICAL)
  1161. # twist
  1162. self.win['settings']['view']['twist'] = {}
  1163. tvals = UserSettings.Get(group='nviz', key='view', subkey='twist')
  1164. itvals = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
  1165. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1166. label=_("Twist (value):")),
  1167. pos=(3, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1168. tval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1169. initial=tvals['value'],
  1170. min=itvals['min'],
  1171. max=itvals['max'])
  1172. self.win['settings']['view']['twist']['value'] = tval.GetId()
  1173. gridSizer.Add(item=tval, pos=(3, 1),
  1174. flag=wx.ALIGN_CENTER_VERTICAL)
  1175. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1176. label=_("(step):")),
  1177. pos=(3, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1178. tstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1179. initial=tvals['step'],
  1180. min=itvals['min'],
  1181. max=itvals['max']-1)
  1182. self.win['settings']['view']['twist']['step'] = tstep.GetId()
  1183. gridSizer.Add(item=tstep, pos=(3, 3),
  1184. flag=wx.ALIGN_CENTER_VERTICAL)
  1185. # z-exag
  1186. self.win['settings']['view']['z-exag'] = {}
  1187. zvals = UserSettings.Get(group='nviz', key='view', subkey='z-exag')
  1188. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1189. label=_("Z-exag (value):")),
  1190. pos=(4, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1191. zval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1192. initial=zvals['value'],
  1193. min=-1e6,
  1194. max=1e6)
  1195. self.win['settings']['view']['z-exag']['value'] = zval.GetId()
  1196. gridSizer.Add(item=zval, pos=(4, 1),
  1197. flag=wx.ALIGN_CENTER_VERTICAL)
  1198. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1199. label=_("(step):")),
  1200. pos=(4, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1201. zstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1202. initial=zvals['step'],
  1203. min=-1e6,
  1204. max=1e6)
  1205. self.win['settings']['view']['z-exag']['step'] = zstep.GetId()
  1206. gridSizer.Add(item=zstep, pos=(4, 3),
  1207. flag=wx.ALIGN_CENTER_VERTICAL)
  1208. boxSizer.Add(item=gridSizer, proportion=1,
  1209. flag=wx.ALL | wx.EXPAND, border=3)
  1210. pageSizer.Add(item=boxSizer, proportion=0,
  1211. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1212. border=5)
  1213. #
  1214. # surface
  1215. #
  1216. self.win['settings']['surface'] = {}
  1217. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1218. label=" %s " % (_("Surface")))
  1219. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1220. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1221. boxSizer.Add(item=gridSizer, proportion=1,
  1222. flag=wx.ALL | wx.EXPAND, border=3)
  1223. pageSizer.Add(item=boxSizer, proportion=0,
  1224. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1225. border=5)
  1226. #
  1227. # vector
  1228. #
  1229. self.win['settings']['vector'] = {}
  1230. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1231. label=" %s " % (_("Vector")))
  1232. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1233. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1234. boxSizer.Add(item=gridSizer, proportion=1,
  1235. flag=wx.ALL | wx.EXPAND, border=3)
  1236. pageSizer.Add(item=boxSizer, proportion=0,
  1237. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1238. border=5)
  1239. #
  1240. # buttons
  1241. #
  1242. btnDefault = wx.Button(panel, wx.ID_CANCEL, label=_("Default"))
  1243. btnSave = wx.Button(panel, wx.ID_SAVE)
  1244. btnApply = wx.Button(panel, wx.ID_APPLY)
  1245. btnDefault.Bind(wx.EVT_BUTTON, self.OnDefault)
  1246. btnDefault.SetToolTipString(_("Restore default settings"))
  1247. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  1248. btnApply.SetToolTipString(_("Apply changes for the current session"))
  1249. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  1250. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  1251. btnSave.SetDefault()
  1252. btnSizer = wx.StdDialogButtonSizer()
  1253. btnSizer.AddButton(btnDefault)
  1254. btnSizer.AddButton(btnApply)
  1255. btnSizer.AddButton(btnSave)
  1256. btnSizer.Realize()
  1257. pageSizer.Add(item=btnSizer, proportion=1,
  1258. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM,
  1259. border=5)
  1260. panel.SetSizer(pageSizer)
  1261. def CreateControl(self, parent, dict, name, range, bind, sliderHor=True, size=200):
  1262. """Add control (Slider + SpinCtrl)"""
  1263. dict[name] = {}
  1264. if sliderHor:
  1265. style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  1266. wx.SL_BOTTOM
  1267. sizeW = (size, -1)
  1268. else:
  1269. style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | \
  1270. wx.SL_BOTTOM | wx.SL_INVERSE
  1271. sizeW = (-1, size)
  1272. try:
  1273. val = self.mapWindow.view[name]['value']
  1274. except KeyError:
  1275. val=-1
  1276. slider = wx.Slider(parent=parent, id=wx.ID_ANY,
  1277. value=val,
  1278. minValue=range[0],
  1279. maxValue=range[1],
  1280. style=style,
  1281. size=sizeW)
  1282. slider.SetName('slider')
  1283. slider.Bind(wx.EVT_SCROLL, bind[0])
  1284. slider.Bind(wx.EVT_SCROLL_CHANGED, bind[1])
  1285. dict[name]['slider'] = slider.GetId()
  1286. spin = wx.SpinCtrl(parent=parent, id=wx.ID_ANY, size=(65, -1),
  1287. initial=val,
  1288. min=range[0],
  1289. max=range[1])
  1290. # spin = wx.SpinButton(parent=parent, id=wx.ID_ANY)
  1291. # spin.SetValue (self.mapWindow.view[name]['value'])
  1292. # spin.SetRange(self.mapWindow.view[name]['min'],
  1293. # self.mapWindow.view[name]['max'])
  1294. # no 'changed' event ... (FIXME)
  1295. spin.SetName('spin')
  1296. spin.Bind(wx.EVT_SPINCTRL, bind[2])
  1297. dict[name]['spin'] = spin.GetId()
  1298. def UpdateSettings(self):
  1299. """Update dialog settings"""
  1300. for control in ('height',
  1301. 'persp',
  1302. 'twist',
  1303. 'z-exag'):
  1304. for win in self.win['view'][control].itervalues():
  1305. if control == 'height':
  1306. value = UserSettings.Get(group='nviz', key='view',
  1307. subkey=['height', 'value'], internal=True)
  1308. else:
  1309. value = self.mapWindow.view[control]['value']
  1310. self.FindWindowById(win).SetValue(value)
  1311. self.FindWindowById(self.win['view']['pos']).Draw()
  1312. self.FindWindowById(self.win['view']['pos']).Refresh(False)
  1313. self.Refresh(False)
  1314. def __GetWindowName(self, dict, id):
  1315. for name in dict.iterkeys():
  1316. if type(dict[name]) is type({}):
  1317. for win in dict[name].itervalues():
  1318. if win == id:
  1319. return name
  1320. else:
  1321. if dict[name] == id:
  1322. return name
  1323. return None
  1324. def OnViewChange(self, event):
  1325. """Change view, render in quick mode"""
  1326. # find control
  1327. winName = self.__GetWindowName(self.win['view'], event.GetId())
  1328. if not winName:
  1329. return
  1330. if winName == 'height':
  1331. view = self.mapWindow.iview # internal
  1332. else:
  1333. view = self.mapWindow.view
  1334. view[winName]['value'] = event.GetInt()
  1335. for win in self.win['view'][winName].itervalues():
  1336. self.FindWindowById(win).SetValue(view[winName]['value'])
  1337. self.mapWindow.update.append('view')
  1338. if winName == 'z-exag':
  1339. self.mapWindow.update.append('z-exag')
  1340. self.mapWindow.render = False
  1341. self.mapWindow.Refresh(False)
  1342. def OnViewChanged(self, event):
  1343. """View changed, render in full resolution"""
  1344. self.mapWindow.render = True
  1345. self.mapWindow.Refresh(False)
  1346. def OnViewChangedSpin(self, event):
  1347. """View changed, render in full resolution"""
  1348. # TODO: use step value instead
  1349. self.OnViewChange(event)
  1350. self.OnViewChanged(None)
  1351. def OnResetView(self, event):
  1352. """Reset to default view (view page)"""
  1353. self.mapWindow.ResetView()
  1354. self.UpdateSettings()
  1355. self.mapWindow.Refresh(False)
  1356. def OnLookAt(self, event):
  1357. """Look at (view page)"""
  1358. sel = event.GetSelection()
  1359. if sel == 0: # top
  1360. self.mapWindow.view['pos']['x'] = 0.5
  1361. self.mapWindow.view['pos']['y'] = 0.5
  1362. elif sel == 1: # north
  1363. self.mapWindow.view['pos']['x'] = 0.5
  1364. self.mapWindow.view['pos']['y'] = 0.0
  1365. elif sel == 2: # south
  1366. self.mapWindow.view['pos']['x'] = 0.5
  1367. self.mapWindow.view['pos']['y'] = 1.0
  1368. elif sel == 3: # east
  1369. self.mapWindow.view['pos']['x'] = 1.0
  1370. self.mapWindow.view['pos']['y'] = 0.5
  1371. elif sel == 4: # west
  1372. self.mapWindow.view['pos']['x'] = 0.0
  1373. self.mapWindow.view['pos']['y'] = 0.5
  1374. elif sel == 5: # north-west
  1375. self.mapWindow.view['pos']['x'] = 0.0
  1376. self.mapWindow.view['pos']['y'] = 0.0
  1377. elif sel == 6: # north-east
  1378. self.mapWindow.view['pos']['x'] = 1.0
  1379. self.mapWindow.view['pos']['y'] = 0.0
  1380. elif sel == 7: # south-east
  1381. self.mapWindow.view['pos']['x'] = 1.0
  1382. self.mapWindow.view['pos']['y'] = 1.0
  1383. elif sel == 8: # south-west
  1384. self.mapWindow.view['pos']['x'] = 0.0
  1385. self.mapWindow.view['pos']['y'] = 1.0
  1386. self.mapWindow.update.append('view')
  1387. self.UpdateSettings()
  1388. self.mapWindow.Refresh(False)
  1389. def OnDefault(self, event):
  1390. """Restore default settings"""
  1391. settings = copy.deepcopy(UserSettings.GetDefaultSettings()['nviz'])
  1392. UserSettings.Set(group='nviz',
  1393. value=settings)
  1394. for subgroup, key in settings.iteritems(): # view, surface, vector...
  1395. if subgroup != 'view':
  1396. continue
  1397. for subkey, value in key.iteritems():
  1398. for subvalue in value.keys():
  1399. win = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue])
  1400. val = settings[subgroup][subkey][subvalue]
  1401. if subkey == 'pos':
  1402. val = int(val * 100)
  1403. win.SetValue(val)
  1404. event.Skip()
  1405. def OnApply(self, event):
  1406. """Apply button pressed"""
  1407. if self.notebook.GetSelection() == self.page['settings']:
  1408. self.ApplySettings()
  1409. if event:
  1410. event.Skip()
  1411. def ApplySettings(self):
  1412. """Apply Nviz settings for current session"""
  1413. settings = UserSettings.Get(group='nviz')
  1414. for subgroup, key in settings.iteritems(): # view, surface, vector...
  1415. if subgroup != 'view':
  1416. continue
  1417. for subkey, value in key.iteritems():
  1418. for subvalue in value.keys():
  1419. value = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue]).GetValue()
  1420. if subkey == 'pos':
  1421. value = float(value) / 100
  1422. settings[subgroup][subkey][subvalue] = value
  1423. def OnSave(self, event):
  1424. """OK button pressed
  1425. Apply changes, update map and save settings of selected layer
  1426. """
  1427. #
  1428. # apply changes
  1429. #
  1430. self.OnApply(None)
  1431. if self.notebook.GetSelection() == self.page['settings']:
  1432. fileSettings = {}
  1433. UserSettings.ReadSettingsFile(settings=fileSettings)
  1434. fileSettings['nviz'] = UserSettings.Get(group='nviz')
  1435. file = UserSettings.SaveToFile(fileSettings)
  1436. self.lmgr.goutput.WriteLog(_('Nviz settings saved to file <%s>.') % file)
  1437. def OnBgColor(self, event):
  1438. """Background color changed"""
  1439. color = event.GetValue()
  1440. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1441. self.mapWindow.nvizClass.SetBgColor(str(color))
  1442. if self.parent.autoRender.IsChecked():
  1443. self.mapWindow.Refresh(False)
  1444. def OnClose(self, event):
  1445. """Close button pressed
  1446. Close dialog
  1447. """
  1448. self.Hide()
  1449. def OnSurfaceUse(self, event):
  1450. """Surface attribute -- use -- map/constant"""
  1451. if not self.mapWindow.init:
  1452. return
  1453. wx.Yield()
  1454. # find attribute row
  1455. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1456. if not attrb:
  1457. return
  1458. selection = event.GetSelection()
  1459. if self.win['surface'][attrb]['required']: # no 'unset'
  1460. selection += 1
  1461. if selection == 0: # unset
  1462. useMap = None
  1463. value = ''
  1464. elif selection == 1: # map
  1465. useMap = True
  1466. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1467. elif selection == 2: # constant
  1468. useMap = False
  1469. if attrb == 'color':
  1470. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1471. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1472. else:
  1473. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1474. self.SetSurfaceUseMap(attrb, useMap)
  1475. self.mapWindow.update.append('surface:attribute:%s' % attrb)
  1476. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1477. data['surface']['attribute'][attrb] = { 'map' : useMap,
  1478. 'value' : str(value),
  1479. }
  1480. self.mapWindow.UpdateLayerProperties()
  1481. if self.parent.autoRender.IsChecked():
  1482. self.mapWindow.Refresh(False)
  1483. def SetSurfaceUseMap(self, attrb, map=None):
  1484. if attrb in ('topo', 'color', 'shine'):
  1485. incSel = -1 # decrement selection (no 'unset')
  1486. else:
  1487. incSel = 0
  1488. if map is True: # map
  1489. if attrb != 'topo': # changing map topography not allowed
  1490. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(True) # FIXME
  1491. if self.win['surface'][attrb]['const']:
  1492. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1493. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(1 + incSel)
  1494. elif map is False: # const
  1495. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1496. if self.win['surface'][attrb]['const']:
  1497. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(True)
  1498. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(2 + incSel)
  1499. else: # unset
  1500. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1501. if self.win['surface'][attrb]['const']:
  1502. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1503. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(0)
  1504. def OnSurfaceMap(self, event):
  1505. """Set surface attribute"""
  1506. if not self.mapWindow.init:
  1507. return
  1508. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1509. if not attrb:
  1510. return
  1511. selection = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  1512. if self.win['surface'][attrb]['required']:
  1513. selection += 1
  1514. if selection == 0: # unset
  1515. map = None
  1516. value = ''
  1517. elif selection == 1: # map
  1518. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1519. map = True
  1520. else: # constant
  1521. if attrb == 'color':
  1522. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1523. # tuple to string
  1524. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1525. else:
  1526. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1527. map = False
  1528. if not self.pageChanging:
  1529. self.mapWindow.update.append('surface:attribute:%s' % attrb)
  1530. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1531. data['surface']['attribute'][attrb] = { 'map' : map,
  1532. 'value' : str(value),
  1533. }
  1534. self.mapWindow.UpdateLayerProperties()
  1535. if self.parent.autoRender.IsChecked():
  1536. self.mapWindow.Refresh(False)
  1537. def OnSurfaceResolution(self, event):
  1538. """Draw resolution changed"""
  1539. self.SetSurfaceResolution()
  1540. if apply and self.parent.autoRender.IsChecked():
  1541. self.mapWindow.Refresh(False)
  1542. def SetSurfaceResolution(self, all=False):
  1543. """Set draw resolution"""
  1544. coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
  1545. fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
  1546. self.mapWindow.update.append('surface:draw:resolution')
  1547. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1548. data['surface']['draw']['resolution'] = { 'coarse' : coarse,
  1549. 'fine' : fine,
  1550. 'all' : all }
  1551. self.mapWindow.UpdateLayerProperties()
  1552. def SetSurfaceMode(self, all=False):
  1553. """Set draw mode
  1554. @param apply allow auto-rendering
  1555. """
  1556. mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
  1557. if mode == 0: # coarse
  1558. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1559. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
  1560. elif mode == 1: # fine
  1561. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
  1562. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1563. else: # both
  1564. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1565. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1566. style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
  1567. shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
  1568. value, desc = self.mapWindow.GetSurfaceMode(mode, style, shade)
  1569. return value, desc
  1570. def OnSurfaceMode(self, event):
  1571. """Set draw mode"""
  1572. value, desc = self.SetSurfaceMode()
  1573. self.mapWindow.update.append('surface:draw:mode')
  1574. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1575. data['surface']['draw']['mode'] = { 'value' : value,
  1576. 'all' : False,
  1577. 'desc' : desc }
  1578. self.mapWindow.UpdateLayerProperties()
  1579. if apply and self.parent.autoRender.IsChecked():
  1580. self.mapWindow.Refresh(False)
  1581. def OnSurfaceModeAll(self, event):
  1582. """Set draw mode (including wire color) for all loaded surfaces"""
  1583. self.SetSurfaceMode(all=True)
  1584. self.SetSurfaceResolution(all=True)
  1585. color = self.FindWindowById(self.win['surface']['draw']['wire-color']).GetColour()
  1586. self.SetSurfaceWireColor(color, all=True)
  1587. if apply and self.parent.autoRender.IsChecked():
  1588. self.mapWindow.Refresh(False)
  1589. def SetSurfaceWireColor(self, color, all=False, apply=True):
  1590. """Set wire color"""
  1591. value = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1592. def OnSurfaceWireColor(self, event):
  1593. """Set wire color"""
  1594. self.SetSurfaceWireColor(event.GetValue())
  1595. self.mapWindow.update.append('surface:draw:wire-color')
  1596. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1597. data['surface']['draw']['wire-color'] = { 'value' : value,
  1598. 'all' : all }
  1599. self.mapWindow.UpdateLayerProperties()
  1600. if self.parent.autoRender.IsChecked():
  1601. self.mapWindow.Refresh(False)
  1602. def OnSurfaceAxis(self, event):
  1603. """Surface position, axis changed"""
  1604. mapLayer = self.mapWindow.GetSelectedLayer()
  1605. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1606. id = data['object']['id']
  1607. axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
  1608. win = self.FindWindowById(self.win['surface']['position']['pos'])
  1609. x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
  1610. if axis == 0: # x
  1611. win.SetRange(-1e4, 1e4)
  1612. win.SetValue(x)
  1613. elif axis == 1: # y
  1614. win.SetRange(-1e4, 1e4)
  1615. win.SetValue(y)
  1616. else: # z
  1617. win.SetRange(-1e3, 1e3)
  1618. win.SetValue(z)
  1619. def OnSurfacePosition(self, event):
  1620. """Surface position"""
  1621. axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
  1622. value = event.GetInt()
  1623. mapLayer = self.mapWindow.GetSelectedLayer()
  1624. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1625. id = data['object']['id']
  1626. x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
  1627. if axis == 0: # x
  1628. x = value
  1629. elif axis == 1: # y
  1630. y = value
  1631. else: # z
  1632. z = value
  1633. self.mapWindow.update.append('surface:position')
  1634. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1635. data['surface']['position']['x'] = x
  1636. data['surface']['position']['y'] = y
  1637. data['surface']['position']['z'] = z
  1638. self.mapWindow.UpdateLayerProperties()
  1639. if self.parent.autoRender.IsChecked():
  1640. self.mapWindow.Refresh(False)
  1641. def OnVectorDisplay(self, event):
  1642. """Display vector lines on surface/flat"""
  1643. if event.GetSelection() == 0: # surface
  1644. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(True)
  1645. # set first found surface
  1646. ### TODO
  1647. else: # flat
  1648. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(False)
  1649. self.OnVectorLines(event)
  1650. event.Skip()
  1651. def OnVectorLines(self, event):
  1652. """Set vector lines mode, apply changes if auto-rendering is enabled"""
  1653. width = self.FindWindowById(self.win['vector']['lines']['width']).GetValue()
  1654. color = self.FindWindowById(self.win['vector']['lines']['color']).GetColour()
  1655. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1656. mode = {}
  1657. if self.FindWindowById(self.win['vector']['lines']['flat']).GetSelection() == 0:
  1658. mode['type'] = 'surface'
  1659. mode['map'] = '' # TODO
  1660. else:
  1661. mode['type'] = 'flat'
  1662. self.mapWindow.update.append('vector:lines:width')
  1663. self.mapWindow.update.append('vector:lines:color')
  1664. self.mapWindow.update.append('vector:lines:mode')
  1665. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1666. data['vector']['lines']['width'] = width
  1667. data['vector']['lines']['color'] = color
  1668. data['vector']['lines']['mode'] = mode
  1669. self.mapWindow.UpdateLayerProperties()
  1670. if self.parent.autoRender.IsChecked():
  1671. self.mapWindow.Refresh(False)
  1672. def OnVectorHeight(self, event):
  1673. value = event.GetInt()
  1674. if type(event) == type(wx.ScrollEvent()):
  1675. # slider
  1676. win = self.FindWindowById(self.win['vector']['lines']['height']['spin'])
  1677. else:
  1678. # spin
  1679. win = self.FindWindowById(self.win['vector']['lines']['height']['slider'])
  1680. win.SetValue(value)
  1681. self.mapWindow.update.append('vector:lines:height')
  1682. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1683. data['vector']['lines']['height'] = value
  1684. self.mapWindow.UpdateLayerProperties()
  1685. if self.parent.autoRender.IsChecked():
  1686. self.mapWindow.Refresh(False)
  1687. def UpdatePage(self, pageId):
  1688. """Update dialog (selected page)"""
  1689. self.pageChanging = True
  1690. layer = self.mapWindow.GetSelectedLayer()
  1691. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1692. if pageId == 'view':
  1693. max = self.mapWindow.view['z-exag']['value'] * 10
  1694. for control in ('spin', 'slider'):
  1695. self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(0,
  1696. max)
  1697. elif pageId == 'surface':
  1698. self.UpdateSurfacePage(layer, data['surface'])
  1699. # disable vector and enable surface page
  1700. self.notebook.GetPage(self.page['surface']).Enable(True)
  1701. self.notebook.GetPage(self.page['vector']).Enable(False)
  1702. elif pageId == 'vector':
  1703. self.UpdateVectorPage(layer, data['vector'])
  1704. # disable surface and enable current
  1705. self.notebook.GetPage(self.page['surface']).Enable(False)
  1706. self.notebook.GetPage(self.page['vector']).Enable(True)
  1707. self.pageChanging = False
  1708. def UpdateSurfacePage(self, layer, data):
  1709. #
  1710. # attributes
  1711. #
  1712. for attr in ('topo', 'color'): # required
  1713. if layer and layer.type == 'raster':
  1714. self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
  1715. else:
  1716. self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
  1717. self.SetSurfaceUseMap(attr, True) # -> map
  1718. if data['attribute'].has_key('color'):
  1719. value = data['attribute']['color']['value']
  1720. if data['attribute']['color']['map']:
  1721. self.FindWindowById(self.win['surface']['color']['map']).SetValue(value)
  1722. else: # constant
  1723. color = map(int, value.split(':'))
  1724. self.FindWindowById(self.win['surface']['color']['const']).SetColour(color)
  1725. self.SetSurfaceUseMap(attr, data['attribute']['color']['map'])
  1726. self.SetSurfaceUseMap('shine', data['attribute']['shine']['map'])
  1727. value = data['attribute']['shine']['value']
  1728. if data['attribute']['shine']['map']:
  1729. self.FindWindowById(self.win['surface']['shine']['map']).SetValue(value)
  1730. else:
  1731. self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
  1732. #
  1733. # draw
  1734. #
  1735. for control, dict in data['draw'].iteritems():
  1736. if control == 'resolution':
  1737. self.FindWindowById(self.win['surface']['draw']['res-coarse']).SetValue(dict['coarse'])
  1738. self.FindWindowById(self.win['surface']['draw']['res-fine']).SetValue(dict['fine'])
  1739. continue
  1740. if control == 'mode':
  1741. if dict['desc']['mode'] == 'coarse':
  1742. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(0)
  1743. elif dict['desc']['mode'] == 'fine':
  1744. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(1)
  1745. else: # both
  1746. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(2)
  1747. if dict['desc']['style'] == 'wire':
  1748. self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(0)
  1749. else: # surface
  1750. self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(1)
  1751. if dict['desc']['shading'] == 'flat':
  1752. self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(0)
  1753. else: # gouraud
  1754. self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(1)
  1755. continue
  1756. value = dict['value']
  1757. win = self.FindWindowById(self.win['surface']['draw'][control])
  1758. name = win.GetName()
  1759. if name == "selection":
  1760. win.SetSelection(value)
  1761. elif name == "colour":
  1762. color = map(int, value.split(':'))
  1763. win.SetColour(color)
  1764. else:
  1765. win.SetValue(value)
  1766. # enable/disable res widget + set draw mode
  1767. self.SetSurfaceMode()
  1768. color = self.FindWindowById(self.win['surface']['draw']['wire-color'])
  1769. self.SetSurfaceWireColor(color.GetColour())
  1770. def UpdateVectorPage(self, layer, data):
  1771. #
  1772. # lines
  1773. #
  1774. width = self.FindWindowById(self.win['vector']['lines']['width'])
  1775. width.SetValue(data['lines']['width'])
  1776. color = self.FindWindowById(self.win['vector']['lines']['color'])
  1777. color.SetValue(map(int, data['lines']['color'].split(':')))
  1778. display = self.FindWindowById(self.win['vector']['lines']['flat'])
  1779. if data['lines']['mode']['type'] == 'flat':
  1780. display.SetSelection(1)
  1781. else:
  1782. display.SetSelection(0)
  1783. for type in ('slider', 'spin'):
  1784. win = self.FindWindowById(self.win['vector']['lines']['height'][type])
  1785. win.SetValue(data['lines']['height'])
  1786. def SetPage(self, name):
  1787. """Get named page"""
  1788. self.notebook.SetSelection(self.page[name])
  1789. class ViewPositionWindow(wx.Window):
  1790. """Position control window (for NvizToolWindow)"""
  1791. def __init__(self, parent, id, mapwindow,
  1792. pos=wx.DefaultPosition,
  1793. size=wx.DefaultSize):
  1794. self.mapWindow = mapwindow
  1795. wx.Window.__init__(self, parent, id, pos, size)
  1796. self.SetBackgroundColour("WHITE")
  1797. self.pdc = wx.PseudoDC()
  1798. self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
  1799. self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
  1800. self.Draw()
  1801. self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
  1802. self.Bind(wx.EVT_PAINT, self.OnPaint)
  1803. # self.Bind(wx.EVT_MOTION, self.OnMouse)
  1804. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
  1805. def Draw(self, pos=None):
  1806. w, h = self.GetClientSize()
  1807. if pos is None:
  1808. x = self.mapWindow.view['pos']['x']
  1809. y = self.mapWindow.view['pos']['y']
  1810. x = x * w
  1811. y = y * h
  1812. else:
  1813. x, y = pos
  1814. self.pdc.Clear()
  1815. self.pdc.BeginDrawing()
  1816. self.pdc.DrawLine(w / 2, h / 2, x, y)
  1817. self.pdc.DrawCircle(x, y, 5)
  1818. self.pdc.EndDrawing()
  1819. def OnPaint(self, event):
  1820. dc = wx.BufferedPaintDC(self)
  1821. dc.SetBackground(wx.Brush("White"))
  1822. dc.Clear()
  1823. self.PrepareDC(dc)
  1824. self.pdc.DrawToDC(dc)
  1825. def OnMouse(self, event):
  1826. if event.LeftIsDown():
  1827. x, y = event.GetPosition()
  1828. self.Draw(pos=(x, y))
  1829. self.Refresh(False)
  1830. w, h = self.GetClientSize()
  1831. x = float(x) / w
  1832. y = float(y) / h
  1833. if x >= 0 and x <= 1.0:
  1834. self.mapWindow.view['pos']['x'] = x
  1835. if y >= 0 and y <= 1.0:
  1836. self.mapWindow.view['pos']['y'] = y
  1837. self.mapWindow.update.append('view')
  1838. self.mapWindow.render = False
  1839. self.mapWindow.Refresh(eraseBackground=False)
  1840. elif event.LeftUp():
  1841. self.mapWindow.render = True
  1842. self.mapWindow.Refresh(eraseBackground=False)
  1843. event.Skip()