[GRASS-SVN] r55367 - grass-addons/grass7/gui/wxpython/newgui
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Mar 13 11:04:31 PDT 2013
Author: rashadkm
Date: 2013-03-13 11:04:30 -0700 (Wed, 13 Mar 2013)
New Revision: 55367
Added:
grass-addons/grass7/gui/wxpython/newgui/render2.py
Log:
test api code(copied render.py)
Added: grass-addons/grass7/gui/wxpython/newgui/render2.py
===================================================================
--- grass-addons/grass7/gui/wxpython/newgui/render2.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/newgui/render2.py 2013-03-13 18:04:30 UTC (rev 55367)
@@ -0,0 +1,1403 @@
+"""!
+ at package core.render
+
+ at brief Rendering map layers and overlays into map composition image.
+
+ at todo Implement RenderManager also for other layers (see WMS
+implementation for details)
+
+ at todo Render classes should not care about updating statusbar (change emiting events).
+
+Classes:
+ - render::Layer
+ - render::MapLayer
+ - render::Overlay
+ - render::Map
+
+(C) 2006-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.
+
+ at author Michael Barton
+ at author Jachym Cepicky
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+import sys
+import glob
+import math
+import copy
+import tempfile
+import types
+
+import wx
+
+from grass.script import core as grass
+
+from core import utils
+from core.ws import RenderWMSMgr, wxUpdateProgressBar
+from core.gcmd import GException, GError, RunCommand
+from core.debug import Debug
+from core.settings import UserSettings
+
+USE_GPNMCOMP = True
+
+class Layer(object):
+ """!Virtual class which stores information about layers (map layers and
+ overlays) of the map composition.
+
+ - For map layer use MapLayer class.
+ - For overlays use Overlay class.
+ """
+ def __init__(self, ltype, cmd, Map, name = None,
+ active = True, hidden = False, opacity = 1.0):
+ """!Create new instance
+
+ @todo pass cmd as tuple instead of list
+
+ @param ltype layer type ('raster', 'vector', 'overlay', 'command', etc.)
+ @param cmd GRASS command to render layer,
+ given as list, e.g. ['d.rast', 'map=elevation at PERMANENT']
+ @param Map render.Map instance
+ @param name layer name, e.g. 'elevation at PERMANENT' (for layer tree)
+ @param active layer is active, will be rendered only if True
+ @param hidden layer is hidden, won't be listed in Layer Manager if True
+ @param opacity layer opacity <0;1>
+ """
+
+ # generated file for each layer
+ if USE_GPNMCOMP or ltype == 'overlay':
+ tmpfile = tempfile.mkstemp()[1]
+ self.maskfile = tmpfile + '.pgm'
+ if ltype == 'overlay':
+ self.mapfile = tmpfile + '.png'
+ else:
+ self.mapfile = tmpfile + '.ppm'
+ grass.try_remove(tmpfile)
+ else:
+ self.mapfile = self.maskfile = None
+
+ # stores class which manages rendering instead of simple command - e. g. wms
+ self.renderMgr = None
+
+ self.Map = Map
+ self.type = None
+ self.SetType(ltype)
+ self.name = name
+
+
+
+ if self.type == 'command':
+ self.cmd = list()
+ for c in cmd:
+ self.cmd.append(utils.CmdToTuple(c))
+ else:
+ self.cmd = utils.CmdToTuple(cmd)
+
+ self.active = active
+ self.hidden = hidden
+ self.opacity = opacity
+
+ self.forceRender = True
+
+ Debug.msg (3, "Layer.__init__(): type=%s, cmd='%s', name=%s, " \
+ "active=%d, opacity=%d, hidden=%d" % \
+ (self.type, self.GetCmd(string = True), self.name, self.active,
+ self.opacity, self.hidden))
+
+ def __del__(self):
+ Debug.msg (3, "Layer.__del__(): layer=%s, cmd='%s'" %
+ (self.name, self.GetCmd(string = True)))
+
+ def Render(self):
+ """!Render layer to image
+
+ @return rendered image filename
+ @return None on error or if cmdfile is defined
+ """
+ if not self.cmd:
+ return None
+
+ # ignore in 2D
+ if self.type == '3d-raster':
+ return None
+
+ Debug.msg (3, "Layer.Render(): type=%s, name=%s" % \
+ (self.type, self.name))
+
+ # prepare command for each layer
+ layertypes = utils.command2ltype.values() + ['overlay', 'command']
+
+ if self.type not in layertypes:
+ raise GException(_("<%(name)s>: layer type <%(type)s> is not supported") % \
+ {'type' : self.type, 'name' : self.name})
+
+ if self.mapfile:
+ os.environ["GRASS_PNGFILE"] = self.mapfile
+
+ # execute command
+ try:
+ if self.type == 'command':
+ read = False
+ for c in self.cmd:
+ ret, msg = self._runCommand(c)
+ if ret != 0:
+ break
+ if not read:
+ os.environ["GRASS_PNG_READ"] = "TRUE"
+
+ os.environ["GRASS_PNG_READ"] = "FALSE"
+ else:
+ ret, msg = self._runCommand(self.cmd)
+ if ret != 0:
+ sys.stderr.write(_("Command '%s' failed\n") % self.GetCmd(string = True))
+ if msg:
+ sys.stderr.write(_("Details: %s\n") % msg)
+ raise GException()
+
+ except GException:
+ # clean up after problems
+ for f in [self.mapfile, self.maskfile]:
+ if not f:
+ continue
+ grass.try_remove(f)
+ f = None
+
+ # stop monitor
+ if self.mapfile and "GRASS_PNGFILE" in os.environ:
+ del os.environ["GRASS_PNGFILE"]
+
+ self.forceRender = False
+
+ return self.mapfile
+
+ def _runCommand(self, cmd):
+ """!Run command to render data
+ """
+ if self.type == 'wms':
+ ret = 0
+ msg = ''
+ self.renderMgr.Render(cmd)
+ else:
+ ret, msg = RunCommand(cmd[0],
+ getErrorMsg = True,
+ quiet = True,
+ **cmd[1])
+
+ return ret, msg
+
+ def GetCmd(self, string = False):
+ """!Get GRASS command as list of string.
+
+ @param string get command as string if True otherwise as list
+
+ @return command list/string
+ """
+ if string:
+ if self.type == 'command':
+ scmd = []
+ for c in self.cmd:
+ scmd.append(utils.GetCmdString(c))
+
+ return ';'.join(scmd)
+ else:
+ return utils.GetCmdString(self.cmd)
+ else:
+ return self.cmd
+
+ def GetType(self):
+ """!Get map layer type"""
+ return self.type
+
+ def GetElement(self):
+ """!Get map element type"""
+ if self.type == 'raster':
+ return 'cell'
+ return self.type
+
+ def GetOpacity(self, float = False):
+ """
+ Get layer opacity level
+
+ @param float get opacity level in <0,1> otherwise <0,100>
+
+ @return opacity level
+ """
+ if float:
+ return self.opacity
+
+ return int (self.opacity * 100)
+
+ def GetName(self, fullyQualified = True):
+ """!Get map layer name
+
+ @param fullyQualified True to return fully qualified name as a
+ string 'name at mapset' otherwise directory { 'name', 'mapset' }
+ is returned
+
+ @return string / directory
+ """
+ if fullyQualified:
+ return self.name
+ else:
+ if '@' in self.name:
+ return { 'name' : self.name.split('@')[0],
+ 'mapset' : self.name.split('@')[1] }
+ else:
+ return { 'name' : self.name,
+ 'mapset' : '' }
+
+ def IsActive(self):
+ """!Check if layer is activated for rendering"""
+ return self.active
+
+ def SetType(self, ltype):
+ """!Set layer type"""
+ if ltype not in utils.command2ltype.values() + ['overlay', 'command']:
+ raise GException(_("Unsupported map layer type '%s'") % ltype)
+
+ if ltype == 'wms' and not isinstance(self.renderMgr, RenderWMSMgr):
+ self.renderMgr = RenderWMSMgr(receiver = self.Map.GetReceiver(),
+ layer = self,
+ Map = self.Map,
+ mapfile = self.mapfile,
+ maskfile = self.maskfile)
+ elif self.type == 'wms' and ltype != 'wms':
+ self.renderMgr = None
+
+ self.type = ltype
+
+ def SetName(self, name):
+ """!Set layer name"""
+ self.name = name
+
+ def SetActive(self, enable = True):
+ """!Active or deactive layer"""
+ self.active = bool(enable)
+
+ def SetHidden(self, enable = False):
+ """!Hide or show map layer in Layer Manager"""
+ self.hidden = bool(enable)
+
+ def SetOpacity(self, value):
+ """!Set opacity value"""
+ if value < 0:
+ value = 0.
+ elif value > 1:
+ value = 1.
+
+ self.opacity = float(value)
+
+ def SetCmd(self, cmd):
+ """!Set new command for layer"""
+ if self.type == 'command':
+ self.cmd = []
+ for c in cmd:
+ self.cmd.append(utils.CmdToTuple(c))
+ else:
+ self.cmd = utils.CmdToTuple(cmd)
+ Debug.msg(3, "Layer.SetCmd(): cmd='%s'" % self.GetCmd(string = True))
+
+ # for re-rendering
+ self.forceRender = True
+
+ def IsDownloading(self):
+ """!Is data downloading from web server e. g. wms"""
+ if self.renderMgr is None:
+ return False
+ else:
+ return self.renderMgr.IsDownloading()
+
+ def AbortThread(self):
+ """!Abort running thread e. g. downloading data"""
+ if self.renderMgr is None:
+ return
+ else:
+ self.renderMgr.Abort()
+
+ def GetRenderMgr(self):
+ """!Get render manager """
+ return self.renderMgr
+
+class MapLayer(Layer):
+ def __init__(self, ltype, cmd, Map, name = None,
+ active = True, hidden = False, opacity = 1.0):
+ """!Represents map layer in the map canvas
+
+ @param ltype layer type ('raster', 'vector', 'command', etc.)
+ @param cmd GRASS command to render layer,
+ given as list, e.g. ['d.rast', 'map=elevation at PERMANENT']
+ @param Map render.Map instance
+ @param name layer name, e.g. 'elevation at PERMANENT' (for layer tree) or None
+ @param active layer is active, will be rendered only if True
+ @param hidden layer is hidden, won't be listed in Layer Manager if True
+ @param opacity layer opacity <0;1>
+ """
+ Layer.__init__(self, ltype, cmd, Map, name,
+ active, hidden, opacity)
+
+ def GetMapset(self):
+ """!Get mapset of map layer
+
+ @return mapset name
+ @return '' on error (no name given)
+ """
+ if not self.name:
+ return ''
+
+ try:
+ return self.name.split('@')[1]
+ except IndexError:
+ return self.name
+
+class Overlay(Layer):
+ def __init__(self, id, ltype, cmd, Map,
+ active = True, hidden = True, opacity = 1.0):
+ """!Represents overlay displayed in map canvas
+
+ @param id overlay id (for PseudoDC)
+ @param type overlay type ('barscale', 'legend', etc.)
+ @param cmd GRASS command to render overlay,
+ given as list, e.g. ['d.legend', 'map=elevation at PERMANENT']
+ @param Map render.Map instance
+ @param active layer is active, will be rendered only if True
+ @param hidden layer is hidden, won't be listed in Layer Manager if True
+ @param opacity layer opacity <0;1>
+ """
+ Layer.__init__(self, 'overlay', cmd, Map, ltype,
+ active, hidden, opacity)
+ self.id = id
+
+class Map(object):
+ def __init__(self, gisrc = None):
+ """!Map composition (stack of map layers and overlays)
+
+ @param gisrc alternative gisrc (used eg. by georectifier)
+ """
+ # region/extent settigns
+ self.wind = dict() # WIND settings (wind file)
+ self.region = dict() # region settings (g.region)
+ self.width = 640 # map width
+ self.height = 480 # map height
+
+ # list of layers
+ self.layers = list() # stack of available GRASS layer
+
+ self.overlays = list() # stack of available overlays
+ self.ovlookup = dict() # lookup dictionary for overlay items and overlays
+
+ # environment settings
+ self.env = dict()
+
+ # path to external gisrc
+ self.gisrc = gisrc
+
+ # generated file for g.pnmcomp output for rendering the map
+ self.mapfile = grass.tempfile(create = False) + '.ppm'
+
+ # setting some initial env. variables
+ self._initGisEnv() # g.gisenv
+ self.GetWindow()
+
+ # receiver of events
+ self.receiver = None
+
+ # GRASS environment variable (for rendering)
+ self.env = {"GRASS_BACKGROUNDCOLOR" : "FFFFFF",
+ "GRASS_COMPRESSION" : "0",
+ "GRASS_TRUECOLOR" : "TRUE",
+ "GRASS_TRANSPARENT" : "TRUE",
+ "GRASS_PNG_READ" : "FALSE",
+ }
+
+ for k, v in self.env.iteritems():
+ os.environ[k] = v
+
+ # projection info
+ self.projinfo = self._projInfo()
+
+ # is some layer being downloaded?
+ self.downloading = False
+
+ def _runCommand(self, cmd, **kwargs):
+ """!Run command in environment defined by self.gisrc if
+ defined"""
+ # use external gisrc if defined
+ gisrc_orig = os.getenv("GISRC")
+ if self.gisrc:
+ os.environ["GISRC"] = self.gisrc
+
+ ret = cmd(**kwargs)
+
+ # back to original gisrc
+ if self.gisrc:
+ os.environ["GISRC"] = gisrc_orig
+
+ return ret
+
+ def _initGisEnv(self):
+ """!Stores GRASS variables (g.gisenv) to self.env variable
+ """
+ if not os.getenv("GISBASE"):
+ sys.exit(_("GISBASE not set. You must be in GRASS GIS to run this program."))
+
+ self.env = self._runCommand(grass.gisenv)
+
+ def GetProjInfo(self):
+ """!Get projection info"""
+ return self.projinfo
+
+ def _projInfo(self):
+ """!Return region projection and map units information
+ """
+ projinfo = dict()
+ if not grass.find_program('g.proj', ['--help']):
+ sys.exit(_("GRASS module '%s' not found. Unable to start map "
+ "display window.") % 'g.proj')
+
+ ret = self._runCommand(RunCommand, prog = 'g.proj',
+ read = True, flags = 'p')
+
+ if not ret:
+ return projinfo
+
+ for line in ret.splitlines():
+ if ':' in line:
+ key, val = map(lambda x: x.strip(), line.split(':'))
+ if key in ['units']:
+ val = val.lower()
+ projinfo[key] = val
+ elif "XY location (unprojected)" in line:
+ projinfo['proj'] = 'xy'
+ projinfo['units'] = ''
+ break
+
+ return projinfo
+
+ def GetWindow(self):
+ """!Read WIND file and set up self.wind dictionary"""
+ # FIXME: duplicated region WIND == g.region (at least some values)
+ filename = os.path.join (self.env['GISDBASE'],
+ self.env['LOCATION_NAME'],
+ self.env['MAPSET'],
+ "WIND")
+ try:
+ windfile = open (filename, "r")
+ except IOError, e:
+ sys.exit(_("Error: Unable to open '%(file)s'. Reason: %(ret)s. wxGUI exited.\n") % \
+ { 'file' : filename, 'ret' : e})
+
+ for line in windfile.readlines():
+ line = line.strip()
+ key, value = line.split(":", 1)
+ self.wind[key.strip()] = value.strip()
+
+ windfile.close()
+
+ return self.wind
+
+ def AdjustRegion(self):
+ """!Adjusts display resolution to match monitor size in
+ pixels. Maintains constant display resolution, not related to
+ computational region. Do NOT use the display resolution to set
+ computational resolution. Set computational resolution through
+ g.region.
+ """
+ mapwidth = abs(self.region["e"] - self.region["w"])
+ mapheight = abs(self.region['n'] - self.region['s'])
+
+ self.region["nsres"] = mapheight / self.height
+ self.region["ewres"] = mapwidth / self.width
+ self.region['rows'] = round(mapheight / self.region["nsres"])
+ self.region['cols'] = round(mapwidth / self.region["ewres"])
+ self.region['cells'] = self.region['rows'] * self.region['cols']
+
+ Debug.msg (3, "Map.AdjustRegion(): %s" % self.region)
+
+ return self.region
+
+ def AlignResolution(self):
+ """!Sets display extents to even multiple of current
+ resolution defined in WIND file from SW corner. This must be
+ done manually as using the -a flag can produce incorrect
+ extents.
+ """
+ # new values to use for saving to region file
+ new = {}
+ n = s = e = w = 0.0
+ nsres = ewres = 0.0
+
+ # Get current values for region and display
+ reg = self.GetRegion()
+ nsres = reg['nsres']
+ ewres = reg['ewres']
+
+ n = float(self.region['n'])
+ s = float(self.region['s'])
+ e = float(self.region['e'])
+ w = float(self.region['w'])
+
+ # Calculate rows, columns, and extents
+ new['rows'] = math.fabs(round((n-s)/nsres))
+ new['cols'] = math.fabs(round((e-w)/ewres))
+
+ # Calculate new extents
+ new['s'] = nsres * round(s / nsres)
+ new['w'] = ewres * round(w / ewres)
+ new['n'] = new['s'] + (new['rows'] * nsres)
+ new['e'] = new['w'] + (new['cols'] * ewres)
+
+ return new
+
+ def AlignExtentFromDisplay(self):
+ """!Align region extent based on display size from center
+ point"""
+ # calculate new bounding box based on center of display
+ if self.region["ewres"] > self.region["nsres"]:
+ res = self.region["ewres"]
+ else:
+ res = self.region["nsres"]
+
+ Debug.msg(3, "Map.AlignExtentFromDisplay(): width=%d, height=%d, res=%f, center=%f,%f" % \
+ (self.width, self.height, res, self.region['center_easting'],
+ self.region['center_northing']))
+
+ ew = (self.width / 2) * res
+ ns = (self.height / 2) * res
+
+ self.region['n'] = self.region['center_northing'] + ns
+ self.region['s'] = self.region['center_northing'] - ns
+ self.region['e'] = self.region['center_easting'] + ew
+ self.region['w'] = self.region['center_easting'] - ew
+
+ # LL locations
+ if self.projinfo['proj'] == 'll':
+ self.region['n'] = min(self.region['n'], 90.0)
+ self.region['s'] = max(self.region['s'], -90.0)
+
+ def ChangeMapSize(self, (width, height)):
+ """!Change size of rendered map.
+
+ @param width,height map size given as tuple
+ """
+ try:
+ self.width = int(width)
+ self.height = int(height)
+ if self.width < 1 or self.height < 1:
+ sys.stderr.write(_("Invalid map size %d,%d\n") % (self.width, self.height))
+ raise ValueError
+ except ValueError:
+ self.width = 640
+ self.height = 480
+
+ Debug.msg(2, "Map.ChangeMapSize(): width=%d, height=%d" % \
+ (self.width, self.height))
+
+ def GetRegion(self, rast = [], zoom = False, vect = [], regionName = None,
+ n = None, s = None, e = None, w = None, default = False,
+ update = False, add3d = False):
+ """!Get region settings (g.region -upgc)
+
+ Optionally extent, raster or vector map layer can be given.
+
+ @param rast list of raster maps
+ @param zoom zoom to raster map (ignore NULLs)
+ @param vect list of vector maps
+ @param regionName named region or None
+ @param n,s,e,w force extent
+ @param default force default region settings
+ @param update if True update current display region settings
+ @param add3d add 3d region settings
+
+ @return region settings as dictionary, e.g. {
+ 'n':'4928010', 's':'4913700', 'w':'589980',...}
+
+ @see GetCurrentRegion()
+ """
+ region = {}
+
+ tmpreg = os.getenv("GRASS_REGION")
+ if tmpreg:
+ del os.environ["GRASS_REGION"]
+
+ # use external gisrc if defined
+ gisrc_orig = os.getenv("GISRC")
+ if self.gisrc:
+ os.environ["GISRC"] = self.gisrc
+
+ # do not update & shell style output
+ cmd = {}
+ cmd['flags'] = 'ugpc'
+
+ if default:
+ cmd['flags'] += 'd'
+
+ if add3d:
+ cmd['flags'] += '3'
+
+ if regionName:
+ cmd['region'] = regionName
+
+ if n:
+ cmd['n'] = n
+ if s:
+ cmd['s'] = s
+ if e:
+ cmd['e'] = e
+ if w:
+ cmd['w'] = w
+
+ if rast:
+ if zoom:
+ cmd['zoom'] = rast[0]
+ else:
+ cmd['rast'] = ','.join(rast)
+
+ if vect:
+ cmd['vect'] = ','.join(vect)
+
+ ret, reg, msg = RunCommand('g.region',
+ read = True,
+ getErrorMsg = True,
+ **cmd)
+
+ if ret != 0:
+ if rast:
+ message = _("Unable to zoom to raster map <%s>.") % rast[0] + \
+ "\n\n" + _("Details:") + " %s" % msg
+ elif vect:
+ message = _("Unable to zoom to vector map <%s>.") % vect[0] + \
+ "\n\n" + _("Details:") + " %s" % msg
+ else:
+ message = _("Unable to get current geographic extent. "
+ "Force quiting wxGUI. Please manually run g.region to "
+ "fix the problem.")
+ GError(message)
+ return self.region
+
+ for r in reg.splitlines():
+ key, val = r.split("=", 1)
+ try:
+ region[key] = float(val)
+ except ValueError:
+ region[key] = val
+
+ # back to original gisrc
+ if self.gisrc:
+ os.environ["GISRC"] = gisrc_orig
+
+ # restore region
+ if tmpreg:
+ os.environ["GRASS_REGION"] = tmpreg
+
+ Debug.msg (3, "Map.GetRegion(): %s" % region)
+
+ if update:
+ self.region = region
+
+ return region
+
+ def GetCurrentRegion(self):
+ """!Get current display region settings
+
+ @see GetRegion()
+ """
+ return self.region
+
+ def SetRegion(self, windres = False, windres3 = False):
+ """!Render string for GRASS_REGION env. variable, so that the
+ images will be rendered from desired zoom level.
+
+ @param windres uses resolution from WIND file rather than
+ display (for modules that require set resolution like
+ d.rast.num)
+
+ @return String usable for GRASS_REGION variable or None
+ """
+ grass_region = ""
+
+ if windres:
+ compRegion = self.GetRegion(add3d = windres3)
+ region = copy.copy(self.region)
+ for key in ('nsres', 'ewres', 'cells'):
+ region[key] = compRegion[key]
+ if windres3:
+ for key in ('nsres3', 'ewres3', 'tbres', 'cells3',
+ 'cols3', 'rows3', 'depths'):
+ if key in compRegion:
+ region[key] = compRegion[key]
+
+ else:
+ # adjust region settings to match monitor
+ region = self.AdjustRegion()
+
+ # read values from wind file
+ try:
+ for key in self.wind.keys():
+
+ if key == 'north':
+ grass_region += "north: %s; " % \
+ (region['n'])
+ continue
+ elif key == "south":
+ grass_region += "south: %s; " % \
+ (region['s'])
+ continue
+ elif key == "east":
+ grass_region += "east: %s; " % \
+ (region['e'])
+ continue
+ elif key == "west":
+ grass_region += "west: %s; " % \
+ (region['w'])
+ continue
+ elif key == "e-w resol":
+ grass_region += "e-w resol: %f; " % \
+ (region['ewres'])
+ continue
+ elif key == "n-s resol":
+ grass_region += "n-s resol: %f; " % \
+ (region['nsres'])
+ continue
+ elif key == "cols":
+ if windres:
+ continue
+ grass_region += 'cols: %d; ' % \
+ region['cols']
+ continue
+ elif key == "rows":
+ if windres:
+ continue
+ grass_region += 'rows: %d; ' % \
+ region['rows']
+ continue
+ elif key == "n-s resol3" and windres3:
+ grass_region += "n-s resol3: %f; " % \
+ (region['nsres3'])
+ elif key == "e-w resol3" and windres3:
+ grass_region += "e-w resol3: %f; " % \
+ (region['ewres3'])
+ elif key == "t-b resol" and windres3:
+ grass_region += "t-b resol: %f; " % \
+ (region['tbres'])
+ elif key == "cols3" and windres3:
+ grass_region += "cols3: %d; " % \
+ (region['cols3'])
+ elif key == "rows3" and windres3:
+ grass_region += "rows3: %d; " % \
+ (region['rows3'])
+ elif key == "depths" and windres3:
+ grass_region += "depths: %d; " % \
+ (region['depths'])
+ else:
+ grass_region += key + ": " + self.wind[key] + "; "
+
+ Debug.msg (3, "Map.SetRegion(): %s" % grass_region)
+
+ return grass_region
+
+ except:
+ return None
+
+ def GetListOfLayers(self, ltype = None, mapset = None, name = None,
+ active = None, hidden = None):
+ """!Returns list of layers of selected properties or list of
+ all layers.
+
+ @param ltype layer type, e.g. raster/vector/wms/overlay (value or tuple of values)
+ @param mapset all layers from given mapset (only for maplayers)
+ @param name all layers with given name
+ @param active only layers with 'active' attribute set to True or False
+ @param hidden only layers with 'hidden' attribute set to True or False
+
+ @return list of selected layers
+ """
+ selected = []
+
+ if type(ltype) == types.StringType:
+ one_type = True
+ else:
+ one_type = False
+
+ if one_type and ltype == 'overlay':
+ llist = self.overlays
+ else:
+ llist = self.layers
+
+ # ["raster", "vector", "wms", ... ]
+ for layer in llist:
+ # specified type only
+ if ltype != None:
+ if one_type and layer.type != ltype:
+ continue
+ elif not one_type and layer.type not in ltype:
+ continue
+
+ # mapset
+ if (mapset != None and ltype != 'overlay') and \
+ layer.GetMapset() != mapset:
+ continue
+
+ # name
+ if name != None and layer.name != name:
+ continue
+
+ # hidden and active layers
+ if active != None and \
+ hidden != None:
+ if layer.active == active and \
+ layer.hidden == hidden:
+ selected.append(layer)
+
+ # active layers
+ elif active != None:
+ if layer.active == active:
+ selected.append(layer)
+
+ # hidden layers
+ elif hidden != None:
+ if layer.hidden == hidden:
+ selected.append(layer)
+
+ # all layers
+ else:
+ selected.append(layer)
+
+ Debug.msg (3, "Map.GetListOfLayers(): numberof=%d" % len(selected))
+
+ return selected
+
+ def _renderLayers(self, force = False, overlaysOnly = False):
+ """!Render all map layers into files
+
+ @param force True to force rendering
+ @param overlaysOnly True to render only overlays
+
+ @return list of maps, masks and opacities
+ """
+ maps = list()
+ masks = list()
+ opacities = list()
+ # render map layers
+ if overlaysOnly:
+ layers = self.overlays
+ else:
+ layers = self.layers + self.overlays
+
+ self.downloading = False
+ if self.receiver:
+ event = wxUpdateProgressBar(layer = None, map = self)
+ self.receiver.GetEventHandler().ProcessEvent(event)
+ for layer in layers:
+ # skip non-active map layers
+ if not layer or not layer.active:
+ continue
+
+ # render
+ if force or layer.forceRender:
+ if not layer.Render():
+ continue
+
+ if layer.IsDownloading():
+ self.downloading = True
+ if self.receiver:
+ event = wxUpdateProgressBar(layer = layer, map = self)
+ self.receiver.GetEventHandler().ProcessEvent(event)
+
+ # skip map layers when rendering fails
+ if not os.path.exists(layer.mapfile):
+ continue
+
+ # add image to compositing list
+ if layer.type != "overlay":
+ maps.append(layer.mapfile)
+ masks.append(layer.maskfile)
+ opacities.append(str(layer.opacity))
+
+ Debug.msg(3, "Map.Render() type=%s, layer=%s " % (layer.type, layer.name))
+
+ return maps, masks, opacities
+
+ def GetMapsMasksAndOpacities(self, force, windres):
+ """!
+ Used by Render function.
+
+ @return maps, masks, opacities
+ """
+ return self._renderLayers(force)
+
+ def Render(self, force = False, windres = False):
+ """!Creates final image composite
+
+ This function can conditionaly use high-level tools, which
+ should be avaliable in wxPython library
+
+ @param force force rendering
+ @param windres use region resolution (True) otherwise display resolution
+
+ @return name of file with rendered image or None
+ """
+ wx.BeginBusyCursor()
+ # use external gisrc if defined
+ gisrc_orig = os.getenv("GISRC")
+ if self.gisrc:
+ os.environ["GISRC"] = self.gisrc
+
+ tmp_region = os.getenv("GRASS_REGION")
+ os.environ["GRASS_REGION"] = self.SetRegion(windres)
+ os.environ["GRASS_WIDTH"] = str(self.width)
+ os.environ["GRASS_HEIGHT"] = str(self.height)
+ driver = UserSettings.Get(group = 'display', key = 'driver', subkey = 'type')
+ if driver == 'png':
+ os.environ["GRASS_RENDER_IMMEDIATE"] = "png"
+ else:
+ os.environ["GRASS_RENDER_IMMEDIATE"] = "cairo"
+
+ maps, masks, opacities = self.GetMapsMasksAndOpacities(force, windres)
+
+ # ugly hack for MSYS
+ if sys.platform != 'win32':
+ mapstr = ",".join(maps)
+ maskstr = ",".join(masks)
+ else:
+ mapstr = ""
+ for item in maps:
+ mapstr += item.replace('\\', '/')
+ mapstr = mapstr.rstrip(',')
+ maskstr = ""
+ for item in masks:
+ maskstr += item.replace('\\', '/')
+ maskstr = maskstr.rstrip(',')
+
+ # run g.pngcomp to get composite image
+ bgcolor = ':'.join(map(str, UserSettings.Get(group = 'display', key = 'bgcolor',
+ subkey = 'color')))
+
+ if maps:
+ ret, msg = RunCommand('g.pnmcomp',
+ getErrorMsg = True,
+ overwrite = True,
+ input = '%s' % ",".join(maps),
+ mask = '%s' % ",".join(masks),
+ opacity = '%s' % ",".join(opacities),
+ bgcolor = bgcolor,
+ width = self.width,
+ height = self.height,
+ output = self.mapfile)
+
+ if ret != 0:
+ print >> sys.stderr, _("ERROR: Rendering failed. Details: %s") % msg
+ wx.EndBusyCursor()
+ return None
+
+ Debug.msg (3, "Map.Render() force=%s file=%s" % (force, self.mapfile))
+
+ # back to original region
+ if tmp_region:
+ os.environ["GRASS_REGION"] = tmp_region
+ else:
+ del os.environ["GRASS_REGION"]
+
+ # back to original gisrc
+ if self.gisrc:
+ os.environ["GISRC"] = gisrc_orig
+
+ wx.EndBusyCursor()
+ if not maps:
+ return None
+
+ return self.mapfile
+
+ def AddMapLayer(self, mlayer, render = False, pos = -1):
+ wx.BeginBusyCursor()
+ # opacity must be <0;1>
+ if mlayer.opacity < 0:
+ opacity = 0
+ elif mlayer.opacity > 1:
+ opacity = 1
+
+
+
+
+ # add maplayer to the list of layers
+ if pos > -1:
+ self.layers.insert(pos, mlayer)
+ else:
+ self.layers.append(mlayer)
+
+ Debug.msg (3, "Map.AddLayer(): layer=%s" % mlayer.name)
+ if render:
+ if not mlayer.Render():
+ raise GException(_("Unable to render map layer <%s>.") % mlayer.name)
+
+ wx.EndBusyCursor()
+
+ return mlayer
+
+ def AddLayer(self, ltype, command, name = None,
+ active = True, hidden = False, opacity = 1.0, render = False,
+ pos = -1):
+ """!Adds generic map layer to list of layers
+
+ @param ltype layer type ('raster', 'vector', etc.)
+ @param command GRASS command given as list
+ @param name layer name
+ @param active layer render only if True
+ @param hidden layer not displayed in layer tree if True
+ @param opacity opacity level range from 0(transparent) - 1(not transparent)
+ @param render render an image if True
+ @param pos position in layer list (-1 for append)
+
+ @return new layer on success
+ @return None on failure
+ """
+ wx.BeginBusyCursor()
+ # opacity must be <0;1>
+ if opacity < 0:
+ opacity = 0
+ elif opacity > 1:
+ opacity = 1
+
+
+
+ layer = MapLayer(ltype = ltype, name = name, cmd = command, Map = self,
+ active = active, hidden = hidden, opacity = opacity)
+
+ # add maplayer to the list of layers
+ if pos > -1:
+ self.layers.insert(pos, layer)
+ else:
+ self.layers.append(layer)
+
+ Debug.msg (3, "Map.AddLayer(): layer=%s" % layer.name)
+ if render:
+ if not layer.Render():
+ raise GException(_("Unable to render map layer <%s>.") % name)
+
+ wx.EndBusyCursor()
+
+ return layer
+
+ def DeleteAllLayers(self, overlay = False):
+ """!Delete all layers
+
+ @param overlay True to delete also overlayes
+ """
+ self.layers = []
+ if overlay:
+ self.overlays = []
+
+ def DeleteLayer(self, layer, overlay = False):
+ """!Removes layer from list of layers
+
+ @param layer layer instance in layer tree
+ @param overlay delete overlay (use self.DeleteOverlay() instead)
+
+ @return removed layer on success or None
+ """
+ Debug.msg (3, "Map.DeleteLayer(): name=%s" % layer.name)
+
+ if overlay:
+ list = self.overlays
+ else:
+ list = self.layers
+
+ if layer in list:
+ if layer.mapfile:
+ base = os.path.split(layer.mapfile)[0]
+ mapfile = os.path.split(layer.mapfile)[1]
+ tempbase = mapfile.split('.')[0]
+ if base == '' or tempbase == '':
+ return None
+ basefile = os.path.join(base, tempbase) + r'.*'
+ for f in glob.glob(basefile):
+ os.remove(f)
+ list.remove(layer)
+
+ return layer
+
+ return None
+
+ def ReorderLayers(self, layerList):
+ """!Reorder list to match layer tree
+
+ @param layerList list of layers
+ """
+ self.layers = layerList
+
+ layerNameList = ""
+ for layer in self.layers:
+ if layer.GetName():
+ layerNameList += layer.GetName() + ','
+ Debug.msg (4, "Map.ReoderLayers(): layers=%s" % \
+ (layerNameList))
+
+ def ChangeLayer(self, layer, render = False, **kargs):
+ """!Change map layer properties
+
+ @param layer map layer instance
+ @param ltype layer type ('raster', 'vector', etc.)
+ @param command GRASS command given as list
+ @param name layer name
+ @param active layer render only if True
+ @param hidden layer not displayed in layer tree if True
+ @param opacity opacity level range from 0(transparent) - 1(not transparent)
+ @param render render an image if True
+ """
+ Debug.msg (3, "Map.ChangeLayer(): layer=%s" % layer.name)
+
+ if 'ltype' in kargs:
+ layer.SetType(kargs['ltype']) # check type
+
+
+ print kargs['command']
+ print "yyy"
+ if 'command' in kargs:
+ layer.SetCmd(kargs['command'])
+
+ if 'name' in kargs:
+ layer.SetName(kargs['name'])
+
+ if 'active' in kargs:
+ layer.SetActive(kargs['active'])
+
+ if 'hidden' in kargs:
+ layer.SetHidden(kargs['hidden'])
+
+ if 'opacity' in kargs:
+ layer.SetOpacity(kargs['opacity'])
+
+ if render and not layer.Render():
+ raise GException(_("Unable to render map layer <%s>.") %
+ layer.GetName())
+
+ return layer
+
+ def ChangeOpacity(self, layer, opacity):
+ """!Changes opacity value of map layer
+
+ @param layer layer instance in layer tree
+ @param opacity opacity level <0;1>
+ """
+ # opacity must be <0;1>
+ if opacity < 0: opacity = 0
+ elif opacity > 1: opacity = 1
+
+ layer.opacity = opacity
+ Debug.msg (3, "Map.ChangeOpacity(): layer=%s, opacity=%f" % \
+ (layer.name, layer.opacity))
+
+ def ChangeLayerActive(self, layer, active):
+ """!Enable or disable map layer
+
+ @param layer layer instance in layer tree
+ @param active to be rendered (True)
+ """
+ layer.active = active
+
+ Debug.msg (3, "Map.ChangeLayerActive(): name='%s' -> active=%d" % \
+ (layer.name, layer.active))
+
+ def ChangeLayerName (self, layer, name):
+ """!Change name of the layer
+
+ @param layer layer instance in layer tree
+ @param name layer name to set up
+ """
+ Debug.msg (3, "Map.ChangeLayerName(): from=%s to=%s" % \
+ (layer.name, name))
+ layer.name = name
+
+ def RemoveLayer(self, name = None, id = None):
+ """!Removes layer from layer list
+
+ Layer is defined by name at mapset or id.
+
+ @param name layer name (must be unique)
+ @param id layer index in layer list def __init__(self, targetFile, region, bandsNum, gdalDriver, fillValue = None):
+
+ @return removed layer on success
+ @return None on failure
+ """
+ # delete by name
+ if name:
+ retlayer = None
+ for layer in self.layers:
+ if layer.name == name:
+ retlayer = layer
+ os.remove(layer.mapfile)
+ os.remove(layer.maskfile)
+ self.layers.remove(layer)
+ return retlayer
+ # del by id
+ elif id != None:
+ return self.layers.pop(id)
+
+ return None
+
+ def GetLayerIndex(self, layer, overlay = False):
+ """!Get index of layer in layer list.
+
+ @param layer layer instace in layer tree
+ @param overlay use list of overlays instead
+
+ @return layer index
+ @return -1 if layer not found
+ """
+ if overlay:
+ list = self.overlays
+ else:
+ list = self.layers
+
+ if layer in list:
+ return list.index(layer)
+
+ return -1
+
+ def AddOverlay(self, id, ltype, command,
+ active = True, hidden = True, opacity = 1.0, render = False):
+ """!Adds overlay (grid, barscale, legend, etc.) to list of
+ overlays
+
+ @param id overlay id (PseudoDC)
+ @param ltype overlay type (barscale, legend)
+ @param command GRASS command to render overlay
+ @param active overlay activated (True) or disabled (False)
+ @param hidden overlay is not shown in layer tree (if True)
+ @param render render an image (if True)
+
+ @return new layer on success
+ @return None on failure
+ """
+ Debug.msg (2, "Map.AddOverlay(): cmd=%s, render=%d" % (command, render))
+ overlay = Overlay(id = id, ltype = ltype, cmd = command, Map = self,
+ active = active, hidden = hidden, opacity = opacity)
+
+ # add maplayer to the list of layers
+ self.overlays.append(overlay)
+
+ if render and command != '' and not overlay.Render():
+ raise GException(_("Unable to render overlay <%s>.") %
+ ltype)
+
+ return self.overlays[-1]
+
+ def ChangeOverlay(self, id, render = False, **kargs):
+ """!Change overlay properities
+
+ Add new overlay if overlay with 'id' doesn't exist.
+
+ @param id overlay id (PseudoDC)
+ @param ltype overlay ltype (barscale, legend)
+ @param command GRASS command to render overlay
+ @param active overlay activated (True) or disabled (False)
+ @param hidden overlay is not shown in layer tree (if True)
+ @param render render an image (if True)
+
+ @return new layer on success
+ """
+ overlay = self.GetOverlay(id, list = False)
+ if overlay is None:
+ overlay = Overlay(id, ltype = None, cmd = None)
+
+ if 'ltype' in kargs:
+ overlay.SetName(kargs['ltype']) # ltype -> overlay
+
+ if 'command' in kargs:
+ overlay.SetCmd(kargs['command'])
+
+ if 'active' in kargs:
+ overlay.SetActive(kargs['active'])
+
+ if 'hidden' in kargs:
+ overlay.SetHidden(kargs['hidden'])
+
+ if 'opacity' in kargs:
+ overlay.SetOpacity(kargs['opacity'])
+
+ if render and overlay.GetCmd() != [] and not overlay.Render():
+ raise GException(_("Unable to render overlay <%s>.") %
+ overlay.GetType())
+
+ return overlay
+
+ def GetOverlay(self, id, list = False):
+ """!Return overlay(s) with 'id'
+
+ @param id overlay id
+ @param list return list of overlays of True
+ otherwise suppose 'id' to be unique
+
+ @return list of overlays (list=True)
+ @return overlay (list=False)
+ @return None (list=False) if no overlay or more overlays found
+ """
+ ovl = []
+ for overlay in self.overlays:
+ if overlay.id == id:
+ ovl.append(overlay)
+
+ if not list:
+ if len(ovl) != 1:
+ return None
+ else:
+ return ovl[0]
+
+ return ovl
+
+ def DeleteOverlay(self, overlay):
+ """!Delete overlay
+
+ @param overlay overlay layer
+
+ @return removed overlay on success or None
+ """
+ return self.DeleteLayer(overlay, overlay = True)
+
+ def _clean(self, llist):
+ for layer in llist:
+ if layer.maskfile:
+ grass.try_remove(layer.maskfile)
+ if layer.mapfile:
+ grass.try_remove(layer.mapfile)
+ llist.remove(layer)
+
+ def Clean(self):
+ """!Clean layer stack - go trough all layers and remove them
+ from layer list.
+
+ Removes also mapfile and maskfile.
+ """
+ self._clean(self.layers)
+ self._clean(self.overlays)
+
+ def ReverseListOfLayers(self):
+ """!Reverse list of layers"""
+ return self.layers.reverse()
+
+ def RenderOverlays(self, force):
+ """!Render overlays only (for nviz)"""
+ for layer in self.overlays:
+ if force or layer.forceRender:
+ layer.Render()
+
+ def GetReceiver(self):
+ """!Get event receiver"""
+ return self.receiver
+
+ def SetReceiver(self, receiver):
+ """!Set events receiver
+
+ @todo If it will be needed to change receiver, take care of running threads.
+ """
+ self.receiver = receiver
+ for l in self.overlays + self.layers:
+ if l.GetRenderMgr():
+ l.GetRenderMgr().SetReceiver(self.receiver)
+
+ def AbortAllThreads(self):
+ """!Abort all layers threads e. g. donwloading data"""
+ for l in self.layers + self.overlays:
+ l.AbortThread()
More information about the grass-commit
mailing list