nviztask.py 13 KB

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