nviztask.py 12 KB

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