nviztask.py 13 KB

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