nviztask.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. """!
  2. @package animation.nviztask
  3. @brief Conversion from workspace file to m.nviz.image command
  4. Classes:
  5. - nviztask::NvizTask
  6. (C) 2013 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Anna Petrasova <kratochanna gmail.com>
  10. """
  11. import os
  12. import sys
  13. try:
  14. import xml.etree.ElementTree as etree
  15. except ImportError:
  16. import elementtree.ElementTree as etree # Python <= 2.4
  17. if __name__ == '__main__':
  18. sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
  19. from core.workspace import ProcessWorkspaceFile
  20. from core.gcmd import RunCommand, GException
  21. from core.utils import GetLayerNameFromCmd, CmdToTuple, _
  22. from grass.script import task as gtask
  23. class NvizTask:
  24. def __init__(self):
  25. self.task = None
  26. self.filename = None
  27. self.region = {}
  28. def Load(self, filename):
  29. self.task = gtask.grassTask("m.nviz.image")
  30. self.filename = filename
  31. try:
  32. gxwXml = ProcessWorkspaceFile(etree.parse(self.filename))
  33. except Exception:
  34. raise GException(_("Reading workspace file <%s> failed.\n"
  35. "Invalid file, unable to parse XML document.") % filename)
  36. # for display in gxwXml.displays:
  37. # pprint(display)
  38. # for layer in gxwXml.layers:
  39. # pprint(layer)
  40. # pprint(gxwXml.nviz_state)
  41. if not gxwXml.nviz_state:
  42. raise GException(_("No 3d view information in workspace file <%s>.") % self.filename)
  43. self._getExtent(gxwXml)
  44. self._processState(gxwXml.nviz_state)
  45. self._processLayers(gxwXml.layers)
  46. def _getExtent(self, root):
  47. for display in root.displays:
  48. if display['viewMode'] == '3d':
  49. self.region['w'], self.region['s'],\
  50. self.region['e'], self.region['n'],\
  51. self.region['b'], self.region['t'] = display['extent']
  52. self.region['tbres'] = display['tbres']
  53. def _processLayers(self, layers):
  54. for layer in layers:
  55. if not layer['checked']:
  56. continue
  57. if not layer['nviz']:
  58. continue
  59. layerName, found = GetLayerNameFromCmd(layer['cmd'], fullyQualified=False,
  60. param='map')
  61. if not found:
  62. continue
  63. if 'surface' in layer['nviz']:
  64. self._processSurface(layer['nviz']['surface'], mapName=layerName)
  65. if 'volume' in layer['nviz']:
  66. self._processVolume(layer['nviz']['volume'], mapName=layerName)
  67. def _processSurface(self, surface, mapName):
  68. self._setMultiTaskParam('elevation_map', mapName)
  69. # attributes like color, shine, transparency
  70. attributes = ('color', 'shine', 'transp') # mask missing
  71. parameters = (('color_map', 'color'),
  72. ('shininess_map', 'shininess_value'),
  73. ('transparency_map', 'transparency_value'))
  74. for attr, params in zip(attributes, parameters):
  75. mapname = None
  76. const = None
  77. if attr in surface['attribute']:
  78. if surface['attribute'][attr]['map']:
  79. mapname = surface['attribute'][attr]['value']
  80. else:
  81. const = surface['attribute'][attr]['value']
  82. else:
  83. if attr == 'transp':
  84. const = 0
  85. elif attr == 'color':
  86. mapname = mapName
  87. if mapname:
  88. self._setMultiTaskParam(params[0], mapname)
  89. else:
  90. self._setMultiTaskParam(params[1], const)
  91. # draw mode
  92. for mode in ('mode', 'shading', 'style'):
  93. value = surface['draw']['mode']['desc'][mode]
  94. self._setMultiTaskParam(mode, value)
  95. # wire color
  96. value = surface['draw']['wire-color']['value']
  97. self._setMultiTaskParam('wire_color', value)
  98. # resolution
  99. for mode1, mode2 in zip(('coarse', 'fine'), ('resolution_coarse', 'resolution_fine')):
  100. value = surface['draw']['resolution'][mode1]
  101. self._setMultiTaskParam(mode2, value)
  102. # position
  103. pos = []
  104. for coor in ('x', 'y', 'z'):
  105. pos.append(str(surface['position'][coor]))
  106. value = ','.join(pos)
  107. self._setMultiTaskParam('surface_position', value)
  108. def _processVolume(self, volume, mapName):
  109. self._setMultiTaskParam('volume', mapName)
  110. if volume['draw']['box']['enabled']:
  111. self.task.set_flag('b', True)
  112. # isosurfaces
  113. isosurfaces = volume['isosurface']
  114. if isosurfaces:
  115. res_value = volume['draw']['resolution']['isosurface']['value']
  116. self._setMultiTaskParam('volume_resolution', res_value)
  117. for isosurface in isosurfaces:
  118. attributes = ('topo', 'color', 'shine', 'transp')
  119. parameters = ((None, 'isosurf_level'),
  120. ('isosurf_color_map', 'isosurf_color_value'),
  121. ('isosurf_shininess_map', 'isosurf_shininess_value'),
  122. ('isosurf_transparency_map', 'isosurf_transparency_value'))
  123. for attr, params in zip(attributes, parameters):
  124. mapname = None
  125. const = None
  126. if attr in isosurface:
  127. if isosurface[attr]['map']:
  128. mapname = isosurface[attr]['value']
  129. else:
  130. const = float(isosurface[attr]['value'])
  131. else:
  132. if attr == 'transp':
  133. const = 0
  134. elif attr == 'color':
  135. mapname = mapName
  136. if mapname:
  137. self._setMultiTaskParam(params[0], mapname)
  138. else:
  139. if attr == 'topo':
  140. # TODO: we just assume it's the first volume, what to do else?
  141. self._setMultiTaskParam(params[1], '1:' + str(const))
  142. else:
  143. self._setMultiTaskParam(params[1], const)
  144. if isosurface['inout']['value']:
  145. self.task.set_flag('n', True)
  146. # slices
  147. slices = volume['slice']
  148. if slices:
  149. res_value = volume['draw']['resolution']['slice']['value']
  150. self._setMultiTaskParam('volume_resolution', res_value)
  151. for slice_ in slices:
  152. self._setMultiTaskParam('slice_transparency', slice_['transp']['value'])
  153. axis = slice_['position']['axis']
  154. self._setMultiTaskParam('slice', '1:' + 'xyz'[axis])
  155. pos = slice_['position']
  156. coords = pos['x1'], pos['x2'], pos['y1'], pos['y2'], pos['z1'], pos['z2']
  157. self._setMultiTaskParam('slice_position', ','.join([str(c) for c in coords]))
  158. # position
  159. pos = []
  160. for coor in ('x', 'y', 'z'):
  161. pos.append(str(volume['position'][coor]))
  162. value = ','.join(pos)
  163. self._setMultiTaskParam('volume_position', value)
  164. def _processState(self, state):
  165. color = state['view']['background']['color']
  166. self.task.set_param('bgcolor', self._join(color, delim=':'))
  167. self.task.set_param('position', self._join((state['view']['position']['x'],
  168. state['view']['position']['y'])))
  169. self.task.set_param('height', state['iview']['height']['value'])
  170. self.task.set_param('perspective', state['view']['persp']['value'])
  171. self.task.set_param('twist', state['view']['twist']['value'])
  172. # TODO: fix zexag
  173. self.task.set_param('zexag', state['view']['z-exag']['value'])
  174. self.task.set_param('focus', self._join((state['iview']['focus']['x'],
  175. state['iview']['focus']['y'],
  176. state['iview']['focus']['z'])))
  177. self.task.set_param('light_position', self._join((state['light']['position']['x'],
  178. state['light']['position']['y'],
  179. state['light']['position']['z'] / 100.)))
  180. color = state['light']['color'][:3]
  181. self.task.set_param('light_color', self._join(color, delim=':'))
  182. self.task.set_param('light_brightness', int(state['light']['bright']))
  183. self.task.set_param('light_ambient', state['light']['ambient'])
  184. def _setMultiTaskParam(self, param, value):
  185. last = self.task.get_param(param)['value']
  186. self.task.set_param(param, self._join((last, value)))
  187. def _join(self, toJoin, delim=','):
  188. toJoin = filter(self._ignore, toJoin)
  189. return delim.join(map(str, toJoin))
  190. def _ignore(self, value):
  191. if value == '' or value is None:
  192. return False
  193. else:
  194. return True
  195. def ListMapParameters(self):
  196. # params = self.task.get_list_params()
  197. # parameter with 'map' name
  198. # params = filter(lambda x: 'map' in x, params)
  199. return ('elevation_map', 'color_map', 'vline', 'vpoint', 'volume')
  200. def GetCommandSeries(self, layerList, paramName):
  201. commands = []
  202. if not self.task:
  203. return commands
  204. if len(layerList) > 1:
  205. raise GException(_("Please add only one layer in the list."))
  206. return
  207. layer = layerList[0]
  208. if hasattr(layer, 'maps'):
  209. series = layer.maps
  210. else:
  211. raise GException(_("No map series nor space-time dataset is added."))
  212. for value in series:
  213. self.task.set_param(paramName, value)
  214. # FIXME: we assume we want always default color map
  215. if paramName == 'elevation_map':
  216. self.task.set_param('color_map', '')
  217. if paramName == 'volume':
  218. self.task.set_param('isosurf_color_map', '')
  219. self.task.set_flag('overwrite', True)
  220. self.task.set_param('output', 'tobechanged')
  221. cmd = self.task.get_cmd(ignoreErrors=False, ignoreRequired=False, ignoreDefault=True)
  222. commands.append(cmd)
  223. return commands
  224. def GetCommand(self):
  225. if not self.task:
  226. return None
  227. self.task.set_flag('overwrite', True)
  228. self.task.set_param('output', 'tobechanged')
  229. cmd = self.task.get_cmd(ignoreErrors=False, ignoreRequired=False, ignoreDefault=True)
  230. return CmdToTuple(cmd)
  231. def GetRegion(self):
  232. return self.region
  233. def test():
  234. nviz = NvizTask('/home/anna/testy/nviz/t12.gxw')
  235. # nviz = NvizState('/home/anna/testy/nviz/t3.gxw')
  236. # cmd = nviz.GetCommand()
  237. cmds = nviz.GetCommandSeries(['aspect', 'elevation'], 'color_map')
  238. for cmd in cmds:
  239. print cmd
  240. returncode, message = RunCommand(getErrorMsg=True, prog=cmd[0], **cmd[1])
  241. print returncode, message
  242. if __name__ == '__main__':
  243. test()