| 1 | """
|
|---|
| 2 | @package render
|
|---|
| 3 |
|
|---|
| 4 | Rendering map layers into image
|
|---|
| 5 |
|
|---|
| 6 | Classes:
|
|---|
| 7 | - MapLayer
|
|---|
| 8 | - Map
|
|---|
| 9 |
|
|---|
| 10 | C) 2006-2008 by the GRASS Development Team
|
|---|
| 11 | This program is free software under the GNU General Public
|
|---|
| 12 | License (>=v2). Read the file COPYING that comes with GRASS
|
|---|
| 13 | for details.
|
|---|
| 14 |
|
|---|
| 15 | @author Michael Barton, Jachym Cepicky, Martin Landa
|
|---|
| 16 |
|
|---|
| 17 | @date 2006-2008
|
|---|
| 18 | """
|
|---|
| 19 |
|
|---|
| 20 | import os
|
|---|
| 21 | import sys
|
|---|
| 22 | import glob
|
|---|
| 23 | import math
|
|---|
| 24 | try:
|
|---|
| 25 | import subprocess
|
|---|
| 26 | except:
|
|---|
| 27 | compatPath = os.path.join(globalvar.ETCWXDIR, "compat")
|
|---|
| 28 | sys.path.append(compatPath)
|
|---|
| 29 | import subprocess
|
|---|
| 30 |
|
|---|
| 31 | import wx
|
|---|
| 32 |
|
|---|
| 33 | import globalvar
|
|---|
| 34 | import utils
|
|---|
| 35 | import gcmd
|
|---|
| 36 | from debug import Debug as Debug
|
|---|
| 37 |
|
|---|
| 38 | #
|
|---|
| 39 | # use g.pnmcomp for creating image composition or
|
|---|
| 40 | # wxPython functionality
|
|---|
| 41 | #
|
|---|
| 42 | USE_GPNMCOMP = True
|
|---|
| 43 |
|
|---|
| 44 | class MapLayer(object):
|
|---|
| 45 | """Stores information about map layers or overlays to be displayed"""
|
|---|
| 46 | def __init__(self, type, cmd, name=None,
|
|---|
| 47 | active=True, hidden=False, opacity=1.0):
|
|---|
| 48 | """
|
|---|
| 49 | @param type layer type (raster, vector, overlay, command, etc.)
|
|---|
| 50 | @param cmd GRASS command for rendering layer, given as list, e.g. ['d.rast', 'map=elevation@PERMANENT']
|
|---|
| 51 | @param name layer name, e.g. 'elevation@PERMANENT'
|
|---|
| 52 | @param active layer is active, will be rendered only if True
|
|---|
| 53 | @param hidden layer is hidden, won't be listed in Layer Manager if True
|
|---|
| 54 | @param opacity layer opacity <0;1>
|
|---|
| 55 | """
|
|---|
| 56 | self.type = type
|
|---|
| 57 | self.name = name
|
|---|
| 58 | self.cmdlist = cmd
|
|---|
| 59 |
|
|---|
| 60 | self.active = active
|
|---|
| 61 | self.hidden = hidden
|
|---|
| 62 | self.opacity = opacity
|
|---|
| 63 |
|
|---|
| 64 | Debug.msg (3, "MapLayer.__init__(): type=%s, cmd='%s', name=%s, " \
|
|---|
| 65 | "active=%d, opacity=%d, hidden=%d" % \
|
|---|
| 66 | (self.type, self.GetCmd(string=True), self.name, self.active,
|
|---|
| 67 | self.opacity, self.hidden))
|
|---|
| 68 |
|
|---|
| 69 | # generated file for layer
|
|---|
| 70 | gtemp = utils.GetTempfile()
|
|---|
| 71 | self.maskfile = gtemp + ".pgm"
|
|---|
| 72 | if self.type == "overlay":
|
|---|
| 73 | self.mapfile = gtemp + ".png"
|
|---|
| 74 | else:
|
|---|
| 75 | self.mapfile = gtemp + ".ppm"
|
|---|
| 76 |
|
|---|
| 77 | def __del__(self):
|
|---|
| 78 | Debug.msg (3, "MapLayer.__del__(): layer=%s, cmd='%s'" %
|
|---|
| 79 | (self.name, self.GetCmd(string=True)))
|
|---|
| 80 |
|
|---|
| 81 | def Render(self):
|
|---|
| 82 | """Render map layer to image
|
|---|
| 83 |
|
|---|
| 84 | @return name of file with rendered image or None
|
|---|
| 85 | """
|
|---|
| 86 | if len(self.cmdlist) == 0:
|
|---|
| 87 | return
|
|---|
| 88 |
|
|---|
| 89 | Debug.msg (3, "MapLayer.Render(): type=%s" % \
|
|---|
| 90 | (self.type))
|
|---|
| 91 |
|
|---|
| 92 | #
|
|---|
| 93 | # to be sure, set temporary file with layer and mask
|
|---|
| 94 | #
|
|---|
| 95 | gtemp = utils.GetTempfile()
|
|---|
| 96 | self.maskfile = gtemp + ".pgm"
|
|---|
| 97 | if self.type == 'overlay':
|
|---|
| 98 | self.mapfile = gtemp + ".png"
|
|---|
| 99 | else:
|
|---|
| 100 | self.mapfile = gtemp + ".ppm"
|
|---|
| 101 |
|
|---|
| 102 | #
|
|---|
| 103 | # prepare command for each layer
|
|---|
| 104 | #
|
|---|
| 105 | layertypes = ['raster', 'rgb', 'his', 'shaded', 'rastarrow', 'rastnum',
|
|---|
| 106 | 'vector','thememap','themechart',
|
|---|
| 107 | 'grid', 'geodesic', 'rhumb', 'labels',
|
|---|
| 108 | 'command',
|
|---|
| 109 | 'overlay']
|
|---|
| 110 |
|
|---|
| 111 | if self.type not in layertypes:
|
|---|
| 112 | raise gcmd.GStdError(_("<%(name)s>: layer type <%(type)s> is not supported yet.") % \
|
|---|
| 113 | {'type' : self.type, 'name' : self.name})
|
|---|
| 114 |
|
|---|
| 115 | #
|
|---|
| 116 | # start monitor
|
|---|
| 117 | #
|
|---|
| 118 | os.environ["GRASS_PNGFILE"] = self.mapfile
|
|---|
| 119 |
|
|---|
| 120 | #
|
|---|
| 121 | # execute command
|
|---|
| 122 | #
|
|---|
| 123 | try:
|
|---|
| 124 | runcmd = gcmd.Command(cmd=self.cmdlist + ['--q'],
|
|---|
| 125 | stderr=None)
|
|---|
| 126 | except gcmd.CmdError, e:
|
|---|
| 127 | print e
|
|---|
| 128 |
|
|---|
| 129 | if runcmd.returncode != 0:
|
|---|
| 130 | self.mapfile = None
|
|---|
| 131 | self.maskfile = None
|
|---|
| 132 | return None
|
|---|
| 133 |
|
|---|
| 134 | #
|
|---|
| 135 | # stop monitor
|
|---|
| 136 | #
|
|---|
| 137 | os.unsetenv("GRASS_PNGFILE")
|
|---|
| 138 |
|
|---|
| 139 | return self.mapfile
|
|---|
| 140 |
|
|---|
| 141 | def GetMapset(self):
|
|---|
| 142 | """
|
|---|
| 143 | @return mapset name of the layer
|
|---|
| 144 | """
|
|---|
| 145 | if not self.name:
|
|---|
| 146 | return ''
|
|---|
| 147 |
|
|---|
| 148 | try:
|
|---|
| 149 | return self.name.split('@')[1]
|
|---|
| 150 | except IndexError:
|
|---|
| 151 | return self.name
|
|---|
| 152 |
|
|---|
| 153 | def GetCmd(self, string=False):
|
|---|
| 154 | """
|
|---|
| 155 | @param string get command as string if True otherwise list
|
|---|
| 156 |
|
|---|
| 157 | @return command list/string
|
|---|
| 158 | """
|
|---|
| 159 | if string:
|
|---|
| 160 | return ' '.join(self.cmdlist)
|
|---|
| 161 | else:
|
|---|
| 162 | return self.cmdlist
|
|---|
| 163 |
|
|---|
| 164 | def GetOpacity(self, float=False):
|
|---|
| 165 | """
|
|---|
| 166 | Get opacity level
|
|---|
| 167 | @param float get opacity level in <0,1> otherwise <0,100>
|
|---|
| 168 |
|
|---|
| 169 | @return opacity level
|
|---|
| 170 | """
|
|---|
| 171 | if float:
|
|---|
| 172 | return self.opacity
|
|---|
| 173 |
|
|---|
| 174 | return int (self.opacity * 100)
|
|---|
| 175 |
|
|---|
| 176 | class Map(object):
|
|---|
| 177 | """
|
|---|
| 178 | Map composition (stack of map layers)
|
|---|
| 179 | """
|
|---|
| 180 | def __init__(self):
|
|---|
| 181 | #
|
|---|
| 182 | # region/extent settigns
|
|---|
| 183 | #
|
|---|
| 184 | self.wind = {} # WIND settings (wind file)
|
|---|
| 185 | self.region = {} # region settings (g.region)
|
|---|
| 186 | self.width = 640 # map width
|
|---|
| 187 | self.height = 480 # map height
|
|---|
| 188 |
|
|---|
| 189 | #
|
|---|
| 190 | # list of layers
|
|---|
| 191 | #
|
|---|
| 192 | self.layers = [] # stack of available GRASS layer
|
|---|
| 193 |
|
|---|
| 194 | self.overlays = [] # stack of available overlays
|
|---|
| 195 | self.ovlookup = {} # lookup dictionary for overlay items and overlays
|
|---|
| 196 |
|
|---|
| 197 | #
|
|---|
| 198 | # environment settings
|
|---|
| 199 | #
|
|---|
| 200 | self.env = {} # enviroment variables, like MAPSET, LOCATION_NAME, etc.
|
|---|
| 201 | self.verbosity = 0 # --q
|
|---|
| 202 |
|
|---|
| 203 | #
|
|---|
| 204 | # generated file for rendering the map
|
|---|
| 205 | #
|
|---|
| 206 | self.mapfile = utils.GetTempfile()
|
|---|
| 207 |
|
|---|
| 208 | # setting some initial env. variables
|
|---|
| 209 | self.InitGisEnv() # g.gisenv
|
|---|
| 210 | self.InitRegion()
|
|---|
| 211 | os.environ["GRASS_TRANSPARENT"] = "TRUE"
|
|---|
| 212 | os.environ["GRASS_BACKGROUNDCOLOR"] = "ffffff"
|
|---|
| 213 | os.environ["GRASS_HEIGHT"] = str(self.height)
|
|---|
| 214 | os.environ["GRASS_WIDTH"] = str(self.width)
|
|---|
| 215 | os.environ["GRASS_MESSAGE_FORMAT"] = "gui"
|
|---|
| 216 | os.environ["GRASS_PNG_AUTO_WRITE"] = "TRUE"
|
|---|
| 217 | os.environ["GRASS_TRUECOLOR"] = "TRUE"
|
|---|
| 218 | os.environ["GRASS_COMPRESSION"] = "0"
|
|---|
| 219 | os.environ["GRASS_VERBOSE"] = str(self.verbosity)
|
|---|
| 220 |
|
|---|
| 221 | def InitRegion(self):
|
|---|
| 222 | """
|
|---|
| 223 | Initialize current region settings.
|
|---|
| 224 |
|
|---|
| 225 | Set up 'self.region' using g.region command and
|
|---|
| 226 | self.wind according to the wind file.
|
|---|
| 227 |
|
|---|
| 228 | Adjust self.region based on map window size.
|
|---|
| 229 | """
|
|---|
| 230 |
|
|---|
| 231 | #
|
|---|
| 232 | # setting region ('g.region -upg')
|
|---|
| 233 | #
|
|---|
| 234 | self.region = self.GetRegion()
|
|---|
| 235 |
|
|---|
| 236 | #
|
|---|
| 237 | # read WIND file
|
|---|
| 238 | #
|
|---|
| 239 | self.GetWindow()
|
|---|
| 240 |
|
|---|
| 241 | #
|
|---|
| 242 | # setting resolution
|
|---|
| 243 | #
|
|---|
| 244 | self.SetRegion()
|
|---|
| 245 |
|
|---|
| 246 | def InitGisEnv(self):
|
|---|
| 247 | """
|
|---|
| 248 | Stores GRASS variables (g.gisenv) to self.env variable
|
|---|
| 249 | """
|
|---|
| 250 |
|
|---|
| 251 | if not os.getenv("GISBASE"):
|
|---|
| 252 | print >> sys.stderr, _("GISBASE not set. You must be in GRASS GIS to run this program.")
|
|---|
| 253 | sys.exit(1)
|
|---|
| 254 |
|
|---|
| 255 | gisenvCmd = gcmd.Command(["g.gisenv"])
|
|---|
| 256 |
|
|---|
| 257 | for line in gisenvCmd.ReadStdOutput():
|
|---|
| 258 | line = line.strip()
|
|---|
| 259 | key, val = line.split("=")
|
|---|
| 260 | val = val.replace(";","")
|
|---|
| 261 | val = val.replace("'","")
|
|---|
| 262 | self.env[key] = val
|
|---|
| 263 |
|
|---|
| 264 | def GetWindow(self):
|
|---|
| 265 | """Read WIND file and set up self.wind dictionary"""
|
|---|
| 266 | # FIXME: duplicated region WIND == g.region (at least some values)
|
|---|
| 267 | windfile = os.path.join (self.env['GISDBASE'],
|
|---|
| 268 | self.env['LOCATION_NAME'],
|
|---|
| 269 | self.env['MAPSET'],
|
|---|
| 270 | "WIND")
|
|---|
| 271 | try:
|
|---|
| 272 | windfile = open (windfile, "r")
|
|---|
| 273 | except StandardError, e:
|
|---|
| 274 | sys.stderr.write("%s %<s>: %s" % (_("Unable to open file"), windfile, e))
|
|---|
| 275 | sys.exit(1)
|
|---|
| 276 |
|
|---|
| 277 | for line in windfile.readlines():
|
|---|
| 278 | line = line.strip()
|
|---|
| 279 | key, value = line.split(":",1)
|
|---|
| 280 | key = key.strip()
|
|---|
| 281 | value = value.strip()
|
|---|
| 282 | self.wind[key] = value
|
|---|
| 283 |
|
|---|
| 284 | windfile.close()
|
|---|
| 285 |
|
|---|
| 286 | return self.wind
|
|---|
| 287 |
|
|---|
| 288 | def __adjustRegion(self):
|
|---|
| 289 | """
|
|---|
| 290 | Adjusts display resolution to match monitor size in pixels.
|
|---|
| 291 | Maintains constant display resolution, not related to computational
|
|---|
| 292 | region. Do NOT use the display resolution to set computational
|
|---|
| 293 | resolution. Set computational resolution through g.region.
|
|---|
| 294 | """
|
|---|
| 295 |
|
|---|
| 296 | mapwidth = abs(self.region["e"] - self.region["w"])
|
|---|
| 297 | mapheight = abs(self.region['n'] - self.region['s'])
|
|---|
| 298 |
|
|---|
| 299 | self.region["nsres"] = mapheight / self.height
|
|---|
| 300 | self.region["ewres"] = mapwidth / self.width
|
|---|
| 301 | self.region['rows'] = round(mapheight / self.region["nsres"])
|
|---|
| 302 | self.region['cols'] = round(mapwidth / self.region["ewres"])
|
|---|
| 303 | self.region['cells'] = self.region['rows'] * self.region['cols']
|
|---|
| 304 |
|
|---|
| 305 | Debug.msg (3, "Map.__adjustRegion(): %s" % self.region)
|
|---|
| 306 |
|
|---|
| 307 | return self.region
|
|---|
| 308 |
|
|---|
| 309 | def AlignResolution(self):
|
|---|
| 310 | """
|
|---|
| 311 | Sets display extents to even multiple of
|
|---|
| 312 | current resolution defined in WIND file from SW corner.
|
|---|
| 313 | This must be done manually as using the -a flag
|
|---|
| 314 | can produce incorrect extents.
|
|---|
| 315 | """
|
|---|
| 316 |
|
|---|
| 317 | # new values to use for saving to region file
|
|---|
| 318 | new = {}
|
|---|
| 319 | n = s = e = w = 0.0
|
|---|
| 320 | nwres = ewres = 0.0
|
|---|
| 321 |
|
|---|
| 322 | # Get current values for region and display
|
|---|
| 323 | nsres = self.GetRegion()['nsres']
|
|---|
| 324 | ewres = self.GetRegion()['ewres']
|
|---|
| 325 |
|
|---|
| 326 | n = float(self.region['n'])
|
|---|
| 327 | s = float(self.region['s'])
|
|---|
| 328 | e = float(self.region['e'])
|
|---|
| 329 | w = float(self.region['w'])
|
|---|
| 330 |
|
|---|
| 331 | # Calculate rows, columns, and extents
|
|---|
| 332 | new['rows'] = math.fabs(round((n-s)/nsres))
|
|---|
| 333 | new['cols'] = math.fabs(round((e-w)/ewres))
|
|---|
| 334 |
|
|---|
| 335 | # Calculate new extents
|
|---|
| 336 | new['s'] = nsres * round(s/nsres)
|
|---|
| 337 | new['w'] = ewres * round(w/ewres)
|
|---|
| 338 | new['n'] = new['s'] + (new['rows'] * nsres)
|
|---|
| 339 | new['e'] = new['w'] + (new['cols'] * ewres)
|
|---|
| 340 |
|
|---|
| 341 | return new
|
|---|
| 342 |
|
|---|
| 343 | def AlignExtentFromDisplay(self):
|
|---|
| 344 | """Sets display extents (n,s,e,w) to even multiple of
|
|---|
| 345 | current display resolution from center point"""
|
|---|
| 346 |
|
|---|
| 347 | # calculate new bounding box based on center of display
|
|---|
| 348 | if self.region["ewres"] > self.region["nsres"]:
|
|---|
| 349 | res = self.region["ewres"]
|
|---|
| 350 | else:
|
|---|
| 351 | res = self.region["nsres"]
|
|---|
| 352 |
|
|---|
| 353 | Debug.msg(3, "Map.AlignExtentFromDisplay(): width=%d, height=%d, res=%f, center=%f,%f" % \
|
|---|
| 354 | (self.width, self.height, res, self.region['center_easting'],
|
|---|
| 355 | self.region['center_northing']))
|
|---|
| 356 |
|
|---|
| 357 | ew = (self.width / 2) * res
|
|---|
| 358 | ns = (self.height / 2) * res
|
|---|
| 359 |
|
|---|
| 360 | self.region['n'] = self.region['center_northing'] + ns
|
|---|
| 361 | self.region['s'] = self.region['center_northing'] - ns
|
|---|
| 362 | self.region['e'] = self.region['center_easting'] + ew
|
|---|
| 363 | self.region['w'] = self.region['center_easting'] - ew
|
|---|
| 364 |
|
|---|
| 365 | def ChangeMapSize(self, (width, height)):
|
|---|
| 366 | """Change size of rendered map.
|
|---|
| 367 |
|
|---|
| 368 | @param width,height map size
|
|---|
| 369 |
|
|---|
| 370 | @return True on success
|
|---|
| 371 | @return False on failure
|
|---|
| 372 | """
|
|---|
| 373 | try:
|
|---|
| 374 | self.width = int(width)
|
|---|
| 375 | self.height = int(height)
|
|---|
| 376 | Debug.msg(2, "Map.ChangeMapSize(): width=%d, height=%d" % \
|
|---|
| 377 | (self.width, self.height))
|
|---|
| 378 | return True
|
|---|
| 379 | except:
|
|---|
| 380 | self.width = 640
|
|---|
| 381 | self.height = 480
|
|---|
| 382 | return False
|
|---|
| 383 |
|
|---|
| 384 | def GetRegion(self, rast=None, vect=None,
|
|---|
| 385 | n=None, s=None, e=None, w=None):
|
|---|
| 386 | """
|
|---|
| 387 | Get region settings
|
|---|
| 388 |
|
|---|
| 389 | Optionaly raster or vector map layer can be given.
|
|---|
| 390 |
|
|---|
| 391 | @param rast raster name or None
|
|---|
| 392 | @param vect vector name or None
|
|---|
| 393 |
|
|---|
| 394 | @return region settings as directory, e.g. {
|
|---|
| 395 | "n":"4928010", "s":"4913700", "w":"589980",...}
|
|---|
| 396 | """
|
|---|
| 397 |
|
|---|
| 398 | region = {}
|
|---|
| 399 |
|
|---|
| 400 | tmpreg = os.getenv("GRASS_REGION")
|
|---|
| 401 | os.unsetenv("GRASS_REGION")
|
|---|
| 402 |
|
|---|
| 403 | # do not update & shell style output
|
|---|
| 404 | cmdList = ["g.region", "-u", "-g", "-p", "-c"]
|
|---|
| 405 |
|
|---|
| 406 | if n:
|
|---|
| 407 | cmdList.append('n=%s' % n)
|
|---|
| 408 | if s:
|
|---|
| 409 | cmdList.append('s=%s' % s)
|
|---|
| 410 | if e:
|
|---|
| 411 | cmdList.append('e=%s' % e)
|
|---|
| 412 | if w:
|
|---|
| 413 | cmdList.append('w=%s' % w)
|
|---|
| 414 |
|
|---|
| 415 | if rast:
|
|---|
| 416 | cmdList.append('rast=%s' % rast)
|
|---|
| 417 | if vect:
|
|---|
| 418 | cmdList.append('vect=%s' % vect)
|
|---|
| 419 |
|
|---|
| 420 | try:
|
|---|
| 421 | cmdRegion = gcmd.Command(cmdList)
|
|---|
| 422 | except gcmd.CmdError, e:
|
|---|
| 423 | if rast:
|
|---|
| 424 | e.message = _("Unable to zoom to raster map <%s>.") % rast + \
|
|---|
| 425 | '%s%s' % (os.linesep, os.linesep) + e.message
|
|---|
| 426 | elif vect:
|
|---|
| 427 | e.message = _("Unable to zoom to vector map <%s>.") % vect + \
|
|---|
| 428 | '%s%s' % (os.linesep, os.linesep) + e.message
|
|---|
| 429 |
|
|---|
| 430 | print e
|
|---|
| 431 | return self.region
|
|---|
| 432 |
|
|---|
| 433 | for reg in cmdRegion.ReadStdOutput():
|
|---|
| 434 | key, val = reg.split("=", 1)
|
|---|
| 435 | try:
|
|---|
| 436 | region[key] = float(val)
|
|---|
| 437 | except ValueError:
|
|---|
| 438 | region[key] = val
|
|---|
| 439 |
|
|---|
| 440 | # restore region
|
|---|
| 441 | if tmpreg:
|
|---|
| 442 | os.environ["GRASS_REGION"] = tmpreg
|
|---|
| 443 |
|
|---|
| 444 | Debug.msg (3, "Map.GetRegion(): %s" % region)
|
|---|
| 445 |
|
|---|
| 446 | return region
|
|---|
| 447 |
|
|---|
| 448 | def SetRegion(self, windres=False):
|
|---|
| 449 | """
|
|---|
| 450 | Render string for GRASS_REGION env. variable, so that the images will be rendered
|
|---|
| 451 | from desired zoom level.
|
|---|
| 452 |
|
|---|
| 453 | @param windres If windres set to True, uses resolution from
|
|---|
| 454 | WIND file rather than display (for modules that require set
|
|---|
| 455 | resolution like d.rast.num)
|
|---|
| 456 |
|
|---|
| 457 | @return String usable for GRASS_REGION variable or None
|
|---|
| 458 | """
|
|---|
| 459 | grass_region = ""
|
|---|
| 460 |
|
|---|
| 461 | # adjust region settigns to match monitor
|
|---|
| 462 | self.region = self.__adjustRegion()
|
|---|
| 463 |
|
|---|
| 464 | # newextents = self.AlignResolution()
|
|---|
| 465 | # self.region['n'] = newextents['n']
|
|---|
| 466 | # self.region['s'] = newextents['s']
|
|---|
| 467 | # self.region['e'] = newextents['e']
|
|---|
| 468 | # self.region['w'] = newextents['w']
|
|---|
| 469 |
|
|---|
| 470 | # read values from wind file
|
|---|
| 471 | try:
|
|---|
| 472 | for key in self.wind.keys():
|
|---|
| 473 | if key == 'north':
|
|---|
| 474 | grass_region += "north: %s; " % \
|
|---|
| 475 | (self.region['n'])
|
|---|
| 476 | continue
|
|---|
| 477 | elif key == "south":
|
|---|
| 478 | grass_region += "south: %s; " % \
|
|---|
| 479 | (self.region['s'])
|
|---|
| 480 | continue
|
|---|
| 481 | elif key == "east":
|
|---|
| 482 | grass_region += "east: %s; " % \
|
|---|
| 483 | (self.region['e'])
|
|---|
| 484 | continue
|
|---|
| 485 | elif key == "west":
|
|---|
| 486 | grass_region += "west: %s; " % \
|
|---|
| 487 | (self.region['w'])
|
|---|
| 488 | continue
|
|---|
| 489 | elif key == "e-w resol":
|
|---|
| 490 | grass_region += "e-w resol: %f; " % \
|
|---|
| 491 | (self.region['ewres'])
|
|---|
| 492 | continue
|
|---|
| 493 | elif key == "n-s resol":
|
|---|
| 494 | grass_region += "n-s resol: %f; " % \
|
|---|
| 495 | (self.region['nsres'])
|
|---|
| 496 | continue
|
|---|
| 497 | elif key == "cols":
|
|---|
| 498 | grass_region += 'cols: %d; ' % \
|
|---|
| 499 | (self.width)
|
|---|
| 500 | continue
|
|---|
| 501 | elif key == "rows":
|
|---|
| 502 | grass_region += 'rows: %d; ' % \
|
|---|
| 503 | (self.height)
|
|---|
| 504 | continue
|
|---|
| 505 | else:
|
|---|
| 506 | grass_region += key + ": " + self.wind[key] + "; "
|
|---|
| 507 |
|
|---|
| 508 | Debug.msg (3, "Map.SetRegion(): %s" % grass_region)
|
|---|
| 509 |
|
|---|
| 510 | return grass_region
|
|---|
| 511 |
|
|---|
| 512 | except:
|
|---|
| 513 | return None
|
|---|
| 514 |
|
|---|
| 515 | def ProjInfo(self):
|
|---|
| 516 | """
|
|---|
| 517 | Return region projection and map units information
|
|---|
| 518 | """
|
|---|
| 519 |
|
|---|
| 520 | projinfo = {}
|
|---|
| 521 |
|
|---|
| 522 | p = gcmd.Command(['g.proj', '-p'])
|
|---|
| 523 |
|
|---|
| 524 | if p.returncode == 0:
|
|---|
| 525 | for line in p.ReadStdOutput():
|
|---|
| 526 | if ':' in line:
|
|---|
| 527 | key,val = line.split(':')
|
|---|
| 528 | key = key.strip()
|
|---|
| 529 | val = val.strip()
|
|---|
| 530 | projinfo[key] = val
|
|---|
| 531 | elif "XY location (unprojected)" in line:
|
|---|
| 532 | projinfo['proj'] = "xy"
|
|---|
| 533 | return projinfo
|
|---|
| 534 | else:
|
|---|
| 535 | return None
|
|---|
| 536 |
|
|---|
| 537 | def GetListOfLayers(self, l_type=None, l_mapset=None, l_name=None,
|
|---|
| 538 | l_active=None, l_hidden=None):
|
|---|
| 539 | """
|
|---|
| 540 | Returns list of layers of selected properties or list of all
|
|---|
| 541 | layers.
|
|---|
| 542 |
|
|---|
| 543 | @param l_type layer type, e.g. raster/vector/wms/overlay
|
|---|
| 544 | @param l_mapset all layers from given mapset
|
|---|
| 545 | @param l_name all layers with given name
|
|---|
| 546 | @param l_active only layers with 'active' attribute set to True or False
|
|---|
| 547 | @param l_hidden only layers with 'hidden' attribute set to True or False
|
|---|
| 548 |
|
|---|
| 549 | @return list of selected layers
|
|---|
| 550 | """
|
|---|
| 551 |
|
|---|
| 552 | selected = []
|
|---|
| 553 |
|
|---|
| 554 | # ["raster", "vector", "wms", ... ]
|
|---|
| 555 | for layer in self.layers + self.overlays:
|
|---|
| 556 | # specified type only
|
|---|
| 557 | if l_type != None and layer.type != l_type:
|
|---|
| 558 | continue
|
|---|
| 559 |
|
|---|
| 560 | # mapset
|
|---|
| 561 | if l_mapset != None and layer.GetMapset() != l_mapset:
|
|---|
| 562 | continue
|
|---|
| 563 |
|
|---|
| 564 | # name
|
|---|
| 565 | if l_name != None and layer.name != l_name:
|
|---|
| 566 | continue
|
|---|
| 567 |
|
|---|
| 568 | # hidden and active layers
|
|---|
| 569 | if l_active != None and \
|
|---|
| 570 | l_hidden != None:
|
|---|
| 571 | if layer.active == l_active and \
|
|---|
| 572 | layer.hidden == l_hidden:
|
|---|
| 573 | selected.append(layer)
|
|---|
| 574 |
|
|---|
| 575 | # active layers
|
|---|
| 576 | elif l_active != None:
|
|---|
| 577 | if layer.active == l_active:
|
|---|
| 578 | selected.append(layer)
|
|---|
| 579 |
|
|---|
| 580 | # hidden layers
|
|---|
| 581 | elif l_hidden != None:
|
|---|
| 582 | if layer.hidden == l_hidden:
|
|---|
| 583 | selected.append(layer)
|
|---|
| 584 |
|
|---|
| 585 | # all layers
|
|---|
| 586 | else:
|
|---|
| 587 | selected.append(layer)
|
|---|
| 588 |
|
|---|
| 589 | Debug.msg (3, "Map.GetListOfLayers(): numberof=%d" % len(selected))
|
|---|
| 590 |
|
|---|
| 591 | return selected
|
|---|
| 592 |
|
|---|
| 593 | def Render(self, force=False, mapWindow=None):
|
|---|
| 594 | """
|
|---|
| 595 | Creates final image composite
|
|---|
| 596 |
|
|---|
| 597 | This function can conditionaly use high-level tools, which
|
|---|
| 598 | should be avaliable in wxPython library
|
|---|
| 599 |
|
|---|
| 600 | @param force force rendering
|
|---|
| 601 | @param reference for MapFrame instance (for progress bar)
|
|---|
| 602 |
|
|---|
| 603 | @return name of file with rendered image or None
|
|---|
| 604 | """
|
|---|
| 605 |
|
|---|
| 606 | maps = []
|
|---|
| 607 | masks =[]
|
|---|
| 608 | opacities = []
|
|---|
| 609 |
|
|---|
| 610 | tmp_region = os.getenv("GRASS_REGION")
|
|---|
| 611 | os.environ["GRASS_REGION"] = self.SetRegion()
|
|---|
| 612 | os.environ["GRASS_WIDTH"] = str(self.width)
|
|---|
| 613 | os.environ["GRASS_HEIGHT"] = str(self.height)
|
|---|
| 614 |
|
|---|
| 615 | # render map layers
|
|---|
| 616 | for layer in self.layers + self.overlays:
|
|---|
| 617 | # skip if not active
|
|---|
| 618 | if layer == None or layer.active == False:
|
|---|
| 619 | continue
|
|---|
| 620 |
|
|---|
| 621 | # render if there is no mapfile
|
|---|
| 622 | if layer.mapfile == None:
|
|---|
| 623 | layer.Render()
|
|---|
| 624 |
|
|---|
| 625 | # process bar
|
|---|
| 626 | if mapWindow is not None:
|
|---|
| 627 | mapWindow.onRenderCounter += 1
|
|---|
| 628 |
|
|---|
| 629 | wx.Yield()
|
|---|
| 630 | # redraw layer content
|
|---|
| 631 | if force:
|
|---|
| 632 | if not layer.Render():
|
|---|
| 633 | continue
|
|---|
| 634 |
|
|---|
| 635 | # add image to compositing list
|
|---|
| 636 | if layer.type != "overlay":
|
|---|
| 637 | maps.append(layer.mapfile)
|
|---|
| 638 | masks.append(layer.maskfile)
|
|---|
| 639 | opacities.append(str(layer.opacity))
|
|---|
| 640 |
|
|---|
| 641 | Debug.msg (3, "Map.Render() type=%s, layer=%s " % (layer.type, layer.name))
|
|---|
| 642 |
|
|---|
| 643 | # ugly hack for MSYS
|
|---|
| 644 | if not subprocess.mswindows:
|
|---|
| 645 | mapstr = ",".join(maps)
|
|---|
| 646 | maskstr = ",".join(masks)
|
|---|
| 647 | mapoutstr = self.mapfile
|
|---|
| 648 | else:
|
|---|
| 649 | mapstr = ""
|
|---|
| 650 | for item in maps:
|
|---|
| 651 | mapstr += item.replace('\\', '/')
|
|---|
| 652 | mapstr = mapstr.rstrip(',')
|
|---|
| 653 | maskstr = ""
|
|---|
| 654 | for item in masks:
|
|---|
| 655 | maskstr += item.replace('\\', '/')
|
|---|
| 656 | maskstr = maskstr.rstrip(',')
|
|---|
| 657 | mapoutstr = self.mapfile.replace('\\', '/')
|
|---|
| 658 |
|
|---|
| 659 | compstring = "g.pnmcomp" + globalvar.EXT_BIN + \
|
|---|
| 660 | " in=" + mapstr + \
|
|---|
| 661 | " mask=" + maskstr + \
|
|---|
| 662 | " opacity=" + ",".join(opacities)+ \
|
|---|
| 663 | " background=255:255:255" + \
|
|---|
| 664 | " width=" + str(self.width) + \
|
|---|
| 665 | " height=" + str(self.height) + \
|
|---|
| 666 | " output=" + mapoutstr
|
|---|
| 667 |
|
|---|
| 668 | # compose command
|
|---|
| 669 | complist = ["g.pnmcomp",
|
|---|
| 670 | "in=%s" % ",".join(maps),
|
|---|
| 671 | "mask=%s" % ",".join(masks),
|
|---|
| 672 | "opacity=%s" % ",".join(opacities),
|
|---|
| 673 | "background=255:255:255",
|
|---|
| 674 | "width=%s" % str(self.width),
|
|---|
| 675 | "height=%s" % str(self.height),
|
|---|
| 676 | "output=%s" % self.mapfile]
|
|---|
| 677 |
|
|---|
| 678 |
|
|---|
| 679 | # render overlays
|
|---|
| 680 |
|
|---|
| 681 | os.unsetenv("GRASS_REGION")
|
|---|
| 682 |
|
|---|
| 683 | if tmp_region:
|
|---|
| 684 | os.environ["GRASS_REGION"] = tmp_region
|
|---|
| 685 |
|
|---|
| 686 | # run g.pngcomp to get composite image
|
|---|
| 687 | try:
|
|---|
| 688 | gcmd.Command(complist)
|
|---|
| 689 | # os.system(compstring)
|
|---|
| 690 | except gcmd.CmdError, e:
|
|---|
| 691 | print e
|
|---|
| 692 | return None
|
|---|
| 693 |
|
|---|
| 694 | Debug.msg (2, "Map.Render() force=%s file=%s" % (force, self.mapfile))
|
|---|
| 695 |
|
|---|
| 696 | return self.mapfile
|
|---|
| 697 |
|
|---|
| 698 | def AddLayer(self, type, command, name=None,
|
|---|
| 699 | l_active=True, l_hidden=False, l_opacity=1.0, l_render=False):
|
|---|
| 700 | """
|
|---|
| 701 | Adds generic display command layer to list of layers
|
|---|
| 702 |
|
|---|
| 703 | @param item reference to item in layer tree
|
|---|
| 704 | @param type layer type
|
|---|
| 705 | @param name layer name
|
|---|
| 706 | @param cmd GRASS command to render layer
|
|---|
| 707 | @param l_active checked/not checked for display in layer tree
|
|---|
| 708 | @param l_hidden not used here
|
|---|
| 709 | @param l_opacity opacity leve range from 0(transparent)-1(not transparent)
|
|---|
| 710 | @param l_render render an image if False
|
|---|
| 711 |
|
|---|
| 712 | @return new layer on success
|
|---|
| 713 | @return None on failure
|
|---|
| 714 |
|
|---|
| 715 | """
|
|---|
| 716 | # l_opacity must be <0;1>
|
|---|
| 717 | if l_opacity < 0: l_opacity = 0
|
|---|
| 718 | elif l_opacity > 1: l_opacity = 1
|
|---|
| 719 |
|
|---|
| 720 | layer = MapLayer(type=type, name=name, cmd=command,
|
|---|
| 721 | active=l_active, hidden=l_hidden, opacity=l_opacity)
|
|---|
| 722 |
|
|---|
| 723 | # add maplayer to the list of layers
|
|---|
| 724 | self.layers.append(layer)
|
|---|
| 725 |
|
|---|
| 726 | Debug.msg (3, "Map.AddLayer(): layer=%s" % layer.name)
|
|---|
| 727 | if l_render:
|
|---|
| 728 | if not layer.Render():
|
|---|
| 729 | raise gcmd.GStdError(_("Unable to render map layer <%s>.") % (name))
|
|---|
| 730 |
|
|---|
| 731 | return self.layers[-1]
|
|---|
| 732 |
|
|---|
| 733 | def DeleteLayer(self, layer):
|
|---|
| 734 | """
|
|---|
| 735 | Removes layer from list of layers,
|
|---|
| 736 | defined by reference to MapLayer instance
|
|---|
| 737 |
|
|---|
| 738 | Returns:
|
|---|
| 739 | Removed layer on success or None
|
|---|
| 740 | """
|
|---|
| 741 |
|
|---|
| 742 | Debug.msg (3, "Map.DeleteLayer(): name=%s" % layer.name)
|
|---|
| 743 | if layer in self.layers:
|
|---|
| 744 | if layer.mapfile:
|
|---|
| 745 | base = os.path.split(layer.mapfile)[0]
|
|---|
| 746 | mapfile = os.path.split(layer.mapfile)[1]
|
|---|
| 747 | tempbase = mapfile.split('.')[0]
|
|---|
| 748 | basefile = os.path.join(base,tempbase)+r'.*'
|
|---|
| 749 | for f in glob.glob(basefile):
|
|---|
| 750 | os.remove(f)
|
|---|
| 751 | self.layers.remove(layer)
|
|---|
| 752 | return layer
|
|---|
| 753 |
|
|---|
| 754 | return None
|
|---|
| 755 |
|
|---|
| 756 | def ReorderLayers(self, layerList):
|
|---|
| 757 | """
|
|---|
| 758 | Make a new reordered list to match reordered
|
|---|
| 759 | layer tree - for drag and drop
|
|---|
| 760 | """
|
|---|
| 761 | self.layers = layerList
|
|---|
| 762 |
|
|---|
| 763 | layerNameList = ""
|
|---|
| 764 | for layer in self.layers:
|
|---|
| 765 | if layer.name:
|
|---|
| 766 | layerNameList += layer.name + ','
|
|---|
| 767 | Debug.msg (4, "Map.ReoderLayers(): layers=%s" % \
|
|---|
| 768 | (layerNameList))
|
|---|
| 769 |
|
|---|
| 770 | def ChangeLayer(self, layer, type, command, name=None,
|
|---|
| 771 | l_active=True, l_hidden=False, l_opacity=1, l_render=False):
|
|---|
| 772 | """
|
|---|
| 773 | Change the command and other other options for a layer
|
|---|
| 774 | """
|
|---|
| 775 |
|
|---|
| 776 | # l_opacity must be <0;1>
|
|---|
| 777 | if l_opacity < 0: l_opacity = 0
|
|---|
| 778 | elif l_opacity > 1: l_opacity = 1
|
|---|
| 779 |
|
|---|
| 780 | Debug.msg (3, "Map.ChangeLayer():")
|
|---|
| 781 |
|
|---|
| 782 | newlayer = MapLayer(type=type, cmd=command, name=name,
|
|---|
| 783 | active=l_active, hidden=l_hidden, opacity=l_opacity)
|
|---|
| 784 |
|
|---|
| 785 | oldlayerindex = self.layers.index(layer)
|
|---|
| 786 |
|
|---|
| 787 | # add maplayer to the list of layers
|
|---|
| 788 | if layer:
|
|---|
| 789 | self.layers[oldlayerindex] = newlayer
|
|---|
| 790 |
|
|---|
| 791 | if l_render and not layer.Render():
|
|---|
| 792 | raise gcmd.GException(_("Unable to render map layer <%s>.") %
|
|---|
| 793 | (name))
|
|---|
| 794 |
|
|---|
| 795 | return self.layers[-1]
|
|---|
| 796 |
|
|---|
| 797 | def ChangeOpacity(self, layer, l_opacity):
|
|---|
| 798 | """
|
|---|
| 799 | Changes opacity value of map layer
|
|---|
| 800 |
|
|---|
| 801 | @param layer layer instance
|
|---|
| 802 | @param l_opacity opacity level <0;1>
|
|---|
| 803 | """
|
|---|
| 804 | # l_opacity must be <0;1>
|
|---|
| 805 | if l_opacity < 0: l_opacity = 0
|
|---|
| 806 | elif l_opacity > 1: l_opacity = 1
|
|---|
| 807 |
|
|---|
| 808 | layer.opacity = l_opacity
|
|---|
| 809 | Debug.msg (3, "Map.ChangeOpacity(): layer=%s, opacity=%f" % \
|
|---|
| 810 | (layer.name, layer.opacity))
|
|---|
| 811 |
|
|---|
| 812 | def ChangeLayerActive(self, layer, active):
|
|---|
| 813 | """
|
|---|
| 814 | Change the active state of a layer
|
|---|
| 815 |
|
|---|
| 816 | @param layer layer instance
|
|---|
| 817 | @param active to be rendered (True)
|
|---|
| 818 | """
|
|---|
| 819 | layer.active = active
|
|---|
| 820 |
|
|---|
| 821 | Debug.msg (3, "Map.ChangeLayerActive(): name='%s' -> active=%d" % \
|
|---|
| 822 | (layer.name, layer.active))
|
|---|
| 823 |
|
|---|
| 824 | def ChangeLayerName (self, layer, name):
|
|---|
| 825 | """
|
|---|
| 826 | Change name of the layer
|
|---|
| 827 |
|
|---|
| 828 | @param layer layer instance
|
|---|
| 829 | @param name layer name to set up
|
|---|
| 830 | """
|
|---|
| 831 | Debug.msg (3, "Map.ChangeLayerName(): from=%s to=%s" % \
|
|---|
| 832 | (layer.name, name))
|
|---|
| 833 | layer.name = name
|
|---|
| 834 |
|
|---|
| 835 | def RemoveLayer(self, name=None, id=None):
|
|---|
| 836 | """
|
|---|
| 837 | Removes layer from layer list of layers
|
|---|
| 838 |
|
|---|
| 839 | Layer is defined by name@mapset or id.
|
|---|
| 840 |
|
|---|
| 841 | @param name layer name (must be unique)
|
|---|
| 842 | @param id layer index in layer list
|
|---|
| 843 |
|
|---|
| 844 | @return removed layer on success
|
|---|
| 845 | @return None on failure
|
|---|
| 846 | """
|
|---|
| 847 |
|
|---|
| 848 | # delete by name
|
|---|
| 849 | if name:
|
|---|
| 850 | retlayer = None
|
|---|
| 851 | for layer in self.layers:
|
|---|
| 852 | if layer.name == name:
|
|---|
| 853 | retlayer = layer
|
|---|
| 854 | os.remove(layer.mapfile)
|
|---|
| 855 | os.remove(layer.maskfile)
|
|---|
| 856 | self.layers.remove(layer)
|
|---|
| 857 | return layer
|
|---|
| 858 | # del by id
|
|---|
| 859 | elif id != None:
|
|---|
| 860 | return self.layers.pop(id)
|
|---|
| 861 |
|
|---|
| 862 | return None
|
|---|
| 863 |
|
|---|
| 864 | def GetLayerIndex(self, layer):
|
|---|
| 865 | """
|
|---|
| 866 | Returns index of layer in layer list.
|
|---|
| 867 |
|
|---|
| 868 | @param layer layer instace
|
|---|
| 869 |
|
|---|
| 870 | @return layer index
|
|---|
| 871 | @return None
|
|---|
| 872 | """
|
|---|
| 873 |
|
|---|
| 874 | if layer in self.layers:
|
|---|
| 875 | return self.layers.index(layer)
|
|---|
| 876 | else:
|
|---|
| 877 | return None
|
|---|
| 878 |
|
|---|
| 879 | def AddOverlay(self, ovltype=None, type='overlay', command=None,
|
|---|
| 880 | l_active=True, l_hidden=False, l_opacity=1, l_render=False):
|
|---|
| 881 | """
|
|---|
| 882 | Adds overlay (grid, barscale, others?) to list of overlays
|
|---|
| 883 |
|
|---|
| 884 | @param ovltype overlay type
|
|---|
| 885 | @param command GRASS command to render overlay
|
|---|
| 886 | @param l_active overlay activated (True) or disabled (False)
|
|---|
| 887 | @param l_render render an image (True)
|
|---|
| 888 |
|
|---|
| 889 | @return new layer on success
|
|---|
| 890 | @retutn None on failure
|
|---|
| 891 | """
|
|---|
| 892 |
|
|---|
| 893 | Debug.msg (2, "Map.AddOverlay(): cmd=%s, render=%d" % (command, l_render))
|
|---|
| 894 | overlay = MapLayer(type='overlay', name=None, cmd=command,
|
|---|
| 895 | active=l_active, hidden=l_hidden, opacity=l_opacity)
|
|---|
| 896 |
|
|---|
| 897 | # add maplayer to the list of layers
|
|---|
| 898 | self.overlays.append(overlay)
|
|---|
| 899 |
|
|---|
| 900 | if l_render and command != '' and not overlay.Render():
|
|---|
| 901 | raise gcmd.GException(_("Unable render overlay <%s>.") %
|
|---|
| 902 | (name))
|
|---|
| 903 |
|
|---|
| 904 | self.ovlookup[ovltype] = overlay
|
|---|
| 905 |
|
|---|
| 906 | return self.overlays[-1]
|
|---|
| 907 |
|
|---|
| 908 | def ChangeOverlay(self, ovltype, type, name, command,
|
|---|
| 909 | l_active=True, l_hidden=False, l_opacity=1, l_render=False):
|
|---|
| 910 | """
|
|---|
| 911 | Change overlay properities
|
|---|
| 912 |
|
|---|
| 913 | @param ovltype overlay type
|
|---|
| 914 | @param type layer type
|
|---|
| 915 | @param command GRASS command to render an overlay
|
|---|
| 916 | @param l_active overlay is active (True) or disabled (False)
|
|---|
| 917 | @param l_hidded not used here
|
|---|
| 918 | @param l_opacity opacity level <0,1>
|
|---|
| 919 | @param l_render render overlay (True)
|
|---|
| 920 |
|
|---|
| 921 | @return new overlay instance
|
|---|
| 922 | """
|
|---|
| 923 |
|
|---|
| 924 | newoverlay = MapLayer(type='overlay', name=name, cmd=command,
|
|---|
| 925 | active=l_active, hidden=l_hidden, opacity=l_opacity)
|
|---|
| 926 |
|
|---|
| 927 | oldovlindex = self.overlays.index(self.ovlookup[ovltype])
|
|---|
| 928 |
|
|---|
| 929 | # add overlay to the list of layers
|
|---|
| 930 | if self.ovlookup[ovltype]:
|
|---|
| 931 | self.overlays[oldovlindex] = newoverlay
|
|---|
| 932 | self.ovlookup[ovltype] = newoverlay
|
|---|
| 933 |
|
|---|
| 934 | if l_render and command != '' and not overlay.Render():
|
|---|
| 935 | raise gcmd.GException(_("Unable render overlay <%s>.") %
|
|---|
| 936 | (name))
|
|---|
| 937 |
|
|---|
| 938 | return self.overlays[-1]
|
|---|
| 939 |
|
|---|
| 940 | def changeOverlayActive(self, ovltype, activ):
|
|---|
| 941 | """
|
|---|
| 942 | Change active status of overlay
|
|---|
| 943 | """
|
|---|
| 944 | try:
|
|---|
| 945 | overlay = self.ovlookup[ovltype]
|
|---|
| 946 | overlay.active = activ
|
|---|
| 947 | Debug.msg (3, "Map.changeOverlayActive(): type=%d, active=%d" % (type, activ))
|
|---|
| 948 | except:
|
|---|
| 949 | sys.stderr.write("Cannot change status of overlay index [%d]\n" % type)
|
|---|
| 950 |
|
|---|
| 951 | def Clean(self):
|
|---|
| 952 | """
|
|---|
| 953 | Go trough all layers and remove them from layer list
|
|---|
| 954 | Removes also l_mapfile and l_maskfile
|
|---|
| 955 |
|
|---|
| 956 | @return 1 on faulure
|
|---|
| 957 | @return None on success
|
|---|
| 958 | """
|
|---|
| 959 | try:
|
|---|
| 960 | for layer in self.layers:
|
|---|
| 961 | if layer.mapfile:
|
|---|
| 962 | base = os.path.split(layer.mapfile)[0]
|
|---|
| 963 | mapfile = os.path.split(layer.mapfile)[1]
|
|---|
| 964 | tempbase = mapfile.split('.')[0]
|
|---|
| 965 | basefile = os.path.join(base,tempbase)+r'.*'
|
|---|
| 966 | for f in glob.glob(basefile):
|
|---|
| 967 | os.remove(f)
|
|---|
| 968 | self.layers.remove(layer)
|
|---|
| 969 | for overlay in self.overlays:
|
|---|
| 970 | if overlay.ovlfile:
|
|---|
| 971 | base = os.path.split(overlay.ovlfile)[0]
|
|---|
| 972 | mapfile = os.path.split(overlay.ovlfile)[1]
|
|---|
| 973 | tempbase = mapfile.split('.')[0]
|
|---|
| 974 | basefile = os.path.join(base,tempbase)+r'.*'
|
|---|
| 975 | for f in glob.glob(basefile):
|
|---|
| 976 | os.remove(f)
|
|---|
| 977 | self.overlays.remove(overlay)
|
|---|
| 978 | return None
|
|---|
| 979 | except:
|
|---|
| 980 | return 1
|
|---|
| 981 | self.layers = []
|
|---|
| 982 |
|
|---|
| 983 | def ReverseListOfLayers(self):
|
|---|
| 984 | """Reverse list of layers"""
|
|---|
| 985 | return self.layers.reverse()
|
|---|
| 986 |
|
|---|
| 987 | if __name__ == "__main__":
|
|---|
| 988 | """
|
|---|
| 989 | Test of Display class.
|
|---|
| 990 | Usage: display=Render()
|
|---|
| 991 | """
|
|---|
| 992 |
|
|---|
| 993 | print "Initializing..."
|
|---|
| 994 | os.system("g.region -d")
|
|---|
| 995 |
|
|---|
| 996 | map = Map()
|
|---|
| 997 | map.width = 640
|
|---|
| 998 | map.height = 480
|
|---|
| 999 |
|
|---|
| 1000 | map.AddLayer(item=None, type="raster", name="elevation.dem", command = "d.rast elevation.dem@PERMANENT catlist=1000-1500 -i", l_opacity=.7)
|
|---|
| 1001 |
|
|---|
| 1002 | map.AddLayer(item=None, type="vector", name="streams", command = "d.vect streams@PERMANENT color=red width=3 type=line")
|
|---|
| 1003 |
|
|---|
| 1004 | image = map.Render(force=True)
|
|---|
| 1005 |
|
|---|
| 1006 | if image:
|
|---|
| 1007 | os.system("display %s" % image)
|
|---|