""" @package animation.nviztask @brief Conversion from workspace file to m.nviz.image command Classes: - nviztask::NvizTask (C) 2013 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @author Anna Petrasova """ from __future__ import print_function try: import xml.etree.ElementTree as etree except ImportError: import elementtree.ElementTree as etree # Python <= 2.4 from core.workspace import ProcessWorkspaceFile from core.gcmd import RunCommand, GException from core.utils import GetLayerNameFromCmd from grass.script import task as gtask from core.settings import UserSettings class NvizTask: def __init__(self): self.task = None self.filename = None self.region = {} def Load(self, filename): self.task = gtask.grassTask("m.nviz.image") self.filename = filename try: gxwXml = ProcessWorkspaceFile(etree.parse(self.filename)) except Exception: raise GException( _( "Reading workspace file <%s> failed.\n" "Invalid file, unable to parse XML document." ) % filename ) # for display in gxwXml.displays: # pprint(display) # for layer in gxwXml.layers: # pprint(layer) # pprint(gxwXml.nviz_state) if not gxwXml.nviz_state: raise GException( _("No 3d view information in workspace file <%s>.") % self.filename ) self._getExtent(gxwXml) self._processState(gxwXml.nviz_state) self._processLayers(gxwXml.layers) def _getExtent(self, root): for display in root.displays: if display["viewMode"] == "3d": ( self.region["w"], self.region["s"], self.region["e"], self.region["n"], self.region["b"], self.region["t"], ) = display["extent"] self.region["tbres"] = display["tbres"] def _processLayers(self, layers): for layer in layers: if not layer["checked"]: continue if not layer["nviz"]: continue layerName, found = GetLayerNameFromCmd( layer["cmd"], fullyQualified=False, param="map" ) if not found: continue if "surface" in layer["nviz"]: self._processSurface(layer["nviz"]["surface"], mapName=layerName) if "volume" in layer["nviz"]: self._processVolume(layer["nviz"]["volume"], mapName=layerName) if "vector" in layer["nviz"]: if "points" in layer["nviz"]["vector"]: self._processPoints( layer["nviz"]["vector"]["points"], mapName=layerName ) def _processSurface(self, surface, mapName): self._setMultiTaskParam("elevation_map", mapName) # attributes like color, shine, transparency attributes = ("color", "shine", "transp") # mask missing parameters = ( ("color_map", "color"), ("shininess_map", "shininess_value"), ("transparency_map", "transparency_value"), ) for attr, params in zip(attributes, parameters): mapname = None const = None if attr in surface["attribute"]: if surface["attribute"][attr]["map"]: mapname = surface["attribute"][attr]["value"] else: const = surface["attribute"][attr]["value"] else: if attr == "transp": const = 0 elif attr == "color": mapname = mapName if mapname: self._setMultiTaskParam(params[0], mapname) else: self._setMultiTaskParam(params[1], const) # draw mode for mode in ("mode", "shading", "style"): value = surface["draw"]["mode"]["desc"][mode] self._setMultiTaskParam(mode, value) # wire color value = surface["draw"]["wire-color"]["value"] self._setMultiTaskParam("wire_color", value) # resolution for mode1, mode2 in zip( ("coarse", "fine"), ("resolution_coarse", "resolution_fine") ): value = surface["draw"]["resolution"][mode1] self._setMultiTaskParam(mode2, value) # position pos = [] for coor in ("x", "y", "z"): pos.append(str(surface["position"][coor])) value = ",".join(pos) self._setMultiTaskParam("surface_position", value) def _processPoints(self, points, mapName): for attrib in ("color", "size", "width"): if attrib in points: val = points[attrib]["value"] self._setMultiTaskParam("vpoint_" + attrib, str(val)) if "height" in points: height = points["height"]["value"] self._setMultiTaskParam("vpoint_position", "0,0,{h}".format(h=height)) if "marker" in points: marker = list( UserSettings.Get( group="nviz", key="vector", subkey=["points", "marker"], settings_type="internal", ) )[points["marker"]["value"]] self._setMultiTaskParam("vpoint_marker", marker) if "mode" in points: if points["mode"]["type"] == "3d": self._setMultiTaskParam("vpoint_mode", "3D") else: self._setMultiTaskParam("vpoint_mode", "surface") def _processVolume(self, volume, mapName): self._setMultiTaskParam("volume", mapName) if volume["draw"]["box"]["enabled"]: self.task.set_flag("b", True) # isosurfaces isosurfaces = volume["isosurface"] if isosurfaces: res_value = volume["draw"]["resolution"]["isosurface"]["value"] self._setMultiTaskParam("volume_resolution", res_value) for isosurface in isosurfaces: attributes = ("topo", "color", "shine", "transp") parameters = ( (None, "isosurf_level"), ("isosurf_color_map", "isosurf_color_value"), ("isosurf_shininess_map", "isosurf_shininess_value"), ("isosurf_transparency_map", "isosurf_transparency_value"), ) for attr, params in zip(attributes, parameters): mapname = None const = None if attr in isosurface: if isosurface[attr]["map"]: mapname = isosurface[attr]["value"] else: const = float(isosurface[attr]["value"]) else: if attr == "transp": const = 0 elif attr == "color": mapname = mapName if mapname: self._setMultiTaskParam(params[0], mapname) else: if attr == "topo": # TODO: we just assume it's the first volume, what # to do else? self._setMultiTaskParam(params[1], "1:" + str(const)) else: self._setMultiTaskParam(params[1], const) if isosurface["inout"]["value"]: self.task.set_flag("n", True) # slices slices = volume["slice"] if slices: res_value = volume["draw"]["resolution"]["slice"]["value"] self._setMultiTaskParam("volume_resolution", res_value) for slice_ in slices: self._setMultiTaskParam("slice_transparency", slice_["transp"]["value"]) axis = slice_["position"]["axis"] self._setMultiTaskParam("slice", "1:" + "xyz"[axis]) pos = slice_["position"] coords = ( pos["x1"], pos["x2"], pos["y1"], pos["y2"], pos["z1"], pos["z2"], ) self._setMultiTaskParam( "slice_position", ",".join([str(c) for c in coords]) ) # position pos = [] for coor in ("x", "y", "z"): pos.append(str(volume["position"][coor])) value = ",".join(pos) self._setMultiTaskParam("volume_position", value) def _processState(self, state): color = state["view"]["background"]["color"] self.task.set_param("bgcolor", self._join(color, delim=":")) self.task.set_param( "position", self._join( (state["view"]["position"]["x"], state["view"]["position"]["y"]) ), ) self.task.set_param("height", state["iview"]["height"]["value"]) self.task.set_param("perspective", state["view"]["persp"]["value"]) self.task.set_param("twist", state["view"]["twist"]["value"]) # TODO: fix zexag self.task.set_param("zexag", state["view"]["z-exag"]["value"]) self.task.set_param( "focus", self._join( ( state["iview"]["focus"]["x"], state["iview"]["focus"]["y"], state["iview"]["focus"]["z"], ) ), ) self.task.set_param( "light_position", self._join( ( state["light"]["position"]["x"], state["light"]["position"]["y"], state["light"]["position"]["z"] / 100.0, ) ), ) color = state["light"]["color"][:3] self.task.set_param("light_color", self._join(color, delim=":")) self.task.set_param("light_brightness", int(state["light"]["bright"])) self.task.set_param("light_ambient", state["light"]["ambient"]) def _setMultiTaskParam(self, param, value): last = self.task.get_param(param)["value"] self.task.set_param(param, self._join((last, value))) def _join(self, toJoin, delim=","): toJoin = filter(self._ignore, toJoin) return delim.join(map(str, toJoin)) def _ignore(self, value): if value == "" or value is None: return False else: return True def ListMapParameters(self): # params = self.task.get_list_params() # parameter with 'map' name # params = filter(lambda x: 'map' in x, params) return ("elevation_map", "color_map", "vline", "vpoint", "volume") def GetCommandSeries(self, layerList, paramName): commands = [] if not self.task: return commands if len(layerList) > 1: raise GException(_("Please add only one layer in the list.")) return layer = layerList[0] if hasattr(layer, "maps"): series = layer.maps else: raise GException(_("No map series nor space-time dataset is added.")) for value in series: self.task.set_param(paramName, value) # FIXME: we assume we want always default color map if paramName == "elevation_map": self.task.set_param( "color_map", self.task.get_param(paramName)["value"] ) if paramName == "volume": self.task.set_param("isosurf_color_map", "") self.task.set_flag("overwrite", True) self.task.set_param("output", "tobechanged") cmd = self.task.get_cmd( ignoreErrors=False, ignoreRequired=False, ignoreDefault=True ) commands.append(cmd) return commands def GetCommand(self): if not self.task: return None self.task.set_flag("overwrite", True) self.task.set_param("output", "tobechanged") cmd = self.task.get_cmd( ignoreErrors=False, ignoreRequired=False, ignoreDefault=True ) return gtask.cmdlist_to_tuple(cmd) def GetRegion(self): return self.region def test(): nviz = NvizTask("/home/anna/testy/nviz/t12.gxw") # nviz = NvizState('/home/anna/testy/nviz/t3.gxw') # cmd = nviz.GetCommand() cmds = nviz.GetCommandSeries(["aspect", "elevation"], "color_map") for cmd in cmds: print(cmd) returncode, message = RunCommand(getErrorMsg=True, prog=cmd[0], **cmd[1]) print(returncode, message) if __name__ == "__main__": test()