nviz.py 86 KB

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