nviztask.py 12 KB

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