workspace.py 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638
  1. """!
  2. @package workspace.py
  3. @brief Open/save workspace definition file
  4. Classes:
  5. - ProcessWorkspaceFile
  6. - Nviz
  7. - WriteWorkspaceFile
  8. - ProcessGrcFile
  9. (C) 2007-2011 by the GRASS Development Team
  10. This program is free software under the GNU General Public
  11. License (>=v2). Read the file COPYING that comes with GRASS
  12. for details.
  13. @author Martin Landa <landa.martin gmail.com>
  14. @author Anna Kratochvilova <kratochanna gmail.com> (wxNviz / Google SoC 2011)
  15. """
  16. import os
  17. import sys
  18. import copy
  19. import types
  20. import wx
  21. ### for gxw (workspace file) parsering
  22. # xmlproc not available on Mac OS
  23. # from xml.parsers.xmlproc import xmlproc
  24. # from xml.parsers.xmlproc import xmlval
  25. # from xml.parsers.xmlproc import xmldtd
  26. try:
  27. import xml.etree.ElementTree as etree
  28. except ImportError:
  29. import elementtree.ElementTree as etree # Python <= 2.4
  30. import utils
  31. import globalvar
  32. from preferences import globalSettings as UserSettings
  33. try:
  34. import wxnviz
  35. except ImportError:
  36. wxnviz = None
  37. class ProcessWorkspaceFile:
  38. def __init__(self, tree):
  39. """!A ElementTree handler for the GXW XML file, as defined in
  40. grass-gxw.dtd.
  41. """
  42. self.tree = tree
  43. self.root = self.tree.getroot()
  44. #
  45. # layer manager properties
  46. #
  47. self.layerManager = {}
  48. self.layerManager['pos'] = None # window position
  49. self.layerManager['size'] = None # window size
  50. #
  51. # list of mapdisplays
  52. #
  53. self.displays = []
  54. #
  55. # list of map layers
  56. #
  57. self.layers = []
  58. #
  59. # nviz state
  60. #
  61. self.nviz_state = {}
  62. self.displayIndex = -1 # first display has index '0'
  63. self.__processFile()
  64. self.nvizDefault = Nviz()
  65. def __filterValue(self, value):
  66. """!Filter value
  67. @param value
  68. """
  69. value = value.replace('&lt;', '<')
  70. value = value.replace('&gt;', '>')
  71. return value
  72. def __getNodeText(self, node, tag, default = ''):
  73. """!Get node text"""
  74. p = node.find(tag)
  75. if p is not None:
  76. return utils.normalize_whitespace(p.text)
  77. return default
  78. def __processFile(self):
  79. """!Process workspace file"""
  80. #
  81. # layer manager
  82. #
  83. node_lm = self.root.find('layer_manager')
  84. if node_lm is not None:
  85. posAttr = node_lm.get('dim', '')
  86. if posAttr:
  87. posVal = map(int, posAttr.split(','))
  88. try:
  89. self.layerManager['pos'] = (posVal[0], posVal[1])
  90. self.layerManager['size'] = (posVal[2], posVal[3])
  91. except:
  92. pass
  93. #
  94. # displays
  95. #
  96. for display in self.root.findall('display'):
  97. self.displayIndex += 1
  98. # window position and size
  99. posAttr = display.get('dim', '')
  100. if posAttr:
  101. posVal = map(int, posAttr.split(','))
  102. try:
  103. pos = (posVal[0], posVal[1])
  104. size = (posVal[2], posVal[3])
  105. except:
  106. pos = None
  107. size = None
  108. else:
  109. pos = None
  110. size = None
  111. extentAttr = display.get('extent', '')
  112. if extentAttr:
  113. # w, s, e, n
  114. extent = map(float, extentAttr.split(','))
  115. else:
  116. extent = None
  117. # projection
  118. node_projection = display.find('projection')
  119. if node_projection is not None:
  120. projection = { 'enabled' : True,
  121. 'epsg' : node_projection.get('epsg', ''),
  122. 'proj' : self.__getNodeText(node_projection, 'value') }
  123. else:
  124. projection = { 'enabled' : False }
  125. self.displays.append( {
  126. "render" : bool(int(display.get('render', "0"))),
  127. "mode" : int(display.get('mode', 0)),
  128. "showCompExtent" : bool(int(display.get('showCompExtent', "0"))),
  129. "pos" : pos,
  130. "size" : size,
  131. "extent" : extent,
  132. "alignExtent" : bool(int(display.get('alignExtent', "0"))),
  133. "constrainRes" : bool(int(display.get('constrainRes', "0"))),
  134. "projection" : projection,
  135. "viewMode" : display.get('viewMode', '2d')} )
  136. # process all layers/groups in the display
  137. self.__processLayers(display)
  138. # process nviz_state
  139. self.__processNvizState(display)
  140. def __processLayers(self, node, inGroup = -1):
  141. """!Process layers/groups of selected display
  142. @param node display tree node
  143. @param inGroup in group -> index of group item otherwise -1
  144. """
  145. for item in node.getchildren():
  146. if item.tag == 'group':
  147. # -> group
  148. self.layers.append( {
  149. "type" : 'group',
  150. "name" : item.get('name', ''),
  151. "checked" : bool(int(item.get('checked', "0"))),
  152. "opacity" : None,
  153. "cmd" : None,
  154. "group" : inGroup,
  155. "display" : self.displayIndex,
  156. "vdigit" : None,
  157. "nviz" : None})
  158. self.__processLayers(item, inGroup = len(self.layers) - 1) # process items in group
  159. elif item.tag == 'layer':
  160. cmd, selected, vdigit, nviz = self.__processLayer(item)
  161. self.layers.append( {
  162. "type" : item.get('type', None),
  163. "name" : item.get('name', None),
  164. "checked" : bool(int(item.get('checked', "0"))),
  165. "opacity" : float(item.get('opacity', '1.0')),
  166. "cmd" : cmd,
  167. "group" : inGroup,
  168. "display" : self.displayIndex,
  169. "selected" : selected,
  170. "vdigit" : vdigit,
  171. "nviz" : nviz } )
  172. def __processLayer(self, layer):
  173. """!Process layer item
  174. @param layer tree node
  175. """
  176. cmd = list()
  177. #
  178. # layer attributes (task) - 2D settings
  179. #
  180. node_task = layer.find('task')
  181. cmd.append(node_task.get('name', "unknown"))
  182. # flags
  183. for p in node_task.findall('flag'):
  184. flag = p.get('name', '')
  185. if len(flag) > 1:
  186. cmd.append('--' + flag)
  187. else:
  188. cmd.append('-' + flag)
  189. # parameters
  190. for p in node_task.findall('parameter'):
  191. cmd.append('%s=%s' % (p.get('name', ''),
  192. self.__filterValue(self.__getNodeText(p, 'value'))))
  193. if layer.find('selected') is not None:
  194. selected = True
  195. else:
  196. selected = False
  197. #
  198. # Vector digitizer settings
  199. #
  200. node_vdigit = layer.find('vdigit')
  201. if node_vdigit is not None:
  202. vdigit = self.__processLayerVdigit(node_vdigit)
  203. else:
  204. vdigit = None
  205. #
  206. # Nviz (3D settings)
  207. #
  208. node_nviz = layer.find('nviz')
  209. if node_nviz is not None:
  210. nviz = self.__processLayerNviz(node_nviz)
  211. else:
  212. nviz = None
  213. return (cmd, selected, vdigit, nviz)
  214. def __processLayerVdigit(self, node_vdigit):
  215. """!Process vector digitizer layer settings
  216. @param node_vdigit vdigit node
  217. """
  218. # init nviz layer properties
  219. vdigit = dict()
  220. for node in node_vdigit.findall('geometryAttribute'):
  221. if 'geomAttr' not in vdigit:
  222. vdigit['geomAttr'] = dict()
  223. type = node.get('type')
  224. vdigit['geomAttr'][type] = dict()
  225. vdigit['geomAttr'][type]['column'] = node.get('column') # required
  226. # default map units
  227. vdigit['geomAttr'][type]['units'] = node.get('units', 'mu')
  228. return vdigit
  229. def __processLayerNviz(self, node_nviz):
  230. """!Process 3D layer settings
  231. @param node_nviz nviz node
  232. """
  233. # init nviz layer properties
  234. nviz = {}
  235. if node_nviz.find('surface') is not None: # -> raster
  236. nviz['surface'] = {}
  237. for sec in ('attribute', 'draw', 'mask', 'position'):
  238. nviz['surface'][sec] = {}
  239. elif node_nviz.find('vlines') is not None or \
  240. node_nviz.find('vpoints') is not None: # -> vector
  241. nviz['vector'] = {}
  242. for sec in ('lines', 'points'):
  243. nviz['vector'][sec] = {}
  244. if 'surface' in nviz:
  245. node_surface = node_nviz.find('surface')
  246. # attributes
  247. for attrb in node_surface.findall('attribute'):
  248. tagName = str(attrb.tag)
  249. attrbName = attrb.get('name', '')
  250. dc = nviz['surface'][tagName][attrbName] = {}
  251. if attrb.get('map', '0') == '0':
  252. dc['map'] = False
  253. else:
  254. dc['map'] = True
  255. value = self.__getNodeText(attrb, 'value')
  256. try:
  257. dc['value'] = int(value)
  258. except ValueError:
  259. try:
  260. dc['value'] = float(value)
  261. except ValueError:
  262. dc['value'] = str(value)
  263. # draw
  264. node_draw = node_surface.find('draw')
  265. if node_draw is not None:
  266. tagName = str(node_draw.tag)
  267. nviz['surface'][tagName]['all'] = False
  268. nviz['surface'][tagName]['mode'] = {}
  269. nviz['surface'][tagName]['mode']['value'] = -1 # to be calculated
  270. nviz['surface'][tagName]['mode']['desc'] = {}
  271. nviz['surface'][tagName]['mode']['desc']['shading'] = \
  272. str(node_draw.get('shading', ''))
  273. nviz['surface'][tagName]['mode']['desc']['style'] = \
  274. str(node_draw.get('style', ''))
  275. nviz['surface'][tagName]['mode']['desc']['mode'] = \
  276. str(node_draw.get('mode', ''))
  277. # resolution
  278. for node_res in node_draw.findall('resolution'):
  279. resType = str(node_res.get('type', ''))
  280. if 'resolution' not in nviz['surface']['draw']:
  281. nviz['surface']['draw']['resolution'] = {}
  282. value = int(self.__getNodeText(node_res, 'value'))
  283. nviz['surface']['draw']['resolution'][resType] = value
  284. # wire-color
  285. node_wire_color = node_draw.find('wire_color')
  286. if node_wire_color is not None:
  287. nviz['surface']['draw']['wire-color'] = {}
  288. value = str(self.__getNodeText(node_wire_color, 'value'))
  289. nviz['surface']['draw']['wire-color']['value'] = value
  290. # position
  291. node_pos = node_surface.find('position')
  292. if node_pos is not None:
  293. dc = nviz['surface']['position'] = {}
  294. for coor in ['x', 'y', 'z']:
  295. node = node_pos.find(coor)
  296. if node is None:
  297. continue
  298. value = int(self.__getNodeText(node_pos, coor))
  299. dc[coor] = value
  300. elif 'vector' in nviz:
  301. # vpoints
  302. node_vpoints = node_nviz.find('vpoints')
  303. if node_vpoints is not None:
  304. marker = str(node_vpoints.get('marker', ''))
  305. markerId = list(UserSettings.Get(group='nviz', key='vector',
  306. subkey=['points', 'marker'], internal=True)).index(marker)
  307. nviz['vector']['points']['marker'] = { 'value' : markerId }
  308. node_mode = node_vpoints.find('mode')
  309. if node_mode is not None:
  310. nviz['vector']['points']['mode'] = {}
  311. nviz['vector']['points']['mode']['type'] = str(node_mode.get('type', 'surface'))
  312. nviz['vector']['points']['mode']['surface'] = {}
  313. nviz['vector']['points']['mode']['surface']['value'] = []
  314. nviz['vector']['points']['mode']['surface']['show'] = []
  315. # map
  316. for node_map in node_mode.findall('map'):
  317. nviz['vector']['points']['mode']['surface']['value'].append(
  318. self.__processLayerNvizNode(node_map, 'name', str))
  319. nviz['vector']['points']['mode']['surface']['show'].append(bool(
  320. self.__processLayerNvizNode(node_map, 'checked', int)))
  321. # color
  322. self.__processLayerNvizNode(node_vpoints, 'color', str,
  323. nviz['vector']['points'])
  324. # width
  325. self.__processLayerNvizNode(node_vpoints, 'width', int,
  326. nviz['vector']['points'])
  327. # height
  328. self.__processLayerNvizNode(node_vpoints, 'height', int,
  329. nviz['vector']['points'])
  330. # height
  331. self.__processLayerNvizNode(node_vpoints, 'size', int,
  332. nviz['vector']['points'])
  333. # thematic
  334. node_thematic = node_vpoints.find('thematic')
  335. thematic = nviz['vector']['points']['thematic'] = {}
  336. thematic['rgbcolumn'] = self.__processLayerNvizNode(node_thematic, 'rgbcolumn', str)
  337. thematic['sizecolumn'] = self.__processLayerNvizNode(node_thematic, 'sizecolumn', str)
  338. for col in ('rgbcolumn', 'sizecolumn'):
  339. if thematic[col] == 'None':
  340. thematic[col] = None
  341. thematic['layer'] = self.__processLayerNvizNode(node_thematic, 'layer', int)
  342. for use in ('usecolor', 'usesize', 'usewidth'):
  343. if node_thematic.get(use, ''):
  344. thematic[use] = int(node_thematic.get(use, '0'))
  345. # vlines
  346. node_vlines = node_nviz.find('vlines')
  347. if node_vlines is not None:
  348. node_mode = node_vlines.find('mode')
  349. if node_mode is not None:
  350. nviz['vector']['lines']['mode'] = {}
  351. nviz['vector']['lines']['mode']['type'] = str(node_mode.get('type', ''))
  352. nviz['vector']['lines']['mode']['surface'] = {}
  353. nviz['vector']['lines']['mode']['surface']['value'] = []
  354. nviz['vector']['lines']['mode']['surface']['show'] = []
  355. # map
  356. for node_map in node_mode.findall('map'):
  357. nviz['vector']['lines']['mode']['surface']['value'].append(
  358. self.__processLayerNvizNode(node_map, 'name', str))
  359. nviz['vector']['lines']['mode']['surface']['show'].append(bool(
  360. self.__processLayerNvizNode(node_map, 'checked', int)))
  361. # color
  362. self.__processLayerNvizNode(node_vlines, 'color', str,
  363. nviz['vector']['lines'])
  364. # width
  365. self.__processLayerNvizNode(node_vlines, 'width', int,
  366. nviz['vector']['lines'])
  367. # height
  368. self.__processLayerNvizNode(node_vlines, 'height', int,
  369. nviz['vector']['lines'])
  370. # thematic
  371. node_thematic = node_vlines.find('thematic')
  372. thematic = nviz['vector']['lines']['thematic'] = {}
  373. thematic['rgbcolumn'] = self.__processLayerNvizNode(node_thematic, 'rgbcolumn', str)
  374. thematic['sizecolumn'] = self.__processLayerNvizNode(node_thematic, 'sizecolumn', str)
  375. for col in ('rgbcolumn', 'sizecolumn'):
  376. if thematic[col] == 'None':
  377. thematic[col] = None
  378. thematic['layer'] = self.__processLayerNvizNode(node_thematic, 'layer', int)
  379. for use in ('usecolor', 'usesize', 'usewidth'):
  380. if node_thematic.get(use, ''):
  381. thematic[use] = int(node_thematic.get(use, '0'))
  382. return nviz
  383. def __processLayerNvizNode(self, node, tag, cast, dc = None):
  384. """!Process given tag nviz/vector"""
  385. node_tag = node.find(tag)
  386. if node_tag is not None:
  387. if node_tag.find('value') is not None:
  388. value = cast(self.__getNodeText(node_tag, 'value'))
  389. else:
  390. try:
  391. value = cast(node_tag.text)
  392. except ValueError:
  393. if cast == str:
  394. value = ''
  395. else:
  396. value = None
  397. if dc:
  398. dc[tag] = dict()
  399. dc[tag]['value'] = value
  400. else:
  401. return value
  402. def __processNvizState(self, node):
  403. """!Process tag nviz_state"""
  404. node_state = node.find('nviz_state')
  405. if node_state is None:
  406. return
  407. self.nviz_state['display'] = self.displayIndex
  408. #
  409. # view
  410. #
  411. node_view = node_state.find('view')
  412. view = {}
  413. iview = {}
  414. node_position = node_view.find('v_position')
  415. view['position'] = {}
  416. view['position']['x'] = self.__processLayerNvizNode(node_position, 'x', float)
  417. view['position']['y'] = self.__processLayerNvizNode(node_position, 'y', float)
  418. node_persp = node_view.find('persp')
  419. view['persp'] = {}
  420. iview['persp'] = {}
  421. view['persp']['value'] = self.__processLayerNvizNode(node_persp, 'value', int)
  422. view['persp']['step'] = self.__processLayerNvizNode(node_persp, 'step', int)
  423. iview['persp']['min'] = self.__processLayerNvizNode(node_persp, 'min', int)
  424. iview['persp']['max'] = self.__processLayerNvizNode(node_persp, 'max', int)
  425. node_height = node_view.find('v_height')
  426. iview['height'] = {}
  427. iview['height']['value'] = self.__processLayerNvizNode(node_height, 'value', int)
  428. iview['height']['min'] = self.__processLayerNvizNode(node_height, 'min', int)
  429. iview['height']['max'] = self.__processLayerNvizNode(node_height, 'max', int)
  430. node_twist = node_view.find('twist')
  431. view['twist'] = {}
  432. iview['twist'] = {}
  433. view['twist']['value'] = self.__processLayerNvizNode(node_twist, 'value', int)
  434. iview['twist']['min'] = self.__processLayerNvizNode(node_twist, 'min', int)
  435. iview['twist']['max'] = self.__processLayerNvizNode(node_twist, 'max', int)
  436. node_zexag = node_view.find('z-exag')
  437. view['z-exag'] = {}
  438. iview['z-exag'] = {}
  439. view['z-exag']['value'] = self.__processLayerNvizNode(node_zexag, 'value', int)
  440. view['z-exag']['min'] = self.__processLayerNvizNode(node_zexag, 'min', int)
  441. view['z-exag']['max'] = self.__processLayerNvizNode(node_zexag, 'max', int)
  442. iview['z-exag']['original'] = self.__processLayerNvizNode(node_zexag, 'original', float)
  443. node_focus = node_view.find('focus')
  444. iview['focus'] = {}
  445. iview['focus']['x'] = self.__processLayerNvizNode(node_focus, 'x', int)
  446. iview['focus']['y'] = self.__processLayerNvizNode(node_focus, 'y', int)
  447. iview['focus']['z'] = self.__processLayerNvizNode(node_focus, 'z', int)
  448. node_dir = node_view.find('dir')
  449. if node_dir:
  450. iview['dir'] = {}
  451. iview['dir']['x'] = self.__processLayerNvizNode(node_dir, 'x', int)
  452. iview['dir']['y'] = self.__processLayerNvizNode(node_dir, 'y', int)
  453. iview['dir']['z'] = self.__processLayerNvizNode(node_dir, 'z', int)
  454. iview['dir']['use'] = True
  455. else:
  456. iview['dir'] = {}
  457. iview['dir']['x'] = -1
  458. iview['dir']['y'] = -1
  459. iview['dir']['z'] = -1
  460. iview['dir']['use'] = False
  461. view['background'] = {}
  462. color = self.__processLayerNvizNode(node_view, 'background_color', str)
  463. view['background']['color'] = tuple(map(int, color.split(':')))
  464. self.nviz_state['view'] = view
  465. self.nviz_state['iview'] = iview
  466. #
  467. # light
  468. #
  469. node_light = node_state.find('light')
  470. light = {}
  471. node_position = node_light.find('l_position')
  472. light['position'] = {}
  473. light['position']['x'] = self.__processLayerNvizNode(node_position, 'x', float)
  474. light['position']['y'] = self.__processLayerNvizNode(node_position, 'y', float)
  475. light['position']['z'] = self.__processLayerNvizNode(node_position, 'z', int)
  476. light['bright'] = self.__processLayerNvizNode(node_light, 'bright', int)
  477. light['ambient'] = self.__processLayerNvizNode(node_light, 'ambient', int)
  478. color = self.__processLayerNvizNode(node_light, 'color', str)
  479. light['color'] = tuple(map(int, color.split(':')))
  480. self.nviz_state['light'] = light
  481. node_constants = node_state.find('constant_planes')
  482. constants = []
  483. if node_constants:
  484. for i, node_plane in enumerate(node_constants.findall('plane')):
  485. plane = {}
  486. plane['color'] = self.__processLayerNvizNode(node_plane, 'color', str)
  487. plane['resolution'] = self.__processLayerNvizNode(node_plane, 'fine_resolution', int)
  488. plane['value'] = self.__processLayerNvizNode(node_plane, 'height', int)
  489. plane['object'] = {}
  490. constants.append({'constant': plane})
  491. self.nviz_state['constants'] = constants
  492. class Nviz:
  493. def __init__(self):
  494. """Default 3D settings"""
  495. UserSettings.Reset('nviz')
  496. UserSettings.ReadSettingsFile()
  497. def SetConstantDefaultProp(self):
  498. """Set default constant data properties"""
  499. data = dict()
  500. for key, value in UserSettings.Get(group='nviz', key='constant').iteritems():
  501. data[key] = value
  502. color = str(data['color'][0]) + ':' + str(data['color'][1]) + ':' + str(data['color'][2])
  503. data['color'] = color
  504. return data
  505. def SetSurfaceDefaultProp(self, data = None):
  506. """Set default surface data properties"""
  507. if not data:
  508. data = dict()
  509. for sec in ('attribute', 'draw', 'mask', 'position'):
  510. data[sec] = {}
  511. #
  512. # attributes
  513. #
  514. for attrb in ('shine', ):
  515. data['attribute'][attrb] = {}
  516. for key, value in UserSettings.Get(group='nviz', key='surface',
  517. subkey=attrb).iteritems():
  518. data['attribute'][attrb][key] = value
  519. data['attribute'][attrb]['update'] = None
  520. #
  521. # draw
  522. #
  523. data['draw']['all'] = False # apply only for current surface
  524. for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
  525. if control[:3] == 'res':
  526. if 'resolution' not in data['draw']:
  527. data['draw']['resolution'] = {}
  528. if 'update' not in data['draw']['resolution']:
  529. data['draw']['resolution']['update'] = None
  530. data['draw']['resolution'][control[4:]] = value
  531. continue
  532. if control == 'wire-color':
  533. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  534. elif control in ('mode', 'style', 'shading'):
  535. if 'mode' not in data['draw']:
  536. data['draw']['mode'] = {}
  537. continue
  538. data['draw'][control] = { 'value' : value }
  539. data['draw'][control]['update'] = None
  540. value, desc = self.GetDrawMode(UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'mode']),
  541. UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'style']),
  542. UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading']))
  543. data['draw']['mode'] = { 'value' : value,
  544. 'desc' : desc,
  545. 'update': None }
  546. # position
  547. for coord in ('x', 'y', 'z'):
  548. data['position'][coord] = UserSettings.Get(group='nviz', key='surface', subkey=['position', coord])
  549. data['position']['update'] = None
  550. return data
  551. def SetVolumeDefaultProp(self):
  552. """Set default volume data properties"""
  553. data = dict()
  554. for sec in ('attribute', 'draw', 'position'):
  555. data[sec] = dict()
  556. for sec in ('isosurface', 'slice'):
  557. data[sec] = list()
  558. #
  559. # draw
  560. #
  561. for control, value in UserSettings.Get(group='nviz', key='volume', subkey='draw').iteritems():
  562. if control == 'shading':
  563. sel = UserSettings.Get(group='nviz', key='volume', subkey=['draw', 'shading'])
  564. value, desc = self.GetDrawMode(shade=sel, string=False)
  565. data['draw']['shading'] = {}
  566. data['draw']['shading']['isosurface'] = { 'value' : value,
  567. 'desc' : desc['shading'] }
  568. data['draw']['shading']['slice'] = { 'value' : value,
  569. 'desc' : desc['shading'] }
  570. elif control == 'mode':
  571. sel = UserSettings.Get(group='nviz', key='volume', subkey=['draw', 'mode'])
  572. if sel == 0:
  573. desc = 'isosurface'
  574. else:
  575. desc = 'slice'
  576. data['draw']['mode'] = { 'value' : sel,
  577. 'desc' : desc, }
  578. else:
  579. data['draw'][control] = {}
  580. data['draw'][control]['isosurface'] = { 'value' : value }
  581. data['draw'][control]['slice'] = { 'value' : value }
  582. if 'update' not in data['draw'][control]:
  583. data['draw'][control]['update'] = None
  584. #
  585. # isosurface attributes
  586. #
  587. for attrb in ('shine', ):
  588. data['attribute'][attrb] = {}
  589. for key, value in UserSettings.Get(group='nviz', key='volume',
  590. subkey=attrb).iteritems():
  591. data['attribute'][attrb][key] = value
  592. return data
  593. def SetIsosurfaceDefaultProp(self):
  594. """!Set default isosurface properties"""
  595. data = dict()
  596. for attr in ('shine', 'topo', 'transp', 'color'):
  597. data[attr] = {}
  598. for key, value in UserSettings.Get(group = 'nviz', key = 'volume',
  599. subkey = attr).iteritems():
  600. data[attr][key] = value
  601. data[attr]['update'] = None
  602. return data
  603. def SetSliceDefaultProp(self):
  604. """!Set default slice properties"""
  605. data = dict()
  606. data['position'] = copy.deepcopy(UserSettings.Get(group = 'nviz', key = 'volume',
  607. subkey = 'slice_position'))
  608. data['position']['update'] = None
  609. data['transp'] = copy.deepcopy(UserSettings.Get(group = 'nviz', key = 'volume',
  610. subkey = 'transp'))
  611. return data
  612. def SetVectorDefaultProp(self, data = None):
  613. """Set default vector data properties"""
  614. if not data:
  615. data = dict()
  616. for sec in ('lines', 'points'):
  617. data[sec] = {}
  618. self.SetVectorLinesDefaultProp(data['lines'])
  619. self.SetVectorPointsDefaultProp(data['points'])
  620. return data
  621. def SetVectorLinesDefaultProp(self, data):
  622. """Set default vector properties -- lines"""
  623. # width
  624. data['width'] = {'value' : UserSettings.Get(group='nviz', key='vector',
  625. subkey=['lines', 'width']) }
  626. # color
  627. value = UserSettings.Get(group='nviz', key='vector',
  628. subkey=['lines', 'color'])
  629. color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  630. data['color'] = { 'value' : color }
  631. # mode
  632. if UserSettings.Get(group='nviz', key='vector',
  633. subkey=['lines', 'flat']):
  634. type = 'flat'
  635. else:
  636. type = 'surface'
  637. data['mode'] = {}
  638. data['mode']['type'] = type
  639. data['mode']['update'] = None
  640. # height
  641. data['height'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  642. subkey=['lines', 'height']) }
  643. # thematic
  644. data['thematic'] = {'rgbcolumn' : UserSettings.Get(group='nviz', key='vector',
  645. subkey=['lines', 'rgbcolumn']),
  646. 'sizecolumn' : UserSettings.Get(group='nviz', key='vector',
  647. subkey=['lines', 'sizecolumn']),
  648. 'layer': 1,
  649. 'usecolor' : False,
  650. 'usewidth' : False}
  651. if 'object' in data:
  652. for attrb in ('color', 'width', 'mode', 'height', 'thematic'):
  653. data[attrb]['update'] = None
  654. def SetVectorPointsDefaultProp(self, data):
  655. """Set default vector properties -- points"""
  656. # size
  657. data['size'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  658. subkey=['points', 'size']) }
  659. # width
  660. data['width'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  661. subkey=['points', 'width']) }
  662. # marker
  663. data['marker'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  664. subkey=['points', 'marker']) }
  665. # color
  666. value = UserSettings.Get(group='nviz', key='vector',
  667. subkey=['points', 'color'])
  668. color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  669. data['color'] = { 'value' : color }
  670. # mode
  671. data['mode'] = { 'type' : 'surface'}
  672. ## 'surface' : '', }
  673. # height
  674. data['height'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  675. subkey=['points', 'height']) }
  676. data['thematic'] = {'rgbcolumn' : UserSettings.Get(group='nviz', key='vector',
  677. subkey=['points', 'rgbcolumn']),
  678. 'sizecolumn' : UserSettings.Get(group='nviz', key='vector',
  679. subkey=['points', 'sizecolumn']),
  680. 'layer': 1,
  681. 'usecolor' : False,
  682. 'usesize' : False}
  683. if 'object' in data:
  684. for attrb in ('size', 'width', 'marker',
  685. 'color', 'height', 'thematic'):
  686. data[attrb]['update'] = None
  687. def GetDrawMode(self, mode=None, style=None, shade=None, string=False):
  688. """Get surface draw mode (value) from description/selection
  689. @param mode,style,shade modes
  690. @param string if True input parameters are strings otherwise
  691. selections
  692. """
  693. if not wxnviz:
  694. return None
  695. value = 0
  696. desc = {}
  697. if string:
  698. if mode is not None:
  699. if mode == 'coarse':
  700. value |= wxnviz.DM_WIRE
  701. elif mode == 'fine':
  702. value |= wxnviz.DM_POLY
  703. else: # both
  704. value |= wxnviz.DM_WIRE_POLY
  705. if style is not None:
  706. if style == 'wire':
  707. value |= wxnviz.DM_GRID_WIRE
  708. else: # surface
  709. value |= wxnviz.DM_GRID_SURF
  710. if shade is not None:
  711. if shade == 'flat':
  712. value |= wxnviz.DM_FLAT
  713. else: # surface
  714. value |= wxnviz.DM_GOURAUD
  715. return value
  716. # -> string is False
  717. if mode is not None:
  718. if mode == 0: # coarse
  719. value |= wxnviz.DM_WIRE
  720. desc['mode'] = 'coarse'
  721. elif mode == 1: # fine
  722. value |= wxnviz.DM_POLY
  723. desc['mode'] = 'fine'
  724. else: # both
  725. value |= wxnviz.DM_WIRE_POLY
  726. desc['mode'] = 'both'
  727. if style is not None:
  728. if style == 0: # wire
  729. value |= wxnviz.DM_GRID_WIRE
  730. desc['style'] = 'wire'
  731. else: # surface
  732. value |= wxnviz.DM_GRID_SURF
  733. desc['style'] = 'surface'
  734. if shade is not None:
  735. if shade == 0:
  736. value |= wxnviz.DM_FLAT
  737. desc['shading'] = 'flat'
  738. else: # surface
  739. value |= wxnviz.DM_GOURAUD
  740. desc['shading'] = 'gouraud'
  741. return (value, desc)
  742. def SetDecorDefaultProp(self, type):
  743. """!Set default arrow properties
  744. """
  745. data = {}
  746. # arrow
  747. if type == 'arrow':
  748. data['arrow'] = UserSettings.Get(group = 'nviz', key = 'arrow')
  749. data['arrow']['color'] = "%d:%d:%d" % (
  750. UserSettings.Get(group = 'nviz', key = 'arrow', subkey = 'color')[:3])
  751. data['arrow'].update(UserSettings.Get(group = 'nviz', key = 'arrow', internal = True))
  752. data['arrow']['show'] = False
  753. # arrow
  754. if type == 'scalebar':
  755. data['scalebar'] = copy.deepcopy(UserSettings.Get(group = 'nviz', key = 'scalebar'))
  756. data['scalebar']['color'] = "%d:%d:%d" % (
  757. UserSettings.Get(group = 'nviz', key = 'scalebar', subkey = 'color')[:3])
  758. data['scalebar'].update(copy.deepcopy(UserSettings.Get(group = 'nviz', key = 'scalebar', internal = True)))
  759. data['scalebar']['id'] = 0
  760. return data
  761. class WriteWorkspaceFile(object):
  762. """!Generic class for writing workspace file"""
  763. def __init__(self, lmgr, file):
  764. self.file = file
  765. self.lmgr = lmgr
  766. self.indent = 0
  767. # write header
  768. self.file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
  769. self.file.write('<!DOCTYPE gxw SYSTEM "grass-gxw.dtd">\n')
  770. self.file.write('%s<gxw>\n' % (' ' * self.indent))
  771. self.indent =+ 4
  772. # layer manager
  773. windowPos = self.lmgr.GetPosition()
  774. windowSize = self.lmgr.GetSize()
  775. file.write('%s<layer_manager dim="%d,%d,%d,%d">\n' % (' ' * self.indent,
  776. windowPos[0],
  777. windowPos[1],
  778. windowSize[0],
  779. windowSize[1]
  780. ))
  781. file.write('%s</layer_manager>\n' % (' ' * self.indent))
  782. # list of displays
  783. for page in range(0, self.lmgr.gm_cb.GetPageCount()):
  784. mapTree = self.lmgr.gm_cb.GetPage(page).maptree
  785. region = mapTree.Map.region
  786. displayPos = mapTree.mapdisplay.GetPosition()
  787. displaySize = mapTree.mapdisplay.GetSize()
  788. if mapTree.mapdisplay.toolbars['map'].combo.GetSelection() == 1:
  789. viewmode = '3d'
  790. else:
  791. viewmode = '2d'
  792. file.write('%s<display render="%d" '
  793. 'mode="%d" showCompExtent="%d" '
  794. 'alignExtent="%d" '
  795. 'constrainRes="%d" '
  796. 'dim="%d,%d,%d,%d" '
  797. 'extent="%f,%f,%f,%f" '
  798. 'viewMode="%s" >\n' % (' ' * self.indent,
  799. int(mapTree.mapdisplay.GetProperty('render')),
  800. mapTree.mapdisplay.statusbarManager.GetMode(),
  801. int(mapTree.mapdisplay.GetProperty('region')),
  802. int(mapTree.mapdisplay.GetProperty('alignExtent')),
  803. int(mapTree.mapdisplay.GetProperty('resolution')),
  804. displayPos[0],
  805. displayPos[1],
  806. displaySize[0],
  807. displaySize[1],
  808. region['w'],
  809. region['s'],
  810. region['e'],
  811. region['n'],
  812. viewmode
  813. ))
  814. # projection statusbar info
  815. if mapTree.mapdisplay.GetProperty('projection') and \
  816. UserSettings.Get(group='display', key='projection', subkey='proj4'):
  817. self.indent += 4
  818. file.write('%s<projection' % (' ' * self.indent))
  819. epsg = UserSettings.Get(group='display', key='projection', subkey='epsg')
  820. if epsg:
  821. file.write(' epsg="%s"' % epsg)
  822. file.write('>\n')
  823. proj = UserSettings.Get(group='display', key='projection', subkey='proj4')
  824. self.indent += 4
  825. file.write('%s<value>%s</value>\n' % (' ' * self.indent, proj))
  826. self.indent -= 4
  827. file.write('%s</projection>\n' % (' ' * self.indent))
  828. self.indent -= 4
  829. # list of layers
  830. item = mapTree.GetFirstChild(mapTree.root)[0]
  831. self.__writeLayer(mapTree, item)
  832. if mapTree.mapdisplay.MapWindow3D is not None:
  833. nvizDisp = mapTree.mapdisplay.MapWindow3D
  834. self.__writeNvizState(view = nvizDisp.view, iview = nvizDisp.iview,
  835. light = nvizDisp.light, constants = nvizDisp.constants)
  836. file.write('%s</display>\n' % (' ' * self.indent))
  837. self.indent =- 4
  838. file.write('%s</gxw>\n' % (' ' * self.indent))
  839. def __filterValue(self, value):
  840. """!Make value XML-valid"""
  841. value = value.replace('<', '&lt;')
  842. value = value.replace('>', '&gt;')
  843. return value
  844. def __writeLayer(self, mapTree, item):
  845. """!Write bunch of layers to GRASS Workspace XML file"""
  846. self.indent += 4
  847. itemSelected = mapTree.GetSelections()
  848. while item and item.IsOk():
  849. type = mapTree.GetPyData(item)[0]['type']
  850. if type != 'group':
  851. maplayer = mapTree.GetPyData(item)[0]['maplayer']
  852. else:
  853. maplayer = None
  854. checked = int(item.IsChecked())
  855. if type == 'command':
  856. cmd = mapTree.GetPyData(item)[0]['maplayer'].GetCmd(string=True)
  857. self.file.write('%s<layer type="%s" name="%s" checked="%d">\n' % \
  858. (' ' * self.indent, type, cmd, checked));
  859. self.file.write('%s</layer>\n' % (' ' * self.indent));
  860. elif type == 'group':
  861. name = mapTree.GetItemText(item)
  862. self.file.write('%s<group name="%s" checked="%d">\n' % \
  863. (' ' * self.indent, name.encode('utf8'), checked));
  864. self.indent += 4
  865. subItem = mapTree.GetFirstChild(item)[0]
  866. self.__writeLayer(mapTree, subItem)
  867. self.indent -= 4
  868. self.file.write('%s</group>\n' % (' ' * self.indent));
  869. else:
  870. cmd = mapTree.GetPyData(item)[0]['maplayer'].GetCmd(string=False)
  871. name = mapTree.GetItemText(item)
  872. opacity = maplayer.GetOpacity(float = True)
  873. # remove 'opacity' part
  874. if opacity < 1:
  875. name = name.split('(', -1)[0].strip()
  876. self.file.write('%s<layer type="%s" name="%s" checked="%d" opacity="%f">\n' % \
  877. (' ' * self.indent, type, name.encode('utf8'), checked, opacity));
  878. self.indent += 4
  879. # selected ?
  880. if item in itemSelected:
  881. self.file.write('%s<selected />\n' % (' ' * self.indent))
  882. # layer properties
  883. self.file.write('%s<task name="%s">\n' % (' ' * self.indent, cmd[0]))
  884. self.indent += 4
  885. for key, val in cmd[1].iteritems():
  886. if key == 'flags':
  887. for f in val:
  888. self.file.write('%s<flag name="%s" />\n' %
  889. (' ' * self.indent, f))
  890. elif val in (True, False):
  891. self.file.write('%s<flag name="%s" />\n' %
  892. (' ' * self.indent, key))
  893. else: # parameter
  894. self.file.write('%s<parameter name="%s">\n' %
  895. (' ' * self.indent, key))
  896. self.indent += 4
  897. self.file.write('%s<value>%s</value>\n' %
  898. (' ' * self.indent, self.__filterValue(val)))
  899. self.indent -= 4
  900. self.file.write('%s</parameter>\n' % (' ' * self.indent));
  901. self.indent -= 4
  902. self.file.write('%s</task>\n' % (' ' * self.indent));
  903. # vector digitizer
  904. vdigit = mapTree.GetPyData(item)[0]['vdigit']
  905. if vdigit:
  906. self.file.write('%s<vdigit>\n' % (' ' * self.indent))
  907. if 'geomAttr' in vdigit:
  908. self.indent += 4
  909. for type, val in vdigit['geomAttr'].iteritems():
  910. units = ''
  911. if val['units'] != 'mu':
  912. units = ' units="%s"' % val['units']
  913. self.file.write('%s<geometryAttribute type="%s" column="%s"%s />\n' % \
  914. (' ' * self.indent, type, val['column'], units))
  915. self.indent -= 4
  916. self.file.write('%s</vdigit>\n' % (' ' * self.indent))
  917. # nviz
  918. nviz = mapTree.GetPyData(item)[0]['nviz']
  919. if nviz:
  920. self.file.write('%s<nviz>\n' % (' ' * self.indent))
  921. if maplayer.type == 'raster':
  922. self.__writeNvizSurface(nviz['surface'])
  923. elif maplayer.type == 'vector':
  924. self.__writeNvizVector(nviz['vector'])
  925. self.file.write('%s</nviz>\n' % (' ' * self.indent))
  926. self.indent -= 4
  927. self.file.write('%s</layer>\n' % (' ' * self.indent))
  928. item = mapTree.GetNextSibling(item)
  929. self.indent -= 4
  930. def __writeNvizSurface(self, data):
  931. """!Save Nviz raster layer properties to workspace
  932. @param data Nviz layer properties
  933. """
  934. if 'object' not in data: # skip disabled
  935. return
  936. self.indent += 4
  937. self.file.write('%s<surface>\n' % (' ' * self.indent))
  938. self.indent += 4
  939. for attrb in data.iterkeys():
  940. if len(data[attrb]) < 1: # skip empty attributes
  941. continue
  942. if attrb == 'object':
  943. continue
  944. for name in data[attrb].iterkeys():
  945. # surface attribute
  946. if attrb == 'attribute':
  947. self.file.write('%s<%s name="%s" map="%d">\n' % \
  948. (' ' * self.indent, attrb, name, data[attrb][name]['map']))
  949. self.indent += 4
  950. self.file.write('%s<value>%s</value>\n' % (' ' * self.indent, data[attrb][name]['value']))
  951. self.indent -= 4
  952. # end tag
  953. self.file.write('%s</%s>\n' % (' ' * self.indent, attrb))
  954. # draw mode
  955. if attrb == 'draw':
  956. self.file.write('%s<%s' %(' ' * self.indent, attrb))
  957. if 'mode' in data[attrb]:
  958. for tag, value in data[attrb]['mode']['desc'].iteritems():
  959. self.file.write(' %s="%s"' % (tag, value))
  960. self.file.write('>\n') # <draw ...>
  961. if 'resolution' in data[attrb]:
  962. self.indent += 4
  963. for type in ('coarse', 'fine'):
  964. self.file.write('%s<resolution type="%s">\n' % (' ' * self.indent, type))
  965. self.indent += 4
  966. self.file.write('%s<value>%d</value>\n' % (' ' * self.indent,
  967. data[attrb]['resolution'][type]))
  968. self.indent -= 4
  969. self.file.write('%s</resolution>\n' % (' ' * self.indent))
  970. if 'wire-color' in data[attrb]:
  971. self.file.write('%s<wire_color>\n' % (' ' * self.indent))
  972. self.indent += 4
  973. self.file.write('%s<value>%s</value>\n' % (' ' * self.indent,
  974. data[attrb]['wire-color']['value']))
  975. self.indent -= 4
  976. self.file.write('%s</wire_color>\n' % (' ' * self.indent))
  977. self.indent -= 4
  978. # position
  979. elif attrb == 'position':
  980. self.file.write('%s<%s>\n' %(' ' * self.indent, attrb))
  981. i = 0
  982. for tag in ('x', 'y', 'z'):
  983. self.indent += 4
  984. self.file.write('%s<%s>%d</%s>\n' % (' ' * self.indent, tag,
  985. data[attrb][tag], tag))
  986. i += 1
  987. self.indent -= 4
  988. if attrb != 'attribute':
  989. # end tag
  990. self.file.write('%s</%s>\n' % (' ' * self.indent, attrb))
  991. self.indent -= 4
  992. self.file.write('%s</surface>\n' % (' ' * self.indent))
  993. self.indent -= 4
  994. def __writeNvizVector(self, data):
  995. """!Save Nviz vector layer properties (lines/points) to workspace
  996. @param data Nviz layer properties
  997. """
  998. self.indent += 4
  999. for attrb in data.iterkeys():
  1000. if len(data[attrb]) < 1: # skip empty attributes
  1001. continue
  1002. if 'object' not in data[attrb]: # skip disabled
  1003. continue
  1004. if attrb == 'lines':
  1005. self.file.write('%s<v%s>\n' % (' ' * self.indent, attrb))
  1006. elif attrb == 'points':
  1007. markerId = data[attrb]['marker']['value']
  1008. marker = UserSettings.Get(group = 'nviz', key = 'vector',
  1009. subkey = ['points', 'marker'], internal = True)[markerId]
  1010. self.file.write('%s<v%s marker="%s">\n' % (' ' * self.indent,
  1011. attrb,
  1012. marker))
  1013. self.indent += 4
  1014. for name in data[attrb].iterkeys():
  1015. if name in ('object', 'marker'):
  1016. continue
  1017. if name == 'mode':
  1018. self.file.write('%s<%s type="%s">\n' % (' ' * self.indent, name,
  1019. data[attrb][name]['type']))
  1020. if data[attrb][name]['type'] == 'surface':
  1021. self.indent += 4
  1022. for idx, surface in enumerate(data[attrb][name]['surface']['value']):
  1023. checked = data[attrb][name]['surface']['show'][idx]
  1024. self.file.write('%s<map>\n' % (' ' * self.indent))
  1025. self.indent += 4
  1026. self.file.write('%s<name>%s</name>\n' % (' ' * self.indent, surface))
  1027. self.file.write('%s<checked>%s</checked>\n' % (' ' * self.indent, int(checked)))
  1028. self.indent -= 4
  1029. self.file.write('%s</map>\n' % (' ' * self.indent))
  1030. self.indent -= 4
  1031. self.file.write('%s</%s>\n' % ((' ' * self.indent, name)))
  1032. elif name == 'thematic':
  1033. self.file.write('%s<%s ' % (' ' * self.indent, name))
  1034. for key in data[attrb][name].iterkeys():
  1035. if key.startswith('use'):
  1036. self.file.write('%s="%s" ' % (key, int(data[attrb][name][key])))
  1037. self.file.write('>\n')
  1038. self.indent += 4
  1039. for key, value in data[attrb][name].iteritems():
  1040. if key.startswith('use'):
  1041. continue
  1042. if value is None:
  1043. value = ''
  1044. self.file.write('%s<%s>%s</%s>\n' % (' ' * self.indent, key, value, key))
  1045. self.indent -= 4
  1046. self.file.write('%s</%s>\n' % (' ' * self.indent, name))
  1047. else:
  1048. self.file.write('%s<%s>\n' % (' ' * self.indent, name))
  1049. self.indent += 4
  1050. self.file.write('%s<value>%s</value>\n' % (' ' * self.indent, data[attrb][name]['value']))
  1051. self.indent -= 4
  1052. self.file.write('%s</%s>\n' % (' ' * self.indent, name))
  1053. self.indent -= 4
  1054. self.file.write('%s</v%s>\n' % (' ' * self.indent, attrb))
  1055. self.indent -= 4
  1056. def __writeNvizState(self, view, iview, light, constants):
  1057. """"!Save Nviz properties (view, light) to workspace
  1058. @param view Nviz view properties
  1059. @param iview Nviz internal view properties
  1060. @param light Nviz light properties
  1061. """
  1062. self.indent += 4
  1063. self.file.write('%s<nviz_state>\n' % (' ' * self.indent))
  1064. #
  1065. # view
  1066. #
  1067. self.indent += 4
  1068. self.file.write('%s<view>\n' % (' ' * self.indent))
  1069. self.indent += 4
  1070. # position
  1071. self.file.write('%s<v_position>\n' % (' ' * self.indent))
  1072. self.indent += 4
  1073. self.file.write('%s<x>%.2f</x>\n' % (' ' * self.indent, view['position']['x']))
  1074. self.file.write('%s<y>%.2f</y>\n' % (' ' * self.indent, view['position']['y']))
  1075. self.indent -= 4
  1076. self.file.write('%s</v_position>\n' % (' ' * self.indent))
  1077. # perspective
  1078. self.file.write('%s<persp>\n' % (' ' * self.indent))
  1079. self.indent += 4
  1080. self.file.write('%s<value>%d</value>\n' % (' ' * self.indent, view['persp']['value']))
  1081. self.file.write('%s<step>%d</step>\n' % (' ' * self.indent, view['persp']['step']))
  1082. self.file.write('%s<min>%d</min>\n' % (' ' * self.indent, iview['persp']['min']))
  1083. self.file.write('%s<max>%d</max>\n' % (' ' * self.indent, iview['persp']['max']))
  1084. self.indent -= 4
  1085. self.file.write('%s</persp>\n' % (' ' * self.indent))
  1086. # height
  1087. self.file.write('%s<v_height>\n' % (' ' * self.indent))
  1088. self.indent += 4
  1089. self.file.write('%s<value>%d</value>\n' % (' ' * self.indent, iview['height']['value']))
  1090. self.file.write('%s<min>%d</min>\n' % (' ' * self.indent, iview['height']['min']))
  1091. self.file.write('%s<max>%d</max>\n' % (' ' * self.indent, iview['height']['max']))
  1092. self.indent -= 4
  1093. self.file.write('%s</v_height>\n' % (' ' * self.indent))
  1094. # twist
  1095. self.file.write('%s<twist>\n' % (' ' * self.indent))
  1096. self.indent += 4
  1097. self.file.write('%s<value>%d</value>\n' % (' ' * self.indent, view['twist']['value']))
  1098. self.file.write('%s<min>%d</min>\n' % (' ' * self.indent, iview['twist']['min']))
  1099. self.file.write('%s<max>%d</max>\n' % (' ' * self.indent, iview['twist']['max']))
  1100. self.indent -= 4
  1101. self.file.write('%s</twist>\n' % (' ' * self.indent))
  1102. # z-exag
  1103. self.file.write('%s<z-exag>\n' % (' ' * self.indent))
  1104. self.indent += 4
  1105. self.file.write('%s<value>%d</value>\n' % (' ' * self.indent, view['z-exag']['value']))
  1106. self.file.write('%s<min>%d</min>\n' % (' ' * self.indent, view['z-exag']['min']))
  1107. self.file.write('%s<max>%d</max>\n' % (' ' * self.indent, view['z-exag']['max']))
  1108. self.file.write('%s<original>%d</original>\n' % (' ' * self.indent, iview['z-exag']['original']))
  1109. self.indent -= 4
  1110. self.file.write('%s</z-exag>\n' % (' ' * self.indent))
  1111. # focus (look here)
  1112. self.file.write('%s<focus>\n' % (' ' * self.indent))
  1113. self.indent += 4
  1114. self.file.write('%s<x>%d</x>\n' % (' ' * self.indent, iview['focus']['x']))
  1115. self.file.write('%s<y>%d</y>\n' % (' ' * self.indent, iview['focus']['y']))
  1116. self.file.write('%s<z>%d</z>\n' % (' ' * self.indent, iview['focus']['z']))
  1117. self.indent -= 4
  1118. self.file.write('%s</focus>\n' % (' ' * self.indent))
  1119. # background
  1120. self.__writeTagWithValue('background_color', view['background']['color'][:3], format = 'd:%d:%d')
  1121. self.indent -= 4
  1122. self.file.write('%s</view>\n' % (' ' * self.indent))
  1123. #
  1124. # light
  1125. #
  1126. self.file.write('%s<light>\n' % (' ' * self.indent))
  1127. self.indent += 4
  1128. # position
  1129. self.file.write('%s<l_position>\n' % (' ' * self.indent))
  1130. self.indent += 4
  1131. self.file.write('%s<x>%.2f</x>\n' % (' ' * self.indent, light['position']['x']))
  1132. self.file.write('%s<y>%.2f</y>\n' % (' ' * self.indent, light['position']['y']))
  1133. self.file.write('%s<z>%d</z>\n' % (' ' * self.indent, light['position']['z']))
  1134. self.indent -= 4
  1135. self.file.write('%s</l_position>\n' % (' ' * self.indent))
  1136. # bright
  1137. self.__writeTagWithValue('bright', light['bright'])
  1138. # ambient
  1139. self.__writeTagWithValue('ambient', light['ambient'])
  1140. # color
  1141. self.__writeTagWithValue('color', light['color'][:3], format = 'd:%d:%d')
  1142. self.indent -= 4
  1143. self.file.write('%s</light>\n' % (' ' * self.indent))
  1144. #
  1145. # constant planes
  1146. #
  1147. if constants:
  1148. self.file.write('%s<constant_planes>\n' % (' ' * self.indent))
  1149. self.indent += 4
  1150. for idx, plane in enumerate(constants):
  1151. self.file.write('%s<plane>\n' % (' ' * self.indent))
  1152. self.indent += 4
  1153. self.__writeTagWithValue('height', constants[idx]['constant']['value'])
  1154. self.__writeTagWithValue('fine_resolution', constants[idx]['constant']['resolution'])
  1155. self.__writeTagWithValue('color', constants[idx]['constant']['color'], format = 's')
  1156. self.indent -= 4
  1157. self.file.write('%s</plane>\n' % (' ' * self.indent))
  1158. self.indent -= 4
  1159. self.file.write('%s</constant_planes>\n' % (' ' * self.indent))
  1160. self.indent -= 4
  1161. self.file.write('%s</nviz_state>\n' % (' ' * self.indent))
  1162. self.indent -= 4
  1163. def __writeTagWithValue(self, tag, data, format = 'd'):
  1164. """!Helper function for writing pair tag
  1165. @param tag written tag
  1166. @param data written data
  1167. @param format conversion type
  1168. """
  1169. self.file.write('%s<%s>\n' % (' ' * self.indent, tag))
  1170. self.indent += 4
  1171. self.file.write('%s' % (' ' * self.indent))
  1172. self.file.write(('<value>%' + format + '</value>\n') % data)
  1173. self.indent -= 4
  1174. self.file.write('%s</%s>\n' % (' ' * self.indent, tag))
  1175. class ProcessGrcFile(object):
  1176. def __init__(self, filename):
  1177. """!Process GRC file"""
  1178. self.filename = filename
  1179. # elements
  1180. self.inGroup = False
  1181. self.inRaster = False
  1182. self.inVector = False
  1183. # list of layers
  1184. self.layers = []
  1185. # error message
  1186. self.error = ''
  1187. self.num_error = 0
  1188. def read(self, parent):
  1189. """!Read GRC file
  1190. @param parent parent window
  1191. @return list of map layers
  1192. """
  1193. try:
  1194. file = open(self.filename, "r")
  1195. except IOError:
  1196. wx.MessageBox(parent=parent,
  1197. message=_("Unable to open file <%s> for reading.") % self.filename,
  1198. caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
  1199. return []
  1200. line_id = 1
  1201. for line in file.readlines():
  1202. self.process_line(line.rstrip('\n'), line_id)
  1203. line_id +=1
  1204. file.close()
  1205. if self.num_error > 0:
  1206. wx.MessageBox(parent=parent,
  1207. message=_("Some lines were skipped when reading settings "
  1208. "from file <%(file)s>.\nSee 'Command output' window for details.\n\n"
  1209. "Number of skipped lines: %(line)d") % \
  1210. { 'file' : self.filename, 'line' : self.num_error },
  1211. caption=_("Warning"), style=wx.OK | wx.ICON_EXCLAMATION)
  1212. parent.goutput.WriteLog('Map layers loaded from GRC file <%s>' % self.filename)
  1213. parent.goutput.WriteLog('Skipped lines:\n%s' % self.error)
  1214. return self.layers
  1215. def process_line(self, line, line_id):
  1216. """!Process line definition"""
  1217. element = self._get_element(line)
  1218. if element == 'Group':
  1219. self.groupName = self._get_value(line)
  1220. self.layers.append({
  1221. "type" : 'group',
  1222. "name" : self.groupName,
  1223. "checked" : None,
  1224. "opacity" : None,
  1225. "cmd" : None,
  1226. "group" : self.inGroup,
  1227. "display" : 0 })
  1228. self.inGroup = True
  1229. elif element == '_check':
  1230. if int(self._get_value(line)) == 1:
  1231. self.layers[-1]['checked'] = True
  1232. else:
  1233. self.layers[-1]['checked'] = False
  1234. elif element == 'End':
  1235. if self.inRaster:
  1236. self.inRaster = False
  1237. elif self.inVector:
  1238. self.inVector = False
  1239. elif self.inGroup:
  1240. self.inGroup = False
  1241. elif self.inGridline:
  1242. self.inGridline = False
  1243. elif element == 'opacity':
  1244. self.layers[-1]['opacity'] = float(self._get_value(line))
  1245. # raster
  1246. elif element == 'Raster':
  1247. self.inRaster = True
  1248. self.layers.append({
  1249. "type" : 'raster',
  1250. "name" : self._get_value(line),
  1251. "checked" : None,
  1252. "opacity" : None,
  1253. "cmd" : ['d.rast'],
  1254. "group" : self.inGroup,
  1255. "display" : 0})
  1256. elif element == 'map' and self.inRaster:
  1257. self.layers[-1]['cmd'].append('map=%s' % self._get_value(line))
  1258. elif element == 'overlay' and self.inRaster:
  1259. if int(self._get_value(line)) == 1:
  1260. self.layers[-1]['cmd'].append('-o')
  1261. elif element == 'rastquery' and self.inRaster:
  1262. value = self._get_value(line)
  1263. if value != '':
  1264. self.layers[-1]['cmd'].append('catlist=%s' % value)
  1265. elif element == 'bkcolor' and self.inRaster:
  1266. value = self._get_value(line)
  1267. if value != '':
  1268. self.layers[-1]['cmd'].append('bg=%s' % value)
  1269. # vector
  1270. elif element == 'Vector':
  1271. self.inVector = True
  1272. self.layers.append({
  1273. "type" : 'vector',
  1274. "name" : self._get_value(line),
  1275. "checked" : None,
  1276. "opacity" : None,
  1277. "cmd" : ['d.vect'],
  1278. "group" : self.inGroup,
  1279. "display" : 0})
  1280. elif element == 'vect' and self.inVector:
  1281. self.layers[-1]['cmd'].append('map=%s' % self._get_value(line))
  1282. elif element in ('display_shape',
  1283. 'display_cat',
  1284. 'display_topo',
  1285. 'display_dir',
  1286. 'display_attr',
  1287. 'type_point',
  1288. 'type_line',
  1289. 'type_boundary',
  1290. 'type_centroid',
  1291. 'type_area',
  1292. 'type_face') and self.inVector:
  1293. if int(self._get_value(line)) == 1:
  1294. name = element.split('_')[0]
  1295. type = element.split('_')[1]
  1296. paramId = self._get_cmd_param_index(self.layers[-1]['cmd'], name)
  1297. if paramId == -1:
  1298. self.layers[-1]['cmd'].append('%s=%s' % (name, type))
  1299. else:
  1300. self.layers[-1]['cmd'][paramId] += ',%s' % type
  1301. elif element in ('color',
  1302. 'fcolor',
  1303. 'lcolor') and self.inVector:
  1304. value = self._get_value(line)
  1305. if value != '':
  1306. self.layers[-1]['cmd'].append('%s=%s' % (element,
  1307. self._color_name_to_rgb(value)))
  1308. elif element == 'rdmcolor' and self.inVector:
  1309. if int(self._get_value(line)) == 1:
  1310. self.layers[-1]['cmd'].append('-c')
  1311. elif element == 'sqlcolor' and self.inVector:
  1312. if int(self._get_value(line)) == 1:
  1313. self.layers[-1]['cmd'].append('-a')
  1314. elif element in ('icon',
  1315. 'size',
  1316. 'layer',
  1317. 'xref',
  1318. 'yref',
  1319. 'lsize',
  1320. 'where',
  1321. 'minreg',
  1322. 'maxreg') and self.inVector:
  1323. value = self._get_value(line)
  1324. if value != '':
  1325. self.layers[-1]['cmd'].append('%s=%s' % (element,
  1326. value))
  1327. elif element == 'lwidth':
  1328. value = self._get_value(line)
  1329. if value != '':
  1330. self.layers[-1]['cmd'].append('width=%s' % value)
  1331. elif element == 'lfield':
  1332. value = self._get_value(line)
  1333. if value != '':
  1334. self.layers[-1]['cmd'].append('llayer=%s' % value)
  1335. elif element == 'attribute':
  1336. value = self._get_value(line)
  1337. if value != '':
  1338. self.layers[-1]['cmd'].append('attrcol=%s' % value)
  1339. elif element == 'cat':
  1340. value = self._get_value(line)
  1341. if value != '':
  1342. self.layers[-1]['cmd'].append('cats=%s' % value)
  1343. # gridline
  1344. elif element == 'gridline':
  1345. self.inGridline = True
  1346. self.layers.append({
  1347. "type" : 'grid',
  1348. "name" : self._get_value(line),
  1349. "checked" : None,
  1350. "opacity" : None,
  1351. "cmd" : ['d.grid'],
  1352. "group" : self.inGroup,
  1353. "display" : 0})
  1354. elif element == 'gridcolor':
  1355. value = self._get_value(line)
  1356. if value != '':
  1357. self.layers[-1]['cmd'].append('color=%s' % self._color_name_to_rgb(value))
  1358. elif element == 'gridborder':
  1359. value = self._get_value(line)
  1360. if value != '':
  1361. self.layers[-1]['cmd'].append('bordercolor=%s' % self._color_name_to_rgb(value))
  1362. elif element == 'textcolor':
  1363. value = self._get_value(line)
  1364. if value != '':
  1365. self.layers[-1]['cmd'].append('textcolor=%s' % self._color_name_to_rgb(value))
  1366. elif element in ('gridsize',
  1367. 'gridorigin'):
  1368. value = self._get_value(line)
  1369. if value != '':
  1370. self.layers[-1]['cmd'].append('%s=%s' % (element[4:], value))
  1371. elif element in 'fontsize':
  1372. value = self._get_value(line)
  1373. if value != '':
  1374. self.layers[-1]['cmd'].append('%s=%s' % (element, value))
  1375. elif element == 'griddraw':
  1376. value = self._get_value(line)
  1377. if value == '0':
  1378. self.layers[-1]['cmd'].append('-n')
  1379. elif element == 'gridgeo':
  1380. value = self._get_value(line)
  1381. if value == '1':
  1382. self.layers[-1]['cmd'].append('-g')
  1383. elif element == 'borderdraw':
  1384. value = self._get_value(line)
  1385. if value == '0':
  1386. self.layers[-1]['cmd'].append('-b')
  1387. elif element == 'textdraw':
  1388. value = self._get_value(line)
  1389. if value == '0':
  1390. self.layers[-1]['cmd'].append('-t')
  1391. else:
  1392. self.error += _(' row %d:') % line_id + line + os.linesep
  1393. self.num_error += 1
  1394. def _get_value(self, line):
  1395. """!Get value of element"""
  1396. try:
  1397. return line.strip(' ').split(' ')[1].strip(' ')
  1398. except:
  1399. return ''
  1400. def _get_element(self, line):
  1401. """!Get element tag"""
  1402. return line.strip(' ').split(' ')[0].strip(' ')
  1403. def _get_cmd_param_index(self, cmd, name):
  1404. """!Get index of parameter in cmd list
  1405. @param cmd cmd list
  1406. @param name parameter name
  1407. @return index
  1408. @return -1 if not found
  1409. """
  1410. i = 0
  1411. for param in cmd:
  1412. if '=' not in param:
  1413. i += 1
  1414. continue
  1415. if param.split('=')[0] == name:
  1416. return i
  1417. i += 1
  1418. return -1
  1419. def _color_name_to_rgb(self, value):
  1420. """!Convert color name (#) to rgb values"""
  1421. col = wx.NamedColour(value)
  1422. return str(col.Red()) + ':' + \
  1423. str(col.Green()) + ':' + \
  1424. str(col.Blue())