nviz.py 87 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269
  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 not item.IsChecked() or \
  237. type not in ('raster', 'vector'):
  238. item = self.tree.GetNextSibling(item)
  239. continue
  240. listOfItems.append(item)
  241. item = self.tree.GetNextSibling(item)
  242. start = time.time()
  243. while(len(listOfItems) > 0):
  244. item = listOfItems.pop()
  245. type = self.tree.GetPyData(item)[0]['type']
  246. mapLayer = self.tree.GetPyData(item)[0]['maplayer']
  247. if type == 'raster':
  248. id = self.LoadRaster(mapLayer)
  249. elif type == 'vector':
  250. id = self.LoadVector(mapLayer)
  251. if type == 'raster' or type == 'vector':
  252. self.SetLayerData(item, id)
  253. self.UpdateLayerProperties(item)
  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'] = { 'id' : 0 }
  595. # surface page
  596. size = self.__createSurfacePage()
  597. size = (size[0] + 20, size[0] + 20)
  598. # vector page
  599. self.__createVectorPage()
  600. # settings page
  601. self.__createSettingsPage()
  602. self.page['settings'] = { 'id' : 1 }
  603. self.UpdatePage('settings')
  604. self.pageChanging = False
  605. mainSizer.Add(item=self.notebook, proportion=1,
  606. flag=wx.EXPAND | wx.ALL, border=5)
  607. #
  608. # bindings
  609. #
  610. self.Bind(wx.EVT_CLOSE, self.OnClose)
  611. #
  612. # layout
  613. #
  614. self.SetSizer(mainSizer)
  615. mainSizer.Fit(self)
  616. self.SetSize(size)
  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. return panel.GetBestSize()
  720. def __createSurfacePage(self):
  721. """Create view settings page"""
  722. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  723. self.page['surface'] = {}
  724. self.page['surface']['id'] = -1
  725. self.page['surface']['panel'] = panel.GetId()
  726. # panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY)
  727. # panel.SetupScrolling(scroll_x=True, scroll_y=True)
  728. pageSizer = wx.BoxSizer(wx.VERTICAL)
  729. self.win['surface'] = {}
  730. #
  731. # surface attributes
  732. #
  733. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  734. label=" %s " % (_("Surface attributes")))
  735. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  736. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  737. # labels
  738. # col = 0
  739. # for type in (_("Attribute"),
  740. # _("Use"),
  741. # _("Map"),
  742. # _("Constant")):
  743. # gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  744. # label=type),
  745. # pos=(0, col))
  746. # col += 1
  747. # type
  748. self.win['surface']['attr'] = {}
  749. row = 0
  750. for code, attrb in (('topo', _("Topography")),
  751. ('color', _("Color")),
  752. ('mask', _("Mask")),
  753. ('transp', _("Transparency")),
  754. ('shine', _("Shininess")),
  755. ('emit', _("Emission"))):
  756. self.win['surface'][code] = {}
  757. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  758. label=attrb + ':'),
  759. pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  760. use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  761. choices = [_("map")])
  762. if code not in ('topo', 'color', 'shine'):
  763. use.Insert(item=_("unset"), pos=0)
  764. self.win['surface'][code]['required'] = False
  765. else:
  766. self.win['surface'][code]['required'] = True
  767. if code != 'mask':
  768. use.Append(item=_('constant'))
  769. self.win['surface'][code]['use'] = use.GetId()
  770. use.Bind(wx.EVT_CHOICE, self.OnSurfaceUse)
  771. gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
  772. pos=(row, 1))
  773. map = gselect.Select(parent=panel, id=wx.ID_ANY,
  774. # size=globalvar.DIALOG_GSELECT_SIZE,
  775. size=(200, -1),
  776. type="raster")
  777. self.win['surface'][code]['map'] = map.GetId() - 1 # FIXME
  778. map.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  779. # changing map topography not allowed
  780. if code == 'topo':
  781. map.Enable(False)
  782. gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
  783. pos=(row, 2))
  784. if code == 'color':
  785. value = csel.ColourSelect(panel, id=wx.ID_ANY,
  786. colour=UserSettings.Get(group='nviz', key='surface',
  787. subkey=['color', 'value']))
  788. value.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceMap)
  789. elif code == 'mask':
  790. value = None
  791. else:
  792. value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  793. initial=0)
  794. if code == 'topo':
  795. value.SetRange(minVal=-1e9, maxVal=1e9)
  796. elif code in ('shine', 'transp', 'emit'):
  797. value.SetRange(minVal=0, maxVal=255)
  798. else:
  799. value.SetRange(minVal=0, maxVal=100)
  800. value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  801. if value:
  802. self.win['surface'][code]['const'] = value.GetId()
  803. value.Enable(False)
  804. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  805. pos=(row, 3))
  806. else:
  807. self.win['surface'][code]['const'] = None
  808. self.SetSurfaceUseMap(code) # -> enable map / disable constant
  809. row += 1
  810. boxSizer.Add(item=gridSizer, proportion=1,
  811. flag=wx.ALL | wx.EXPAND, border=3)
  812. pageSizer.Add(item=boxSizer, proportion=0,
  813. flag=wx.EXPAND | wx.ALL,
  814. border=5)
  815. #
  816. # draw
  817. #
  818. self.win['surface']['draw'] = {}
  819. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  820. label=" %s " % (_("Draw")))
  821. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  822. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  823. gridSizer.AddGrowableCol(4)
  824. # mode
  825. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  826. label=_("Mode:")),
  827. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  828. mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  829. choices = [_("coarse"),
  830. _("fine"),
  831. _("both")])
  832. mode.SetSelection(0)
  833. mode.SetName("selection")
  834. mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  835. self.win['surface']['draw']['mode'] = mode.GetId()
  836. gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
  837. pos=(0, 1))
  838. # resolution (mode)
  839. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  840. label=_("Resolution:")),
  841. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  842. resSizer = wx.BoxSizer(wx.HORIZONTAL)
  843. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  844. label=_("coarse:")),
  845. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  846. resC = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  847. initial=1,
  848. min=1,
  849. max=100)
  850. resC.SetName("value")
  851. self.win['surface']['draw']['res-coarse'] = resC.GetId()
  852. resC.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  853. resSizer.Add(item=resC, flag=wx.ALL, border=3)
  854. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  855. label=_("fine:")),
  856. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  857. resF = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  858. initial=1,
  859. min=1,
  860. max=100)
  861. resF.SetName("value")
  862. self.win['surface']['draw']['res-fine'] = resF.GetId()
  863. resF.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  864. resSizer.Add(item=resF, flag=wx.ALL, border=3)
  865. gridSizer.Add(item=resSizer, pos=(0, 3), span=(1, 2))
  866. # style
  867. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  868. label=_("Coarse style:")),
  869. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  870. style = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  871. choices = [_("wire"),
  872. _("surface")])
  873. style.SetName("selection")
  874. self.win['surface']['draw']['style'] = style.GetId()
  875. style.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  876. gridSizer.Add(item=style, flag=wx.ALIGN_CENTER_VERTICAL,
  877. pos=(1, 1))
  878. # shading
  879. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  880. label=_("Shading:")),
  881. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  882. shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  883. choices = [_("flat"),
  884. _("gouraud")])
  885. shade.SetName("selection")
  886. self.win['surface']['draw']['shading'] = shade.GetId()
  887. shade.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  888. gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
  889. pos=(1, 3))
  890. # color
  891. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  892. label=_("Wire color:")),
  893. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  894. color = csel.ColourSelect(panel, id=wx.ID_ANY)
  895. color.SetName("colour")
  896. color.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceWireColor)
  897. self.win['surface']['draw']['wire-color'] = color.GetId()
  898. gridSizer.Add(item=color, flag=wx.ALIGN_CENTER_VERTICAL,
  899. pos=(2, 1))
  900. boxSizer.Add(item=gridSizer, proportion=1,
  901. flag=wx.ALL | wx.EXPAND, border=3)
  902. pageSizer.Add(item=boxSizer, proportion=0,
  903. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  904. border=5)
  905. all = wx.Button(panel, id=wx.ID_ANY, label=_("All"))
  906. all.SetToolTipString(_("Use for all loaded surfaces"))
  907. # self.win['reset'] = reset.GetId()
  908. all.Bind(wx.EVT_BUTTON, self.OnSurfaceModeAll)
  909. gridSizer.Add(item=all, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
  910. pos=(2, 4))
  911. #
  912. # mask
  913. #
  914. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  915. label=" %s " % (_("Mask")))
  916. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  917. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  918. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  919. label=_("Mask zeros:")),
  920. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  921. elev = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  922. label=_("by elevation"))
  923. elev.Enable(False) # TODO: not implemented yet
  924. gridSizer.Add(item=elev, pos=(0, 1))
  925. color = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  926. label=_("by color"))
  927. color.Enable(False) # TODO: not implemented yet
  928. gridSizer.Add(item=color, pos=(0, 2))
  929. boxSizer.Add(item=gridSizer, proportion=1,
  930. flag=wx.ALL | wx.EXPAND, border=3)
  931. pageSizer.Add(item=boxSizer, proportion=0,
  932. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  933. border=5)
  934. #
  935. # position
  936. #
  937. self.win['surface']['position'] = {}
  938. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  939. label=" %s " % (_("Position")))
  940. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  941. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  942. # position
  943. axis = wx.Choice (parent=panel, id=wx.ID_ANY, size=(75, -1),
  944. choices = ["X",
  945. "Y",
  946. "Z"])
  947. axis.SetSelection(0)
  948. self.win['surface']['position']['axis'] = axis.GetId()
  949. axis.Bind(wx.EVT_CHOICE, self.OnSurfaceAxis)
  950. gridSizer.Add(item=axis, flag=wx.ALIGN_CENTER_VERTICAL,
  951. pos=(0, 0))
  952. value = wx.Slider(parent=panel, id=wx.ID_ANY,
  953. value=0,
  954. minValue=-1e4,
  955. maxValue=1e4,
  956. style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  957. wx.SL_TOP | wx.SL_LABELS,
  958. size=(350, -1))
  959. self.win['surface']['position']['pos'] = value.GetId()
  960. value.Bind(wx.EVT_SCROLL, self.OnSurfacePosition)
  961. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  962. pos=(0, 1))
  963. boxSizer.Add(item=gridSizer, proportion=1,
  964. flag=wx.ALL | wx.EXPAND, border=3)
  965. pageSizer.Add(item=boxSizer, proportion=0,
  966. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  967. border=5)
  968. panel.SetSizer(pageSizer)
  969. return panel.GetBestSize()
  970. def __createVectorPage(self):
  971. """Create view settings page"""
  972. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  973. self.page['vector'] = {}
  974. self.page['vector']['id'] = -1
  975. self.page['vector']['panel'] = panel.GetId()
  976. pageSizer = wx.BoxSizer(wx.VERTICAL)
  977. self.win['vector'] = {}
  978. #
  979. # vector lines
  980. #
  981. self.win['vector']['lines'] = {}
  982. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  983. label=" %s " % (_("Vector lines")))
  984. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  985. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  986. # width
  987. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  988. label=_("Width:")),
  989. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  990. width = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  991. initial=1,
  992. min=1,
  993. max=100)
  994. self.win['vector']['lines']['width'] = width.GetId()
  995. width.Bind(wx.EVT_SPINCTRL, self.OnVectorLines)
  996. gridSizer.Add(item=width, pos=(0, 1),
  997. flag=wx.ALIGN_CENTER_VERTICAL)
  998. gridSizer.AddGrowableCol(2)
  999. # color
  1000. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1001. label=_("Color:")),
  1002. pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL)
  1003. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  1004. colour=UserSettings.Get(group='nviz', key='vector',
  1005. subkey=['lines', 'color']))
  1006. self.win['vector']['lines']['color'] = color.GetId()
  1007. color.Bind(csel.EVT_COLOURSELECT, self.OnVectorLines)
  1008. gridSizer.Add(item=color, pos=(0, 4))
  1009. gridSizer.AddGrowableCol(5)
  1010. # display
  1011. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1012. label=_("Display:")),
  1013. pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
  1014. display = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  1015. choices = [_("on surface"),
  1016. _("flat")])
  1017. self.win['vector']['lines']['flat'] = display.GetId()
  1018. display.Bind(wx.EVT_CHOICE, self.OnVectorDisplay)
  1019. gridSizer.Add(item=display, flag=wx.ALIGN_CENTER_VERTICAL,
  1020. pos=(0, 7))
  1021. surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
  1022. style=wx.CB_SIMPLE | wx.CB_READONLY,
  1023. choices=[])
  1024. self.win['vector']['lines']['surface'] = surface.GetId()
  1025. gridSizer.Add(item=surface,
  1026. pos=(1, 0), span=(1, 8),
  1027. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
  1028. # high
  1029. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1030. label=_("Hight above surface:")),
  1031. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL,
  1032. span=(1, 2))
  1033. self.CreateControl(panel, dict=self.win['vector']['lines'], name='height', size=300,
  1034. range=(0, 1000),
  1035. bind=(self.OnVectorHeight, self.OnVectorHeight, self.OnVectorHeight))
  1036. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['slider']),
  1037. pos=(2, 2), span=(1, 6))
  1038. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['spin']),
  1039. pos=(3, 4),
  1040. flag=wx.ALIGN_CENTER)
  1041. boxSizer.Add(item=gridSizer, proportion=1,
  1042. flag=wx.ALL | wx.EXPAND, border=3)
  1043. pageSizer.Add(item=boxSizer, proportion=0,
  1044. flag=wx.EXPAND | wx.ALL,
  1045. border=5)
  1046. panel.SetSizer(pageSizer)
  1047. return panel.GetBestSize()
  1048. def __createSettingsPage(self):
  1049. """Create settings page"""
  1050. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  1051. self.notebook.AddPage(page=panel,
  1052. text=" %s " % _("Settings"))
  1053. pageSizer = wx.BoxSizer(wx.VERTICAL)
  1054. self.win['settings'] = {}
  1055. #
  1056. # general
  1057. #
  1058. self.win['settings']['general'] = {}
  1059. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1060. label=" %s " % (_("General")))
  1061. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1062. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1063. # background color
  1064. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1065. label=_("Background color:")),
  1066. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1067. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  1068. colour=UserSettings.Get(group='nviz', key='settings',
  1069. subkey=['general', 'bgcolor']))
  1070. self.win['settings']['general']['bgcolor'] = color.GetId()
  1071. color.Bind(csel.EVT_COLOURSELECT, self.OnBgColor)
  1072. gridSizer.Add(item=color, pos=(0, 1))
  1073. boxSizer.Add(item=gridSizer, proportion=1,
  1074. flag=wx.ALL | wx.EXPAND, border=3)
  1075. pageSizer.Add(item=boxSizer, proportion=0,
  1076. flag=wx.EXPAND | wx.ALL,
  1077. border=5)
  1078. #
  1079. # view
  1080. #
  1081. self.win['settings']['view'] = {}
  1082. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1083. label=" %s " % (_("View")))
  1084. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1085. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1086. # perspective
  1087. self.win['settings']['view']['persp'] = {}
  1088. pvals = UserSettings.Get(group='nviz', key='view', subkey='persp')
  1089. ipvals = UserSettings.Get(group='nviz', key='view', subkey='persp', internal=True)
  1090. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1091. label=_("Perspective (value):")),
  1092. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1093. pval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1094. initial=pvals['value'],
  1095. min=ipvals['min'],
  1096. max=ipvals['max'])
  1097. self.win['settings']['view']['persp']['value'] = pval.GetId()
  1098. gridSizer.Add(item=pval, pos=(0, 1),
  1099. flag=wx.ALIGN_CENTER_VERTICAL)
  1100. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1101. label=_("(step):")),
  1102. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1103. pstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1104. initial=pvals['step'],
  1105. min=ipvals['min'],
  1106. max=ipvals['max']-1)
  1107. self.win['settings']['view']['persp']['step'] = pstep.GetId()
  1108. gridSizer.Add(item=pstep, pos=(0, 3),
  1109. flag=wx.ALIGN_CENTER_VERTICAL)
  1110. # position
  1111. self.win['settings']['view']['pos'] = {}
  1112. posvals = UserSettings.Get(group='nviz', key='view', subkey='pos')
  1113. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1114. label=_("Position") + " (x):"),
  1115. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1116. px = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1117. initial=posvals['x'] * 100,
  1118. min=0,
  1119. max=100)
  1120. self.win['settings']['view']['pos']['x'] = px.GetId()
  1121. gridSizer.Add(item=px, pos=(1, 1),
  1122. flag=wx.ALIGN_CENTER_VERTICAL)
  1123. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1124. label="(y):"),
  1125. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1126. py = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1127. initial=posvals['y'] * 100,
  1128. min=0,
  1129. max=100)
  1130. self.win['settings']['view']['pos']['y'] = py.GetId()
  1131. gridSizer.Add(item=py, pos=(1, 3),
  1132. flag=wx.ALIGN_CENTER_VERTICAL)
  1133. # height
  1134. self.win['settings']['view']['height'] = {}
  1135. hvals = UserSettings.Get(group='nviz', key='view', subkey='height')
  1136. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1137. label=_("Height") + " (min):"),
  1138. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1139. hmin = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1140. initial=hvals['min'],
  1141. min=-1e6,
  1142. max=1e6)
  1143. self.win['settings']['view']['height']['min'] = hmin.GetId()
  1144. gridSizer.Add(item=hmin, pos=(2, 1),
  1145. flag=wx.ALIGN_CENTER_VERTICAL)
  1146. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1147. label="(max):"),
  1148. pos=(2, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1149. hmax = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1150. initial=hvals['max'],
  1151. min=-1e6,
  1152. max=1e6)
  1153. self.win['settings']['view']['height']['max'] = hmax.GetId()
  1154. gridSizer.Add(item=hmax, pos=(2, 3),
  1155. flag=wx.ALIGN_CENTER_VERTICAL)
  1156. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1157. label="(step):"),
  1158. pos=(2, 4), flag=wx.ALIGN_CENTER_VERTICAL)
  1159. hstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1160. initial=hvals['step'],
  1161. min=1,
  1162. max=hvals['max']-1)
  1163. self.win['settings']['view']['height']['step'] = hstep.GetId()
  1164. gridSizer.Add(item=hstep, pos=(2, 5),
  1165. flag=wx.ALIGN_CENTER_VERTICAL)
  1166. # twist
  1167. self.win['settings']['view']['twist'] = {}
  1168. tvals = UserSettings.Get(group='nviz', key='view', subkey='twist')
  1169. itvals = UserSettings.Get(group='nviz', key='view', subkey='twist', internal=True)
  1170. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1171. label=_("Twist (value):")),
  1172. pos=(3, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1173. tval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1174. initial=tvals['value'],
  1175. min=itvals['min'],
  1176. max=itvals['max'])
  1177. self.win['settings']['view']['twist']['value'] = tval.GetId()
  1178. gridSizer.Add(item=tval, pos=(3, 1),
  1179. flag=wx.ALIGN_CENTER_VERTICAL)
  1180. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1181. label=_("(step):")),
  1182. pos=(3, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1183. tstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1184. initial=tvals['step'],
  1185. min=itvals['min'],
  1186. max=itvals['max']-1)
  1187. self.win['settings']['view']['twist']['step'] = tstep.GetId()
  1188. gridSizer.Add(item=tstep, pos=(3, 3),
  1189. flag=wx.ALIGN_CENTER_VERTICAL)
  1190. # z-exag
  1191. self.win['settings']['view']['z-exag'] = {}
  1192. zvals = UserSettings.Get(group='nviz', key='view', subkey='z-exag')
  1193. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1194. label=_("Z-exag (value):")),
  1195. pos=(4, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  1196. zval = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1197. initial=zvals['value'],
  1198. min=-1e6,
  1199. max=1e6)
  1200. self.win['settings']['view']['z-exag']['value'] = zval.GetId()
  1201. gridSizer.Add(item=zval, pos=(4, 1),
  1202. flag=wx.ALIGN_CENTER_VERTICAL)
  1203. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1204. label=_("(step):")),
  1205. pos=(4, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  1206. zstep = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  1207. initial=zvals['step'],
  1208. min=-1e6,
  1209. max=1e6)
  1210. self.win['settings']['view']['z-exag']['step'] = zstep.GetId()
  1211. gridSizer.Add(item=zstep, pos=(4, 3),
  1212. flag=wx.ALIGN_CENTER_VERTICAL)
  1213. boxSizer.Add(item=gridSizer, proportion=1,
  1214. flag=wx.ALL | wx.EXPAND, border=3)
  1215. pageSizer.Add(item=boxSizer, proportion=0,
  1216. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1217. border=5)
  1218. #
  1219. # surface
  1220. #
  1221. self.win['settings']['surface'] = {}
  1222. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1223. label=" %s " % (_("Surface")))
  1224. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1225. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1226. boxSizer.Add(item=gridSizer, proportion=1,
  1227. flag=wx.ALL | wx.EXPAND, border=3)
  1228. pageSizer.Add(item=boxSizer, proportion=0,
  1229. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1230. border=5)
  1231. #
  1232. # vector
  1233. #
  1234. self.win['settings']['vector'] = {}
  1235. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  1236. label=" %s " % (_("Vector")))
  1237. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1238. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  1239. boxSizer.Add(item=gridSizer, proportion=1,
  1240. flag=wx.ALL | wx.EXPAND, border=3)
  1241. pageSizer.Add(item=boxSizer, proportion=0,
  1242. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  1243. border=5)
  1244. #
  1245. # buttons
  1246. #
  1247. btnDefault = wx.Button(panel, wx.ID_CANCEL, label=_("Default"))
  1248. btnSave = wx.Button(panel, wx.ID_SAVE)
  1249. btnApply = wx.Button(panel, wx.ID_APPLY)
  1250. btnDefault.Bind(wx.EVT_BUTTON, self.OnDefault)
  1251. btnDefault.SetToolTipString(_("Restore default settings"))
  1252. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  1253. btnApply.SetToolTipString(_("Apply changes for the current session"))
  1254. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  1255. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  1256. btnSave.SetDefault()
  1257. btnSizer = wx.StdDialogButtonSizer()
  1258. btnSizer.AddButton(btnDefault)
  1259. btnSizer.AddButton(btnApply)
  1260. btnSizer.AddButton(btnSave)
  1261. btnSizer.Realize()
  1262. pageSizer.Add(item=btnSizer, proportion=1,
  1263. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM,
  1264. border=5)
  1265. panel.SetSizer(pageSizer)
  1266. return panel.GetBestSize()
  1267. def CreateControl(self, parent, dict, name, range, bind, sliderHor=True, size=200):
  1268. """Add control (Slider + SpinCtrl)"""
  1269. dict[name] = {}
  1270. if sliderHor:
  1271. style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  1272. wx.SL_BOTTOM
  1273. sizeW = (size, -1)
  1274. else:
  1275. style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | \
  1276. wx.SL_BOTTOM | wx.SL_INVERSE
  1277. sizeW = (-1, size)
  1278. try:
  1279. val = self.mapWindow.view[name]['value']
  1280. except KeyError:
  1281. val=-1
  1282. slider = wx.Slider(parent=parent, id=wx.ID_ANY,
  1283. value=val,
  1284. minValue=range[0],
  1285. maxValue=range[1],
  1286. style=style,
  1287. size=sizeW)
  1288. slider.SetName('slider')
  1289. slider.Bind(wx.EVT_SCROLL, bind[0])
  1290. slider.Bind(wx.EVT_SCROLL_CHANGED, bind[1])
  1291. dict[name]['slider'] = slider.GetId()
  1292. spin = wx.SpinCtrl(parent=parent, id=wx.ID_ANY, size=(65, -1),
  1293. initial=val,
  1294. min=range[0],
  1295. max=range[1])
  1296. # spin = wx.SpinButton(parent=parent, id=wx.ID_ANY)
  1297. # spin.SetValue (self.mapWindow.view[name]['value'])
  1298. # spin.SetRange(self.mapWindow.view[name]['min'],
  1299. # self.mapWindow.view[name]['max'])
  1300. # no 'changed' event ... (FIXME)
  1301. spin.SetName('spin')
  1302. spin.Bind(wx.EVT_SPINCTRL, bind[2])
  1303. dict[name]['spin'] = spin.GetId()
  1304. def UpdateSettings(self):
  1305. """Update dialog settings"""
  1306. for control in ('height',
  1307. 'persp',
  1308. 'twist',
  1309. 'z-exag'):
  1310. for win in self.win['view'][control].itervalues():
  1311. if control == 'height':
  1312. value = UserSettings.Get(group='nviz', key='view',
  1313. subkey=['height', 'value'], internal=True)
  1314. else:
  1315. value = self.mapWindow.view[control]['value']
  1316. self.FindWindowById(win).SetValue(value)
  1317. self.FindWindowById(self.win['view']['pos']).Draw()
  1318. self.FindWindowById(self.win['view']['pos']).Refresh(False)
  1319. self.Refresh(False)
  1320. def __GetWindowName(self, dict, id):
  1321. for name in dict.iterkeys():
  1322. if type(dict[name]) is type({}):
  1323. for win in dict[name].itervalues():
  1324. if win == id:
  1325. return name
  1326. else:
  1327. if dict[name] == id:
  1328. return name
  1329. return None
  1330. def OnViewChange(self, event):
  1331. """Change view, render in quick mode"""
  1332. # find control
  1333. winName = self.__GetWindowName(self.win['view'], event.GetId())
  1334. if not winName:
  1335. return
  1336. if winName == 'height':
  1337. view = self.mapWindow.iview # internal
  1338. else:
  1339. view = self.mapWindow.view
  1340. view[winName]['value'] = event.GetInt()
  1341. for win in self.win['view'][winName].itervalues():
  1342. self.FindWindowById(win).SetValue(view[winName]['value'])
  1343. self.mapWindow.update.append('view')
  1344. if winName == 'z-exag':
  1345. self.mapWindow.update.append('z-exag')
  1346. self.mapWindow.render = False
  1347. self.mapWindow.Refresh(False)
  1348. def OnViewChanged(self, event):
  1349. """View changed, render in full resolution"""
  1350. self.mapWindow.render = True
  1351. self.mapWindow.Refresh(False)
  1352. def OnViewChangedSpin(self, event):
  1353. """View changed, render in full resolution"""
  1354. # TODO: use step value instead
  1355. self.OnViewChange(event)
  1356. self.OnViewChanged(None)
  1357. def OnResetView(self, event):
  1358. """Reset to default view (view page)"""
  1359. self.mapWindow.ResetView()
  1360. self.UpdateSettings()
  1361. self.mapWindow.Refresh(False)
  1362. def OnLookAt(self, event):
  1363. """Look at (view page)"""
  1364. sel = event.GetSelection()
  1365. if sel == 0: # top
  1366. self.mapWindow.view['pos']['x'] = 0.5
  1367. self.mapWindow.view['pos']['y'] = 0.5
  1368. elif sel == 1: # north
  1369. self.mapWindow.view['pos']['x'] = 0.5
  1370. self.mapWindow.view['pos']['y'] = 0.0
  1371. elif sel == 2: # south
  1372. self.mapWindow.view['pos']['x'] = 0.5
  1373. self.mapWindow.view['pos']['y'] = 1.0
  1374. elif sel == 3: # east
  1375. self.mapWindow.view['pos']['x'] = 1.0
  1376. self.mapWindow.view['pos']['y'] = 0.5
  1377. elif sel == 4: # west
  1378. self.mapWindow.view['pos']['x'] = 0.0
  1379. self.mapWindow.view['pos']['y'] = 0.5
  1380. elif sel == 5: # north-west
  1381. self.mapWindow.view['pos']['x'] = 0.0
  1382. self.mapWindow.view['pos']['y'] = 0.0
  1383. elif sel == 6: # north-east
  1384. self.mapWindow.view['pos']['x'] = 1.0
  1385. self.mapWindow.view['pos']['y'] = 0.0
  1386. elif sel == 7: # south-east
  1387. self.mapWindow.view['pos']['x'] = 1.0
  1388. self.mapWindow.view['pos']['y'] = 1.0
  1389. elif sel == 8: # south-west
  1390. self.mapWindow.view['pos']['x'] = 0.0
  1391. self.mapWindow.view['pos']['y'] = 1.0
  1392. self.mapWindow.update.append('view')
  1393. self.UpdateSettings()
  1394. self.mapWindow.Refresh(False)
  1395. def OnDefault(self, event):
  1396. """Restore default settings"""
  1397. settings = copy.deepcopy(UserSettings.GetDefaultSettings()['nviz'])
  1398. UserSettings.Set(group='nviz',
  1399. value=settings)
  1400. for subgroup, key in settings.iteritems(): # view, surface, vector...
  1401. if subgroup != 'view':
  1402. continue
  1403. for subkey, value in key.iteritems():
  1404. for subvalue in value.keys():
  1405. win = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue])
  1406. val = settings[subgroup][subkey][subvalue]
  1407. if subkey == 'pos':
  1408. val = int(val * 100)
  1409. win.SetValue(val)
  1410. event.Skip()
  1411. def OnApply(self, event):
  1412. """Apply button pressed"""
  1413. if self.notebook.GetSelection() == self.page['settings']['id']:
  1414. self.ApplySettings()
  1415. if event:
  1416. event.Skip()
  1417. def ApplySettings(self):
  1418. """Apply Nviz settings for current session"""
  1419. settings = UserSettings.Get(group='nviz')
  1420. for subgroup, key in settings.iteritems(): # view, surface, vector...
  1421. if subgroup != 'view':
  1422. continue
  1423. for subkey, value in key.iteritems():
  1424. for subvalue in value.keys():
  1425. value = self.FindWindowById(self.win['settings'][subgroup][subkey][subvalue]).GetValue()
  1426. if subkey == 'pos':
  1427. value = float(value) / 100
  1428. settings[subgroup][subkey][subvalue] = value
  1429. def OnSave(self, event):
  1430. """OK button pressed
  1431. Apply changes, update map and save settings of selected layer
  1432. """
  1433. #
  1434. # apply changes
  1435. #
  1436. self.OnApply(None)
  1437. if self.notebook.GetSelection() == self.page['settings']['id']:
  1438. fileSettings = {}
  1439. UserSettings.ReadSettingsFile(settings=fileSettings)
  1440. fileSettings['nviz'] = UserSettings.Get(group='nviz')
  1441. file = UserSettings.SaveToFile(fileSettings)
  1442. self.lmgr.goutput.WriteLog(_('Nviz settings saved to file <%s>.') % file)
  1443. def OnBgColor(self, event):
  1444. """Background color changed"""
  1445. color = event.GetValue()
  1446. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1447. self.mapWindow.nvizClass.SetBgColor(str(color))
  1448. if self.parent.autoRender.IsChecked():
  1449. self.mapWindow.Refresh(False)
  1450. def OnClose(self, event):
  1451. """Close button pressed
  1452. Close dialog
  1453. """
  1454. self.Hide()
  1455. def OnSurfaceUse(self, event):
  1456. """Surface attribute -- use -- map/constant"""
  1457. if not self.mapWindow.init:
  1458. return
  1459. wx.Yield()
  1460. # find attribute row
  1461. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1462. if not attrb:
  1463. return
  1464. selection = event.GetSelection()
  1465. if self.win['surface'][attrb]['required']: # no 'unset'
  1466. selection += 1
  1467. if selection == 0: # unset
  1468. useMap = None
  1469. value = ''
  1470. elif selection == 1: # map
  1471. useMap = True
  1472. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1473. elif selection == 2: # constant
  1474. useMap = False
  1475. if attrb == 'color':
  1476. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1477. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1478. else:
  1479. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1480. self.SetSurfaceUseMap(attrb, useMap)
  1481. self.mapWindow.update.append('surface:attribute:%s' % attrb)
  1482. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1483. data['surface']['attribute'][attrb] = { 'map' : useMap,
  1484. 'value' : str(value),
  1485. }
  1486. self.mapWindow.UpdateLayerProperties()
  1487. if self.parent.autoRender.IsChecked():
  1488. self.mapWindow.Refresh(False)
  1489. def SetSurfaceUseMap(self, attrb, map=None):
  1490. if attrb in ('topo', 'color', 'shine'):
  1491. incSel = -1 # decrement selection (no 'unset')
  1492. else:
  1493. incSel = 0
  1494. if map is True: # map
  1495. if attrb != 'topo': # changing map topography not allowed
  1496. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(True) # FIXME
  1497. if self.win['surface'][attrb]['const']:
  1498. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1499. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(1 + incSel)
  1500. elif map is False: # const
  1501. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1502. if self.win['surface'][attrb]['const']:
  1503. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(True)
  1504. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(2 + incSel)
  1505. else: # unset
  1506. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1507. if self.win['surface'][attrb]['const']:
  1508. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1509. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(0)
  1510. def OnSurfaceMap(self, event):
  1511. """Set surface attribute"""
  1512. if not self.mapWindow.init:
  1513. return
  1514. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1515. if not attrb:
  1516. return
  1517. selection = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  1518. if self.win['surface'][attrb]['required']:
  1519. selection += 1
  1520. if selection == 0: # unset
  1521. map = None
  1522. value = ''
  1523. elif selection == 1: # map
  1524. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1525. map = True
  1526. else: # constant
  1527. if attrb == 'color':
  1528. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1529. # tuple to string
  1530. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1531. else:
  1532. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1533. map = False
  1534. if not self.pageChanging:
  1535. self.mapWindow.update.append('surface:attribute:%s' % attrb)
  1536. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1537. data['surface']['attribute'][attrb] = { 'map' : map,
  1538. 'value' : str(value),
  1539. }
  1540. self.mapWindow.UpdateLayerProperties()
  1541. if self.parent.autoRender.IsChecked():
  1542. self.mapWindow.Refresh(False)
  1543. def OnSurfaceResolution(self, event):
  1544. """Draw resolution changed"""
  1545. self.SetSurfaceResolution()
  1546. if apply and self.parent.autoRender.IsChecked():
  1547. self.mapWindow.Refresh(False)
  1548. def SetSurfaceResolution(self, all=False):
  1549. """Set draw resolution"""
  1550. coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
  1551. fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
  1552. self.mapWindow.update.append('surface:draw:resolution')
  1553. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1554. data['surface']['draw']['resolution'] = { 'coarse' : coarse,
  1555. 'fine' : fine,
  1556. 'all' : all }
  1557. self.mapWindow.UpdateLayerProperties()
  1558. def SetSurfaceMode(self, all=False):
  1559. """Set draw mode
  1560. @param apply allow auto-rendering
  1561. """
  1562. mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
  1563. if mode == 0: # coarse
  1564. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1565. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
  1566. elif mode == 1: # fine
  1567. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
  1568. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1569. else: # both
  1570. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1571. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1572. style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
  1573. shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
  1574. value, desc = self.mapWindow.GetSurfaceMode(mode, style, shade)
  1575. return value, desc
  1576. def OnSurfaceMode(self, event):
  1577. """Set draw mode"""
  1578. value, desc = self.SetSurfaceMode()
  1579. self.mapWindow.update.append('surface:draw:mode')
  1580. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1581. data['surface']['draw']['mode'] = { 'value' : value,
  1582. 'all' : False,
  1583. 'desc' : desc }
  1584. self.mapWindow.UpdateLayerProperties()
  1585. if apply and self.parent.autoRender.IsChecked():
  1586. self.mapWindow.Refresh(False)
  1587. def OnSurfaceModeAll(self, event):
  1588. """Set draw mode (including wire color) for all loaded surfaces"""
  1589. self.SetSurfaceMode(all=True)
  1590. self.SetSurfaceResolution(all=True)
  1591. color = self.FindWindowById(self.win['surface']['draw']['wire-color']).GetColour()
  1592. self.SetSurfaceWireColor(color, all=True)
  1593. if apply and self.parent.autoRender.IsChecked():
  1594. self.mapWindow.Refresh(False)
  1595. def SetSurfaceWireColor(self, color, all=False, apply=True):
  1596. """Set wire color"""
  1597. value = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1598. def OnSurfaceWireColor(self, event):
  1599. """Set wire color"""
  1600. self.SetSurfaceWireColor(event.GetValue())
  1601. self.mapWindow.update.append('surface:draw:wire-color')
  1602. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1603. data['surface']['draw']['wire-color'] = { 'value' : value,
  1604. 'all' : all }
  1605. self.mapWindow.UpdateLayerProperties()
  1606. if self.parent.autoRender.IsChecked():
  1607. self.mapWindow.Refresh(False)
  1608. def OnSurfaceAxis(self, event):
  1609. """Surface position, axis changed"""
  1610. mapLayer = self.mapWindow.GetSelectedLayer()
  1611. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1612. id = data['object']['id']
  1613. axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
  1614. win = self.FindWindowById(self.win['surface']['position']['pos'])
  1615. x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
  1616. if axis == 0: # x
  1617. win.SetRange(-1e4, 1e4)
  1618. win.SetValue(x)
  1619. elif axis == 1: # y
  1620. win.SetRange(-1e4, 1e4)
  1621. win.SetValue(y)
  1622. else: # z
  1623. win.SetRange(-1e3, 1e3)
  1624. win.SetValue(z)
  1625. def OnSurfacePosition(self, event):
  1626. """Surface position"""
  1627. axis = self.FindWindowById(self.win['surface']['position']['axis']).GetSelection()
  1628. value = event.GetInt()
  1629. mapLayer = self.mapWindow.GetSelectedLayer()
  1630. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1631. id = data['object']['id']
  1632. x, y, z = self.mapWindow.nvizClass.GetSurfacePosition(id)
  1633. if axis == 0: # x
  1634. x = value
  1635. elif axis == 1: # y
  1636. y = value
  1637. else: # z
  1638. z = value
  1639. self.mapWindow.update.append('surface:position')
  1640. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1641. data['surface']['position']['x'] = x
  1642. data['surface']['position']['y'] = y
  1643. data['surface']['position']['z'] = z
  1644. self.mapWindow.UpdateLayerProperties()
  1645. if self.parent.autoRender.IsChecked():
  1646. self.mapWindow.Refresh(False)
  1647. def OnVectorDisplay(self, event):
  1648. """Display vector lines on surface/flat"""
  1649. if event.GetSelection() == 0: # surface
  1650. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(True)
  1651. # set first found surface
  1652. ### TODO
  1653. else: # flat
  1654. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(False)
  1655. self.OnVectorLines(event)
  1656. event.Skip()
  1657. def OnVectorLines(self, event):
  1658. """Set vector lines mode, apply changes if auto-rendering is enabled"""
  1659. width = self.FindWindowById(self.win['vector']['lines']['width']).GetValue()
  1660. color = self.FindWindowById(self.win['vector']['lines']['color']).GetColour()
  1661. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1662. mode = {}
  1663. if self.FindWindowById(self.win['vector']['lines']['flat']).GetSelection() == 0:
  1664. mode['type'] = 'surface'
  1665. mode['map'] = '' # TODO
  1666. else:
  1667. mode['type'] = 'flat'
  1668. self.mapWindow.update.append('vector:lines:width')
  1669. self.mapWindow.update.append('vector:lines:color')
  1670. self.mapWindow.update.append('vector:lines:mode')
  1671. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1672. data['vector']['lines']['width'] = width
  1673. data['vector']['lines']['color'] = color
  1674. data['vector']['lines']['mode'] = mode
  1675. self.mapWindow.UpdateLayerProperties()
  1676. if self.parent.autoRender.IsChecked():
  1677. self.mapWindow.Refresh(False)
  1678. def OnVectorHeight(self, event):
  1679. value = event.GetInt()
  1680. if type(event) == type(wx.ScrollEvent()):
  1681. # slider
  1682. win = self.FindWindowById(self.win['vector']['lines']['height']['spin'])
  1683. else:
  1684. # spin
  1685. win = self.FindWindowById(self.win['vector']['lines']['height']['slider'])
  1686. win.SetValue(value)
  1687. self.mapWindow.update.append('vector:lines:height')
  1688. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1689. data['vector']['lines']['height'] = value
  1690. self.mapWindow.UpdateLayerProperties()
  1691. if self.parent.autoRender.IsChecked():
  1692. self.mapWindow.Refresh(False)
  1693. def UpdatePage(self, pageId):
  1694. """Update dialog (selected page)"""
  1695. self.pageChanging = True
  1696. layer = self.mapWindow.GetSelectedLayer()
  1697. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1698. if pageId == 'view':
  1699. max = self.mapWindow.view['z-exag']['value'] * 10
  1700. for control in ('spin', 'slider'):
  1701. self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(0,
  1702. max)
  1703. elif pageId == 'surface' and \
  1704. self.notebook.GetSelection() != self.page['surface']['id']:
  1705. if self.page['vector']['id'] > -1:
  1706. self.notebook.RemovePage(self.page['vector']['id'])
  1707. self.page['vector']['id'] = -1
  1708. self.page['surface']['id'] = 1
  1709. self.page['settings']['id'] = 2
  1710. panel = wx.FindWindowById(self.page['surface']['panel'])
  1711. self.notebook.InsertPage(n=self.page['surface']['id'],
  1712. page=panel,
  1713. text=" %s " % _("Surface"),
  1714. select=True)
  1715. self.UpdateSurfacePage(layer, data['surface'])
  1716. elif pageId == 'vector' and \
  1717. self.notebook.GetSelection() != self.page['vector']['id']:
  1718. if self.page['surface']['id'] > -1:
  1719. self.notebook.RemovePage(self.page['surface']['id'])
  1720. self.page['surface']['id'] = -1
  1721. self.page['vector']['id'] = 1
  1722. self.page['settings']['id'] = 2
  1723. panel = wx.FindWindowById(self.page['vector']['panel'])
  1724. self.notebook.InsertPage(n=self.page['vector']['id'],
  1725. page=panel,
  1726. text=" %s " % _("Vector"),
  1727. select=True)
  1728. self.UpdateVectorPage(layer, data['vector'])
  1729. self.pageChanging = False
  1730. def UpdateSurfacePage(self, layer, data):
  1731. #
  1732. # attributes
  1733. #
  1734. for attr in ('topo', 'color'): # required
  1735. if layer and layer.type == 'raster':
  1736. self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
  1737. else:
  1738. self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
  1739. self.SetSurfaceUseMap(attr, True) # -> map
  1740. if data['attribute'].has_key('color'):
  1741. value = data['attribute']['color']['value']
  1742. if data['attribute']['color']['map']:
  1743. self.FindWindowById(self.win['surface']['color']['map']).SetValue(value)
  1744. else: # constant
  1745. color = map(int, value.split(':'))
  1746. self.FindWindowById(self.win['surface']['color']['const']).SetColour(color)
  1747. self.SetSurfaceUseMap(attr, data['attribute']['color']['map'])
  1748. self.SetSurfaceUseMap('shine', data['attribute']['shine']['map'])
  1749. value = data['attribute']['shine']['value']
  1750. if data['attribute']['shine']['map']:
  1751. self.FindWindowById(self.win['surface']['shine']['map']).SetValue(value)
  1752. else:
  1753. self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
  1754. #
  1755. # draw
  1756. #
  1757. for control, dict in data['draw'].iteritems():
  1758. if control == 'resolution':
  1759. self.FindWindowById(self.win['surface']['draw']['res-coarse']).SetValue(dict['coarse'])
  1760. self.FindWindowById(self.win['surface']['draw']['res-fine']).SetValue(dict['fine'])
  1761. continue
  1762. if control == 'mode':
  1763. if dict['desc']['mode'] == 'coarse':
  1764. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(0)
  1765. elif dict['desc']['mode'] == 'fine':
  1766. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(1)
  1767. else: # both
  1768. self.FindWindowById(self.win['surface']['draw']['mode']).SetSelection(2)
  1769. if dict['desc']['style'] == 'wire':
  1770. self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(0)
  1771. else: # surface
  1772. self.FindWindowById(self.win['surface']['draw']['style']).SetSelection(1)
  1773. if dict['desc']['shading'] == 'flat':
  1774. self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(0)
  1775. else: # gouraud
  1776. self.FindWindowById(self.win['surface']['draw']['shading']).SetSelection(1)
  1777. continue
  1778. value = dict['value']
  1779. win = self.FindWindowById(self.win['surface']['draw'][control])
  1780. name = win.GetName()
  1781. if name == "selection":
  1782. win.SetSelection(value)
  1783. elif name == "colour":
  1784. color = map(int, value.split(':'))
  1785. win.SetColour(color)
  1786. else:
  1787. win.SetValue(value)
  1788. # enable/disable res widget + set draw mode
  1789. self.SetSurfaceMode()
  1790. color = self.FindWindowById(self.win['surface']['draw']['wire-color'])
  1791. self.SetSurfaceWireColor(color.GetColour())
  1792. def UpdateVectorPage(self, layer, data):
  1793. #
  1794. # lines
  1795. #
  1796. width = self.FindWindowById(self.win['vector']['lines']['width'])
  1797. width.SetValue(data['lines']['width'])
  1798. color = self.FindWindowById(self.win['vector']['lines']['color'])
  1799. color.SetValue(map(int, data['lines']['color'].split(':')))
  1800. display = self.FindWindowById(self.win['vector']['lines']['flat'])
  1801. if data['lines']['mode']['type'] == 'flat':
  1802. display.SetSelection(1)
  1803. else:
  1804. display.SetSelection(0)
  1805. for type in ('slider', 'spin'):
  1806. win = self.FindWindowById(self.win['vector']['lines']['height'][type])
  1807. win.SetValue(data['lines']['height'])
  1808. def SetPage(self, name):
  1809. """Get named page"""
  1810. self.notebook.SetSelection(self.page[name]['id'])
  1811. class ViewPositionWindow(wx.Window):
  1812. """Position control window (for NvizToolWindow)"""
  1813. def __init__(self, parent, id, mapwindow,
  1814. pos=wx.DefaultPosition,
  1815. size=wx.DefaultSize):
  1816. self.mapWindow = mapwindow
  1817. wx.Window.__init__(self, parent, id, pos, size)
  1818. self.SetBackgroundColour("WHITE")
  1819. self.pdc = wx.PseudoDC()
  1820. self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
  1821. self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
  1822. self.Draw()
  1823. self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
  1824. self.Bind(wx.EVT_PAINT, self.OnPaint)
  1825. # self.Bind(wx.EVT_MOTION, self.OnMouse)
  1826. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
  1827. def Draw(self, pos=None):
  1828. w, h = self.GetClientSize()
  1829. if pos is None:
  1830. x = self.mapWindow.view['pos']['x']
  1831. y = self.mapWindow.view['pos']['y']
  1832. x = x * w
  1833. y = y * h
  1834. else:
  1835. x, y = pos
  1836. self.pdc.Clear()
  1837. self.pdc.BeginDrawing()
  1838. self.pdc.DrawLine(w / 2, h / 2, x, y)
  1839. self.pdc.DrawCircle(x, y, 5)
  1840. self.pdc.EndDrawing()
  1841. def OnPaint(self, event):
  1842. dc = wx.BufferedPaintDC(self)
  1843. dc.SetBackground(wx.Brush("White"))
  1844. dc.Clear()
  1845. self.PrepareDC(dc)
  1846. self.pdc.DrawToDC(dc)
  1847. def OnMouse(self, event):
  1848. if event.LeftIsDown():
  1849. x, y = event.GetPosition()
  1850. self.Draw(pos=(x, y))
  1851. self.Refresh(False)
  1852. w, h = self.GetClientSize()
  1853. x = float(x) / w
  1854. y = float(y) / h
  1855. if x >= 0 and x <= 1.0:
  1856. self.mapWindow.view['pos']['x'] = x
  1857. if y >= 0 and y <= 1.0:
  1858. self.mapWindow.view['pos']['y'] = y
  1859. self.mapWindow.update.append('view')
  1860. self.mapWindow.render = False
  1861. self.mapWindow.Refresh(eraseBackground=False)
  1862. elif event.LeftUp():
  1863. self.mapWindow.render = True
  1864. self.mapWindow.Refresh(eraseBackground=False)
  1865. event.Skip()