فهرست منبع

r.in.wms replaced by new version from grass-addons (r.in.wms2)
Module `r.in.wms2` has been written by Stepan Turek (bachelor project)


git-svn-id: https://svn.osgeo.org/grass/grass/trunk@52470 15284696-431f-4ddb-bdfa-cd5b030d7da7

Martin Landa 12 سال پیش
والد
کامیت
31d721a2b3

+ 11 - 9
scripts/r.in.wms/Makefile

@@ -1,16 +1,18 @@
 MODULE_TOPDIR = ../..
 MODULE_TOPDIR = ../..
 
 
-PGM=r.in.wms
+PGM = r.in.wms
 
 
-include $(MODULE_TOPDIR)/include/Make/Script.make
-
-SRCFILES = wms_parse.py wms_request.py wms_download.py gdalwarp.py r.in.gdalwarp.py wms_gdal.py
-DSTFILES := $(patsubst %,$(ETC)/r.in.wms/%,$(SRCFILES))
+MODULES = wms_base wms_drv wms_gdal_drv
+PYFILES := $(patsubst %,$(ETC)/%.py,$(MODULES))
+PYCFILES := $(patsubst %,$(ETC)/%.pyc,$(MODULES))
 
 
-default: script $(DSTFILES)
+include $(MODULE_TOPDIR)/include/Make/Script.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
 
 
-$(ETC)/r.in.wms/%: % | $(ETC)/r.in.wms
-	$(INSTALL) $< $@
+default: script $(PYFILES) $(PYCFILES)
 
 
-$(ETC)/r.in.wms:
+$(ETCDIR):
 	$(MKDIR) $@
 	$(MKDIR) $@
+
+$(ETC)/%: % | $(ETC)
+	$(INSTALL_DATA) $< $@

+ 0 - 353
scripts/r.in.wms/gdalwarp.py

@@ -1,353 +0,0 @@
-############################################################################
-#
-# MODULE:       r.in.wms / wms_gdalwarp.py
-#
-# AUTHOR(S):    Cedric Shock, 2006
-#               Update for GRASS 7 by Martin Landa <landa.martin gmail.com>, 2009
-#
-# PURPOSE:      To import data from web mapping servers
-#               (based on Bash script by Cedric Shock)
-#
-# COPYRIGHT:    (C) 2009 Martin Landa, and 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.
-#
-#############################################################################
-
-#
-# This file needs major rewrite...
-#
-
-import os
-import subprocess
-
-from grass.script import core as grass
-
-class GDALWarp:
-    def __init__(self, flags, options):
-        self.flags   = flags
-        self.options = options
-    
-        self.tmp = grass.tempfile()
-        
-        self.suffixes = []
-        self.patches  = []
-        self.maplist  = []
-        self.tiler = 0
-    
-        if not flags['p']:
-            # todo: check if gdalwarp is available
-            pass
-    
-        # flags for r.in.gdal
-        self.gdal_flags = ''
-        if flags['e']:
-            self.gdal_flags += 'e'
-        if flags['k']:
-            self.gdal_flags += 'k'
-        
-    def run(self):
-        # import tiles
-        tiler = 0
-        for input in self.options['input'].split(','):
-            tmptilename = self.options['output'] + '_tile_' + str(tiler)
-            if not os.path.exists(input):
-                grass.warning(_("Missing input '%s'") % input)
-                continue
-            grass.info(_("Importing tile '%s'...") % os.path.basename(input))
-            if self.flags['p']:
-                self.nowarp_import(input, tmptilename)
-            else:
-                self.warp_import(input, tmptilename)
-            
-            self.maplist.append(tmptilename)
-            tiler += 1
-        
-        if tiler < 1:
-            grass.message(_("Nothing imported"))
-            return 0
-        
-        # if there's more than one tile patch them together, otherwise
-        # just rename that tile.
-        if tiler == 1:
-            if len(self.channel_suffixes) > 0:
-                # multi-band
-                for suffix in self.channel_suffixes:
-                    # rename tile 0 to be the output
-                    ffile = self.options['output'] + '_tile_0' + suffix
-                    tfile = self.options['output'] + suffix
-                    if grass.run_command('g.rename',
-                                         quiet = True,
-                                         rast = ffile + ',' + tfile) != 0:
-                        grass.fatal(_('g.rename failed'))
-            else: # single-band, single-tile
-                ffile = self.options['output'] + '_tile_0' # + sfx ?
-                tfile = self.options['output'] # + sfx ?
-                if grass.run_command('g.rename',
-                                     quiet = True,
-                                     rast = ffile + ',' + tfile) != 0:
-                    grass.fatal(_('g.rename failed'))
-        else:
-            # patch together each channel
-            grass.debug('suffixes: %s' % ','.join(suffixes))
-            if len(suffixes) > 0:
-                # multi-band data
-                for suffix in suffixes:
-                    suffix = suffix.replace('.', '_')
-                    # patch these together (using nulls only)
-                    grass.message(_("Patching '%s' channel...") % suffix)
-                    if grass.run_command('r.patch',
-                                         quiet = True,
-                                         input = patches, # ???
-                                         output = self.options['output'] + suffix) != 0:
-                        grass.fatal(_('r.patch failed'))
-                        
-                    # remove the temporary patches we made
-                    if grass.run_command('g.remove',
-                                         quiet = True,
-                                         rast = patches) != 0:
-                        grass.fatal(_('g.remove failed'))
-            else:
-                # single-band data
-                grass.info(_("Patching tiles (this may take some time)..."))
-                grass.debug("patch list = %s" % ','.join(maplist))
-
-                # HACK: for 8bit PNG, GIF all the different tiles can have
-                #   different color tables so patches output end up all freaky.
-                #	r.mapcalc r#,g#,b# manual patching + r.composite?
-                #	or d.out.file + r.in.png + r.region?
-                # *** there is a GDAL utility to do this: gdal_merge.py
-                #       http://www.gdal.org/gdal_merge.html
-                for color in ('r', 'g', 'b'):
-                    maplist_color = []
-                    for map in maplist:
-                        outmap = map + '_' + color
-                        maplist_color.append(outmap)
-                        if grass.run_command('r.mapcalc',
-                                             quiet = True,
-                                             expression = '%s = %s#%s' % (outmap, color, map)) != 0:
-                            grass.fatal(_('r.mapcalc failed'))
-                        if grass.run_command('r.colors',
-                                             quiet = True,
-                                             map = outmap,
-                                             color = 'grey255') != 0:
-                            grass.fatal(_('r.colors failed'))
-                        if grass.run_command('r.null',
-                                             quiet = True,
-                                             map = outmap,
-                                             setnull = 255) != 0:
-                            grass.fatal(_('r.null failed'))
-                
-                        if grass.run_command('r.patch',
-                                             input = ','.join(maplist_color),
-                                             output = outmap + '_all') != 0:
-                            grass.fatal(_('r.patch failed'))
-                
-                if grass.run_command('r.composite',
-                                     quiet = True,
-                                     red = map + '_r_all',
-                                     green = map + '_g_all',
-                                     blue = map + '_b_all',
-                                     output = self.options['output']) != 0:
-                    grass.fatal(_('r.composite failed'))
-
-                if grass.run_command('g.mremove',
-                                     quiet = True,
-                                     flags = 'f',
-                                     rast = map + '*') != 0:
-                    grass.fatal(_('g.remove failed'))
-
-        # there's already a no suffix, can't make colors
-        # can only go up from here ;)
-        colors = 0
-        for suffix in self.suffixes:
-            if suffix in ('.red', '.green', '.blue'):
-                colors += 1
-        
-        # make a composite image if asked for and colors exist
-        if colors == 3 and self.flags['c']:
-            grass.message(_("Building color image <%s>...") % self.options['output'])
-            if grass.run_command('r.composite',
-                                 quiet = True,
-                                 red = self.options['output'] + '.red',
-                                 green = self.options['output'] + '.green',
-                                 blue = self.options['output'] + '.blue',
-                                 output = self.options['output']) != 0:
-                grass.fatal(_('r.composite failed'))
-        
-        return 0
-    
-    def warp_import(self, file, map):
-        """Wrap raster file using gdalwarp and import wrapped file
-        into GRASS"""
-        warpfile = self.tmp + 'warped.geotiff'
-        tmpmapname = map + '_tmp'
-
-        t_srs = grass.read_command('g.proj',
-                                   quiet = True,
-                                   flags = 'jf').rstrip('\n')
-        if not t_srs:
-            grass.fatal(_('g.proj failed'))
-        
-        grass.debug("gdalwarp -s_srs '%s' -t_srs '%s' -r %s %s %s %s" % \
-                        (self.options['srs'], t_srs,
-                         self.options['method'], self.options['warpoptions'],
-                         file, warpfile))
-        grass.verbose("Warping input file '%s'..." % os.path.basename(file))
-        if self.options['warpoptions']:
-            ps = subprocess.Popen(['gdalwarp',
-                                   '-s_srs', '%s' % self.options['srs'],
-                                   '-t_srs', '%s' % t_srs,
-                                   '-r', self.options['method'],
-                                   self.options['warpoptions'],
-                                   file, warpfile])
-        else:
-            ps = subprocess.Popen(['gdalwarp',
-                                   '-s_srs', '%s' % self.options['srs'],
-                                   '-t_srs', '%s' % t_srs,
-                                   '-r', self.options['method'],
-                                   file, warpfile])
-            
-        ps.wait()
-        if ps.returncode != 0 or \
-                not os.path.exists(warpfile):
-            grass.fatal(_('gdalwarp failed'))
-    
-        # import it into a temporary map
-        grass.info(_('Importing raster map...'))
-        if grass.run_command('r.in.gdal',
-                             quiet = True, overwrite = True,
-                             flags = self.gdal_flags,
-                             input = warpfile,
-                             output = tmpmapname) != 0:
-            grass.fatal(_('r.in.gdal failed'))
-        
-        os.remove(warpfile)
-
-        # get list of channels
-        pattern = tmpmapname + '*'
-        grass.debug('Pattern: %s' % pattern)
-        mapset = grass.gisenv()['MAPSET']
-        channel_list = grass.mlist_grouped(type = 'rast', pattern = pattern)[mapset]
-        grass.debug('Channel list: %s' % ','.join(channel_list))
-        
-        if len(channel_list) < 2: # test for single band data
-            self.channel_suffixes = []
-        else:
-            self.channel_suffixes = channel_list # ???
-        
-        grass.debug('Channel suffixes: %s' % ','.join(self.channel_suffixes))
-        
-        # add to the list of all suffixes
-        self.suffixes = self.suffixes + self.channel_suffixes
-        self.suffixes.sort()
-        
-        # get last suffix
-        if len(self.channel_suffixes) > 0:
-            last_suffix = self.channel_suffixes[-1]
-        else:
-            last_suffix = ''
-
-        # find the alpha layer
-        if self.flags['k']:
-            alphalayer = tmpmapname + last_suffix
-        else:
-            alphalayer = tmpmapname + '.alpha'
-        
-        # test to see if the alpha map exists
-        if not grass.find_file(element = 'cell', name = alphalayer)['name']:
-            alphalayer = ''
-        
-        # calculate the new maps:
-        for suffix in self.channel_suffixes:
-            grass.debug("alpha=%s MAPsfx=%s%s tmpname=%s%s" % \
-                            (alphalayer, map, suffix, tmpmapname, suffix))
-            if alphalayer:
-                # Use alpha channel for nulls: problem: I've seen a map
-                # where alpha was 1-255; 1 being transparent. what to do?
-                # (Geosci Australia Gold layer, format=tiff)
-                if grass.run_command('r.mapcalc',
-                                     quiet = True,
-                                     expression = "%s%s = if(%s, %s%s, null())" % \
-                                         (map, sfx, alphalayer, tmpmapname, sfx)) != 0:
-                    grass.fatal(_('r.mapcalc failed'))
-            else:
-                if grass.run_command('g.copy',
-                                     quiet = True,
-                                     rast = "%s%s,%s%s" % \
-                                         (tmpmapname, suffix, map, suffix)) != 0:
-                    grass.fatal(_('g.copy failed'))
-        
-            # copy the color tables
-            if grass.run_command('r.colors',
-                                 quiet = True,
-                                 map = map + suffix,
-                                 rast = tmpmapname + suffix) != 0:
-                grass.fatal(_('g.copy failed'))
-
-            # make patch lists
-            suffix = suffix.replace('.', '_')
-            # this is a hack to make the patch lists empty:
-            if self.tiler == 0:
-                self.patches = []
-            self.patches = self.patches.append(map + suffix)
-    
-        # if no suffix, processing is simple (e.g. elevation has only 1
-        # band)
-        if len(channel_list) < 2:
-            # run r.mapcalc to crop to region
-            if grass.run_command('r.mapcalc',
-                                 quiet = True,
-                                 expression = "%s = %s" % \
-                                     (map, tmpmapname)) != 0:
-                grass.fatal(_('r.mapcalc failed'))
-            
-            if grass.run_command('r.colors',
-                                 quiet = True,
-                                 map = map,
-                                 rast = tmpmapname) != 0:
-                grass.fatal(_('r.colors failed'))
-    
-        # remove the old channels
-        if grass.run_command('g.remove',
-                             quiet = True,
-                             rast = ','.join(channel_list)) != 0:
-            grass.fatal(_('g.remove failed'))
-        
-    def nowarp_import(self, file, map):
-        """Import raster file into GRASS"""
-        if grass.run_command('r.in.gdal',
-                             quiet = True, overwrite = True,
-                             flags = 'o' + self.gdal_flags,
-                             input = file,
-                             output = map) != 0:
-            grass.fatal(_('r.in.gdal failed'))
-
-        # get a list of channels:
-        pattern = map + '*'
-        grass.debug("pattern: %s" % ','.join(pattern))
-        mapset = grass.gisenv()['MAPSET']
-        channel_list = grass.mlist_grouped(type = 'rast', pattern = pattern, mapset = mapset)
-        grass.debug("channel list: %s" % ','.join(channel_list))
-
-        if len(channel_list) < 2:
-            # test for single band data
-            self.channel_suffixes = []
-        else:
-            self.channel_suffixes = channel_list # ???
-    
-        # add to the list of all suffixes:
-        self.suffixes = self.suffixes + channel.suffixes
-        self.suffixes.sort()
-    
-        for suffix in self.channel_suffixes:
-            # make patch lists
-            suffix = suffix.replace('.', '_')
-            # this is a hack to make the patch lists empty
-            if self.tiler == 0:
-                self.patches = []
-            self.patches = self.patches.append(map + suffix)
-    
-

+ 0 - 101
scripts/r.in.wms/r.in.gdalwarp.py

@@ -1,101 +0,0 @@
-#!/usr/bin/env python
-
-############################################################################
-#
-# MODULE:       r.in.gdalwarp
-#
-# AUTHOR(S):    Cedric Shock, 2006
-#               Pythonized by Martin Landa <landa.martin gmail.com>, 2009
-#
-# PURPOSE:      To warp and import data
-#               (based on Bash script by Cedric Shock)
-#
-# COPYRIGHT:    (C) 2009 Martin Landa, and 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.
-#
-#############################################################################
-
-#%module
-#% description: Warps and imports GDAL supported raster file complete with correct NULL values
-#% keywords: raster
-#% keywords: rotate
-#% keywords: reproject
-#%end
-#%flag
-#% key: p
-#% description: Don't reproject the data, just patch it
-#%end
-#%flag
-#% key: e
-#% description: Extend location extents based on new dataset
-#%end
-#%flag
-#% key: c
-#% description: Make color composite image if possible
-#%end
-#%flag
-#% key: k
-#% description: Keep band numbers instead of using band color names
-#%end
-#%option G_OPT_F_INPUT
-#% label: Name of raster file or files to be imported
-#% description: If multiple files are specified they will be patched together.
-#% multiple: yes
-#%end
-#%option
-#% key: output
-#% type: string
-#% label: Prefix for resultant raster maps.
-#% description: Each band will be name output.bandname
-#% required : yes
-#%end
-#%option
-#% key: s_srs
-#% type: string
-#% description: Source projection in gdalwarp format
-#% required : yes
-#%end
-#%option
-#% key: method
-#% type: string
-#% description: Reprojection method to use
-#% options:near,bilinear,cubic,cubicspline
-#% answer:near
-#% required: yes
-#%end
-#%option
-#% key: warpoptions
-#% type: string
-#% description: Additional options for gdalwarp
-#% required : no
-#%end
-
-import os
-import sys
-import atexit
-
-from grass.script import core as grass
-
-path = os.path.join(os.getenv('GISBASE'), 'etc', 'r.in.wms')
-sys.path.append(path)
-import gdalwarp
-
-def cleanup():
-    if tmp:
-	grass.run_command('g.remove', rast = tmp, quiet = True)
-
-def main():
-    # show progress infromation and grass.info() by default
-    os.environ['GRASS_VERBOSE'] = '1'
-
-    return gdalwarp.GDALWarp(flags, options).run()
-    
-if __name__ == "__main__":
-    options, flags = grass.parser()
-    tmp = None
-    atexit.register(cleanup)
-
-    sys.exit(main())

+ 24 - 85
scripts/r.in.wms/r.in.wms.html

@@ -1,7 +1,7 @@
 <h2>DESCRIPTION</h2>
 <h2>DESCRIPTION</h2>
 
 
-<em>r.in.wms</em> handles all of downloading and importing raster data
-from an <a href="http://www.opengeospatial.org/standards/wms">OGC
+<em>r.in.wms2</em> handles all of downloading and importing raster
+data from an <a href="http://www.opengeospatial.org/standards/wms">OGC
 WMS</a> web mapping server. It need only be told the desired data to
 WMS</a> web mapping server. It need only be told the desired data to
 collect (bounds and resolution) via a region, the server to get the
 collect (bounds and resolution) via a region, the server to get the
 data from, and the layer or layers to get. It downloads the data in
 data from, and the layer or layers to get. It downloads the data in
@@ -9,8 +9,10 @@ tiles, reprojects it, imports it, and patches it back together.
 
 
 <h2>NOTES</h2>
 <h2>NOTES</h2>
 
 
+<!--
 By default data is downloaded to <tt>$GISDBASE/wms_download</tt>. This can be changed
 By default data is downloaded to <tt>$GISDBASE/wms_download</tt>. This can be changed
 by setting the <b>folder</b> option when using <em>r.in.wms</em>.
 by setting the <b>folder</b> option when using <em>r.in.wms</em>.
+-->
 
 
 <p>To understand the data you are getting it is necessary to look at the
 <p>To understand the data you are getting it is necessary to look at the
 capabilities of the WMS server. This should be available via a capabilities
 capabilities of the WMS server. This should be available via a capabilities
@@ -18,120 +20,57 @@ request. This is an
 <a href="http://wms.jpl.nasa.gov/wms.cgi?request=GetCapabilities">example
 <a href="http://wms.jpl.nasa.gov/wms.cgi?request=GetCapabilities">example
 capabilities request to NASA's OnEarth server</a>.
 capabilities request to NASA's OnEarth server</a>.
 
 
-<p><!--
-Some brain-dead servers will only talk to certain web browsers. You can
-fool these by adding <tt>- -user-agent=MSIE5.5</tt> to <b>wgetoptions</b>
-or for curl adding <tt>-A "MSIE5.5"</tt> to <b>curloptions</b>.
--->
-Other brain-dead servers will not accept queries in the form of POST data.
-If you get an error try using the <b>-g</b> flag to force <em>r.in.wms</em>
-to send an atomic GET request instead.
-
 <h2>EXAMPLES</h2>
 <h2>EXAMPLES</h2>
 
 
 <h3>General Get Capabilities Request</h3>
 <h3>General Get Capabilities Request</h3>
 
 
-A capabilities request like
-<a href="http://wms.jpl.nasa.gov/wms.cgi?request=GetCapabilities">http://wms.jpl.nasa.gov/wms.cgi?request=GetCapabilities</a>
-is where you should start. It tells you what data is offered, the projections
-it is in,  where to find meta data, resolutions, scales, and bounds for
-data, etc.
-
-E.g. lists the layers available from the NASA OnEarth server.
-
 <div class="code"><pre>
 <div class="code"><pre>
-r.in.wms mapserver=http://wms.jpl.nasa.gov/wms.cgi -l
+r.in.wms2 -c mapserver=http://wms.cuzk.cz/wms.asp
 </pre></div>
 </pre></div>
 
 
-<h3>US NED Elevation from OnEarth server download (metric units)</h3>
+<h3>CUZK download</h3>
 
 
-Set the resolution to 30 (assuming you're in metric units):
-<div class="code"><pre>
-g.region res=30 -ap
-r.in.wms -o output=elevation_meters mapserver=http://wms.jpl.nasa.gov/wms.cgi \
-         layers=us_ned styles=real
-</pre></div>
-
-Downloads real number meter elevation from OnEarth to cover the current
-region. Uses <b>-o</b> for opaque to get smaller download.
 
 
-<h3>US NED Elevation from OnEarth server download (feet units)</h3>
-
-Set the resolution to 90 (assuming you're in feet units) a save this
-region with a name; this makes resuming downloads possible or rather
-easier:
+World extend data:
 
 
 <div class="code"><pre>
 <div class="code"><pre>
-g.region res=90 -ap
-g.region save=panhandle-90ft
-
-r.in.wms -o output=elevation_feet mapserver=http://wms.jpl.nasa.gov/wms.cgi \
-         layers=us_ned styles=feet_real region=panhandle-90ft
+r.in.wms2 mapserver=http://iceds.ge.ucl.ac.uk/cgi-bin/icedswms layers=bluemarble,landsat_1_01 styles=default,default output=landsat srs=4326 format=png 
 </pre></div>
 </pre></div>
-
-Downloads real number feet elevation from OnEarth to cover the current
-region. Uses <b>-o</b> for opaque to get smaller download. Using a named
-region lets us resume later easily.
+* Server supports only WMS 1.1.1 <br>
 
 
 <div class="code"><pre>
 <div class="code"><pre>
-r.in.wms -d output=elevation_feet mapserver=http://wms.jpl.nasa.gov/wms.cgi \
-         layers=us_ned styles=feet_real -o region=panhandle-90ft method=cubic
+r.in.wms2 mapserver=http://132.156.97.59/cgi-bin/worldmin_en-ca_ows layers=GSC:WORLD_PrecambrianDomains output=pokus srs=4326 format=jpeg 
 </pre></div>
 </pre></div>
+* Server supports only WMS 1.1.1 
+<br>
+<br>
 
 
-Use flag <b>-d</b> to skip ahead to downloading. This could be used to try
-downloading again (if some files failed last time) or to import the data
-differently. Since downloaded files are remembered those already received
-successfully are not re-requested. In this case we are reimporting the
-data using the cubic interpolation method instead of nearest neighbor.
-
-<h3>LANDSAT from OnEarth server download</h3>
+Data in extend of Czech Republic:
 
 
-Set the resolution to 30 meters for LANDSAT:
 <div class="code"><pre>
 <div class="code"><pre>
-g.region res=30 -ap
-r.in.wms layers=global_mosaic mapserver=http://wms.jpl.nasa.gov/wms.cgi \
-         output=wms_global_mosaic
-</pre></div>
-Downloads LANDSAT color scene.
-
-
-<h3>DRG from Terraserver server download</h3>
-
-Set the resolution to 1.2 meters for DRGs. Their native resolution is
-2.4 meters, so this is some pretty hefty oversampling:
-
-<div class="code"><pre>
-g.region res=1.2 -ap
-g.region save=drg-resolution
-
-r.in.wms output=terraserver-drg mapserver=http://terraserver.microsoft.com/ogcmap6.ashx \
-         layers=DRG region=drg-resolution format=jpeg srs=EPSG:26910
+r.in.wms2 output=kn mapserver=http://wms.cuzk.cz/wms.asp layers=prehledka_kraju-linie srs=4326 format=png
 </pre></div>
 </pre></div>
 
 
-Downloads digital raster graphics from Microsoft TerraServer. Note that
-srs will need to be changed to a projection that is appropriate for your
-region.
 
 
 <h2>TODO</h2>
 <h2>TODO</h2>
 
 
 <ul>
 <ul>
-  <li>Use optionally <a href="http://gdal.osgeo.org/frmt_wms.html">GDAL WMS driver</a></li>
+  <li>Implement Tiled WMS</li>
 </ul>
 </ul>
 
 
 <h2>SEE ALSO</h2>
 <h2>SEE ALSO</h2>
 
 
 <em>
 <em>
-<a href="r.tileset.html">r.tileset</a>,
-<a href="r.in.gdal.html">r.in.gdal</a>,
-<a href="r.patch.html">r.patch</a>,
-<a href="r.colors.html">r.colors</a>,
-<a href="r.composite.html">r.composite</a><br><br>
-<a href="v.in.wfs.html">v.in.wfs</a>
+  <a href="r.in.gdal.html">r.in.gdal</a>,
+  <a href="r.patch.html">r.patch</a>,
+  <a href="r.colors.html">r.colors</a>,
+  <a href="r.composite.html">r.composite</a>,
+  <a href="v.in.wfs.html">v.in.wfs</a>
 </em>
 </em>
 
 
 <h2>AUTHORS</h2>
 <h2>AUTHORS</h2>
 
 
-Soeren Gebbert, Jachym Cepicky, and Cedric Shock<br>
-Updated for GRASS 7 by Martin Landa, CTU in Prague, Czech Republic (05/2009)
+Stepan Turek, Czech Technical University in Prague, Czech Republic (bachelor's final project 2012, mentor: Martin Landa) 
 
 
-<p><i>Last changed: $Date$</i>
+<p>
+<i>Last changed: $Date$</i>

+ 99 - 220
scripts/r.in.wms/r.in.wms.py

@@ -1,281 +1,160 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
+"""
+MODULE:    r.in.wms2
 
 
-############################################################################
-#
-# MODULE:       r.in.wms
-#
-# AUTHOR(S):    Cedric Shock, 2006
-#               Upgraded for GRASS 7 by Martin Landa <landa.martin gmail.com>, 2009
-#
-# PURPOSE:      To import data from web mapping servers
-#               (based on Bash script by Cedric Shock)
-#
-# COPYRIGHT:    (C) 2009 Martin Landa, and 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(S): Stepan Turek <stepan.turek AT seznam.cz>
+
+PURPOSE:   Downloads and imports data from WMS server.
+
+COPYRIGHT: (C) 2012 Stepan Turek, and 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.
+"""
 
 
 #%module
 #%module
-#%  description: Downloads and imports data from WMS servers.
-#%  keywords: raster
-#%  keywords: import
-#%  keywords: wms
-#%end
-#%flag
-#% key: l
-#% description: List available layers and exit
-#% guisection: Request
-#%end
-#%flag
-#% key: d
-#% description: Skip to downloading (to resume downloads faster)
-#% guisection: Download
-#%end
-#%flag
-#% key: o
-#% description: Don't request transparent data
-#% guisection: Request
-#%end
-#%flag
-#% key: c
-#% description: Clean existing data out of download directory
-#% guisection: Download
-#%end
-#%flag
-#% key: k
-#% description: Keep band numbers instead of using band color names
-#% guisection: Import
-#%end
-#%flag
-#% key: p
-#% description: Don't reproject the data, just patch it
-#% guisection: Import
-#%end
-#%flag
-#% key: g
-#% label: Use GET method instead of POST data method
-#% description: This may be needed to connect to servers which lack POST capability
-#% guisection: Request
-#%end
-#%flag
-#% key: a
-#% description: Use GDAL WMS driver
-#% guisection: Request
-#%end
-#%option G_OPT_R_OUTPUT
-#% required : no
-#% guisection: Import
+#% description: Downloads and imports data from WMS servers.
+#% keywords: raster
+#% keywords: import
+#% keywords: wms
 #%end
 #%end
+
 #%option
 #%option
 #% key: mapserver
 #% key: mapserver
 #% type: string
 #% type: string
-#% description: Mapserver to request data from
+#% description:URL of WMS server 
 #% required: yes
 #% required: yes
-#% guisection: Request
 #%end
 #%end
+
 #%option
 #%option
 #% key: layers
 #% key: layers
 #% type: string
 #% type: string
 #% description: Layers to request from map server
 #% description: Layers to request from map server
 #% multiple: yes
 #% multiple: yes
-#% required: no
-#% guisection: Request
+#% required: yes
 #%end
 #%end
-#%option
-#% key: styles
-#% type: string
-#% description: Styles to request from map server
-#% multiple: yes
-#% required: no
-#% guisection: Request
+
+#%option G_OPT_R_OUTPUT
+#% description: Name for output raster map
 #%end
 #%end
+
 #%option
 #%option
 #% key: srs
 #% key: srs
+#% type: integer
+#% description: EPSG number of source projection for request 
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: region
 #% type: string
 #% type: string
-#% description: Source projection to request from server
-#% answer:EPSG:4326
-#% guisection: Request
+#% description: Named region to request data for. Current region used if omitted
+#% guisection: Request properties
 #%end
 #%end
+
+#%option
+#% key: wms_version
+#% type:string
+#% description:WMS standard
+#% options:1.1.1,1.3.0
+#% answer:1.1.1
+#% guisection: Request properties
+#%end
+
 #%option
 #%option
 #% key: format
 #% key: format
 #% type: string
 #% type: string
 #% description: Image format requested from the server
 #% description: Image format requested from the server
 #% options: geotiff,tiff,jpeg,gif,png
 #% options: geotiff,tiff,jpeg,gif,png
 #% answer: geotiff
 #% answer: geotiff
-#% required: yes
-#% guisection: Request
+#% guisection: Request properties
 #%end
 #%end
+
 #%option
 #%option
-#% key: wmsquery
-#% type:string
-#% description: Addition query options for server
-#% answer: version=1.1.1
-#% guisection: Request
+#% key: method
+#% type: string
+#% description: Reprojection method to use
+#% options:near,bilinear,cubic,cubicspline
+#% answer:near
+#% guisection: Request properties
 #%end
 #%end
+
 #%option
 #%option
 #% key: maxcols
 #% key: maxcols
-#% type: integer
+#% type:integer
 #% description: Maximum columns to request at a time
 #% description: Maximum columns to request at a time
-#% answer: 1024
-#% required : yes
-#% guisection: Request
+#% answer:400
+#% guisection: Request properties
 #%end
 #%end
+
 #%option
 #%option
 #% key: maxrows
 #% key: maxrows
 #% type: integer
 #% type: integer
 #% description: Maximum rows to request at a time
 #% description: Maximum rows to request at a time
-#% answer: 1024
-#% required : yes
-#% guisection: Request
+#% answer: 300
+#% guisection: Request properties
 #%end
 #%end
+
 #%option
 #%option
-#% key: tileoptions
-#% type: string
-#% description: Additional options for r.tileset
-#% required : no
+#% key: urlparams
+#% type:string
+#% description: Addition query parameters for server (only with 'd' flag)
+#% guisection: Request properties
 #%end
 #%end
+
 #%option
 #%option
-#% key: region
+#% key: styles
 #% type: string
 #% type: string
-#% description: Named region to request data for. Current region used if omitted
-#% required : no
-#% guisection: Request
+#% description: Styles to request from map server
+#% multiple: yes
+#% guisection: Map style
 #%end
 #%end
+
 #%option
 #%option
-#% key: folder
+#% key: bgcolor
 #% type: string
 #% type: string
-#% description: Folder to save downloaded data to (default $GISDBASE/wms_download)
-#% required : no
-#% guisection: Download
+#% description: Color of map background (only with 'd' flag)
+#% guisection: Map style
 #%end
 #%end
-#%option
-#% key: method
-#% type: string
-#% description: Reprojection method to use
-#% options:near,bilinear,cubic,cubicspline
-#% answer:near
-#% required: yes
-#% guisection: Import
+
+#%flag
+#% key: o
+#% description: Don't request transparent data
+#% guisection: Map style
 #%end
 #%end
-#%option
-#% key: cap_file
-#% type: string
-#% label: Filename to save capabilities XML file to
-#% description: Requires list available layers flag
-#% required: no
-#% guisection: Request
+
+#%flag
+#% key: c
+#% description: Get capabilities
+#% guisection: Request properties
+#% suppress_required: yes
+#%end
+
+#%flag
+#% key: d
+#% description: Do not use GDAL WMS driver
 #%end
 #%end
 
 
 import os
 import os
 import sys
 import sys
-import tempfile
-import urllib
-import xml.sax
+sys.path.insert(1, os.path.join(os.path.dirname(sys.path[0]), 'etc', 'r.in.wms2'))
 
 
 import grass.script as grass
 import grass.script as grass
 
 
-wmsPath = os.path.join(os.getenv('GISBASE'), 'etc', 'r.in.wms')
-sys.path.append(wmsPath)
-try:
-    import wms_parse
-    import wms_request
-    import wms_download
-    import gdalwarp
-    import wms_gdal
-except ImportError:
-    pass
-
-def list_layers():
-    """Get list of available layers from WMS server"""
-    qstring = "service=WMS&request=GetCapabilities&" + options['wmsquery']
-    grass.debug("POST-data: %s" % qstring)
-    
-    # download capabilities file
-    grass.verbose("List of layers for server <%s>:" % options['mapserver'])
-    url = options['mapserver'] + '?' + qstring
-    try:
-        if options['cap_file']:
-            cap_file, headers = urllib.urlretrieve(url, options['cap_file'])
-        else:
-            cap_file = urllib.urlopen(url, options['mapserver'] + '?' + qstring)
-    except IOError:
-        grass.fatal(_("Unable to get capabilities of '%s'") % options['mapserver'])
-    
-    # check DOCTYPE first
-    if options['cap_file']:
-        if headers['content-type'] != 'application/vnd.ogc.wms_xml':
-            grass.fatal(_("Unable to get capabilities: %s") % url)
-    else:
-        if cap_file.info()['content-type'] != 'application/vnd.ogc.wms_xml':
-            grass.fatal(_("Unable to get capabilities: %s") % url)
-
-    # parse file with sax
-    cap_xml = wms_parse.ProcessCapFile()
-    try:
-        xml.sax.parse(cap_file, cap_xml)
-    except xml.sax.SAXParseException, err:
-        grass.fatal(_("Reading capabilities failed. "
-                      "Unable to parse XML document: %s") % err)
-    
-    cap_xml.getLayers()
-    
 def main():
 def main():
-    if flags['l']:
-        # list of available layers
-        list_layers()
-        return 0
-    elif not options['output']:
-        grass.fatal(_("No output map specified"))
-    
-    if options['cap_file'] and not flags['l']:
-        grass.warning(_("Option <cap_file> ignored. It requires '-l' flag."))
-    
-    # set directory for download
-    if not options['folder']:
-        options['folder'] = os.path.join(grass.gisenv()['GISDBASE'], 'wms_download')
-    
-    # region settings
-    if options['region']:
-        if not grass.find_file(name = options['region'], element = 'windows')['name']:
-            grass.fatal(_("Region <%s> not found") % options['region'])
-
-    request = wms_request.WMSRequest(flags, options)    
-    if not flags['d']:
-        # request data first
-        request.GetTiles()
-    if not request:
-        grass.fatal(_("WMS request failed"))
-    
-    if flags['a']:
-        # use GDAL WMS driver
-        ### TODO: use GDAL Python bindings instead
-        if not wms_gdal.checkGdalWms():
-            grass.fatal(_("GDAL WMS driver is not available"))
-
-        # create local service description XML file
-        gdalWms = wms_gdal.GdalWms(options, request)
-        options['input'] = gdalWms.GetFile()
+    if flags['d']:
+        grass.debug("Using own driver")
+        from wms_drv import WMSDrv
+        wms = WMSDrv()
     else:
     else:
-        # download data
-        download = wms_download.WMSDownload(flags, options)
-        download.GetTiles(request.GetRequests())
+        grass.debug("Using GDAL WMS driver")
+        from wms_gdal_drv import WMSGdalDrv
+        wms = WMSGdalDrv()
     
     
-        # list of files
-        files = []
-        for item in request.GetRequests():
-            files.append(item['output'])
-        files = ','.join(files)
-        options['input'] = files
-
-    # add flags for r.in.gdalwarp
-    flags['e'] = False
-    flags['c'] = True
-    options['warpoptions'] = ''
-    
-    return gdalwarp.GDALWarp(flags, options).run()
+    if flags['c']:
+        wms.GetCapabilities(options)
+    else:
+        wms.GetMap(options, flags)  
     
     
     return 0
     return 0
 
 

+ 396 - 0
scripts/r.in.wms/wms_base.py

@@ -0,0 +1,396 @@
+import os
+from   math import ceil
+
+import xml.etree.ElementTree as etree
+from urllib2 import urlopen, HTTPError, URLError
+
+import grass.script as grass
+
+class WMSBase:
+    def __init__(self):
+        # these variables are information for destructor
+        self.temp_files_to_cleanup = []
+        self.cleanup_mask   = False
+        self.cleanup_layers = False
+        
+        self.bbox     = None
+        self.temp_map = None
+        
+    def __del__(self):
+        # removes temporary mask, used for import transparent or warped temp_map
+        if self.cleanup_mask:
+            # clear temporary mask, which was set by module      
+            if grass.run_command('r.mask',
+                                 quiet = True,
+                                 flags = 'r') != 0:  
+                grass.fatal(_('%s failed') % 'r.mask')
+            
+            # restore original mask, if exists 
+            if grass.find_file(self.o_output + self.original_mask_suffix, element = 'cell', mapset = '.' )['name']:
+                if grass.run_command('g.copy',
+                                     quiet = True,
+                                     rast =  self.o_output + self.original_mask_suffix + ',MASK') != 0:
+                    grass.fatal(_('%s failed') % 'g.copy')
+        
+        # tries to remove temporary files, all files should be
+        # removoved before, implemented just in case of unexpected
+        # stop of module
+        for temp_file in self.temp_files_to_cleanup:
+            grass.try_remove(temp_file)
+        
+        # remove temporary created rasters
+        if self.cleanup_layers: 
+            maps = []
+            for suffix in ('.red', '.green', '.blue', '.alpha', self.original_mask_suffix):
+                rast = self.o_output + suffix
+                if grass.find_file(rast, element = 'cell', mapset = '.')['file']:
+                    maps.append(rast)
+            
+            if maps:
+                grass.run_command('g.remove',
+                                  quiet = True,
+                                  flags = 'f',
+                                  rast  = ','.join(maps))
+        
+        # deletes enviromental variable which overrides region 
+        if 'GRASS_REGION' in os.environ.keys():
+            os.environ.pop('GRASS_REGION')
+        
+    def _debug(self, fn, msg):
+        grass.debug("%s.%s: %s" %
+                    (self.__class__.__name__, fn, msg))
+        
+    def _initializeParameters(self, options, flags):
+        self._debug("_initialize_parameters", "started")
+        
+        # inicialization of module parameters (options, flags)
+        self.flags = flags 
+        if self.flags['o']:
+            self.transparent = 'FALSE'
+        else:
+            self.transparent = 'TRUE'   
+        
+        self.o_mapserver_url = options['mapserver'].strip() + "?" 
+        self.o_layers = options['layers'].strip()
+        self.o_styles = options['styles'].strip()
+        self.o_output = options['output']
+        self.o_method = options['method']
+        
+        self.o_bgcolor = options['bgcolor'].strip()
+        if self.o_bgcolor != "" and not flags["d"]:
+            grass.warning(_("Parameter bgcolor ignored, use -d flag"))
+        
+        self.o_urlparams = options['urlparams'].strip()
+        if self.o_urlparams != "" and not flags["d"]:
+            grass.warning(_("Parameter urlparams ignored, use -d flag"))
+        
+        self.o_wms_version = options['wms_version']        
+        if self.o_wms_version == "1.3.0":
+            self.projection_name = "CRS"
+        else:
+            self.projection_name = "SRS" 
+        
+        self.o_format = options['format']
+        if self.o_format == "geotiff":
+            self.mime_format = "image/geotiff"
+        elif self.o_format == "tiff":
+            self.mime_format = "image/tiff"
+        elif self.o_format == "png":
+            self.mime_format = "image/png"
+        elif self.o_format == "jpeg":
+            self.mime_format = "image/jpeg"
+            if flags['o']:
+                grass.warning(_("JPEG format does not support transparency"))
+        elif self.o_format == "gif":
+            self.mime_format = "image/gif"
+        else:
+            self.mime_format = self.o_format
+        
+        self.o_srs = int(options['srs'])
+        if self.o_srs <= 0:
+            grass.fatal(_("Invalid EPSG code %d") % self.o_srs)
+        
+        # read projection info
+        self.proj_location = grass.read_command('g.proj', 
+                                                flags ='jf').rstrip('\n')
+        
+        self.proj_srs = grass.read_command('g.proj', 
+                                           flags = 'jf', 
+                                           epsg = str(self.o_srs) ).rstrip('\n')
+        
+        if not self.proj_srs or not self.proj_location:
+            grass.fatal(_("Unable to get projection info"))
+        
+        # set region 
+        self.o_region = options['region']
+	if self.o_region:                 
+            if not grass.find_file(name = self.o_region, element = 'windows', mapset = '.' )['name']:
+                grass.fatal(_("Region <%s> not found") % self.o_region)
+        
+        if self.o_region:
+            s = grass.read_command('g.region',
+                                   quiet = True,
+                                   flags = 'ug',
+                                   region = self.o_region)
+            self.region = grass.parse_key_val(s, val_type = float)
+        else:
+            self.region = grass.region()
+        
+        min_tile_size = 100
+        self.o_maxcols = int(options['maxcols'])
+        if self.o_maxcols <= min_tile_size:
+            grass.fatal(_("Maxcols must be greater than 100"))
+        
+        self.o_maxrows = int(options['maxrows'])
+        if self.o_maxrows <= min_tile_size:
+            grass.fatal(_("Maxrows must be greater than 100"))
+        
+        # setting optimal tile size according to maxcols and maxrows constraint and region cols and rows      
+        self.tile_cols = int(self.region['cols'] / ceil(self.region['cols'] / float(self.o_maxcols)))
+        self.tile_rows = int(self.region['rows'] / ceil(self.region['rows'] / float(self.o_maxrows)))
+        
+        # suffix for existing mask (during overriding will be saved
+        # into raster named:self.o_output + this suffix)
+        self.original_mask_suffix = "_temp_MASK"
+        
+        # check names of temporary rasters, which module may create 
+        maps = []
+        for suffix in ('.red', '.green', '.blue', '.alpha', self.original_mask_suffix ):
+            rast = self.o_output + suffix
+            if grass.find_file(rast, element = 'cell', mapset = '.')['file']:
+                maps.append(rast)
+        
+        if len(maps) != 0:
+            grass.fatal(_("Please change output name, or change names of these rasters: %s, "
+                          "module needs to create this temporary maps during runing") % ",".join(maps))
+        
+        # default format for GDAL library
+        self.gdal_drv_format = "GTiff"
+        
+        self._debug("_initialize_parameters", "finished")
+
+    def GetMap(self, options, flags):
+        """!Download data from WMS server and import data
+        (using GDAL library) into GRASS as a raster map."""
+
+        self._initializeParameters(options, flags)  
+
+        self.bbox     = self._computeBbox()
+        
+        self.temp_map = self._download()  
+        
+        self._createOutputMap() 
+    
+    def GetCapabilities(self, options): 
+        """!Get capabilities from WMS server
+        """
+        # download capabilities file
+        cap_url = options['mapserver'] + "?service=WMS&request=GetCapabilities&version=" + options['wms_version'] 
+        try:
+            cap = urlopen(cap_url)
+        except IOError:
+            grass.fatal(_("Unable to get capabilities from '%s'") % options['mapserver'])
+        
+        cap_lines = cap.readlines()
+        for line in cap_lines: 
+            print line 
+        
+    def _computeBbox(self):
+        """!Get region extent for WMS query (bbox)
+        """
+        self._debug("_computeBbox", "started")
+        
+        bbox_region_items = {'maxy' : 'n', 'miny' : 's', 'maxx' : 'e', 'minx' : 'w'}  
+        bbox = {}
+
+        if self.proj_srs == self.proj_location: # TODO: do it better
+            for bbox_item, region_item in bbox_region_items.iteritems():
+                bbox[bbox_item] = self.region[region_item]
+        
+        # if location projection and wms query projection are
+        # different, corner points of region are transformed into wms
+        # projection and then bbox is created from extreme coordinates
+        # of the transformed points
+        else:
+            for bbox_item, region_item  in bbox_region_items.iteritems():
+                bbox[bbox_item] = None
+
+            temp_region = self._tempfile()
+            
+            try:
+                temp_region_opened = open(temp_region, 'w')
+                temp_region_opened.write("%f %f\n%f %f\n%f %f\n%f %f\n"  %\
+                                       (self.region['e'], self.region['n'],\
+                                        self.region['w'], self.region['n'],\
+                                        self.region['w'], self.region['s'],\
+                                        self.region['e'], self.region['s'] ))
+            except IOError:
+                 grass.fatal(_("Unable to write data into tempfile"))
+            finally:           
+                temp_region_opened.close()            
+            
+            points = grass.read_command('m.proj', flags = 'd',
+                                        proj_output = self.proj_srs,
+                                        proj_input = self.proj_location,
+                                        input = temp_region) # TODO: stdin
+            grass.try_remove(temp_region)
+            if not points:
+                grass.fatal(_("Unable to determine region, %s failed") % 'm.proj')
+            
+            points = points.splitlines()
+            if len(points) != 4:
+                grass.fatal(_("Region defintion: 4 points required"))
+            
+            for point in points:
+                point = map(float, point.split("|"))
+                if not bbox['maxy']:
+                    bbox['maxy'] = point[1]
+                    bbox['miny'] = point[1]
+                    bbox['maxx'] = point[0]
+                    bbox['minx'] = point[0]
+                    continue
+                
+                if   bbox['maxy'] < point[1]:
+                    bbox['maxy'] = point[1]
+                elif bbox['miny'] > point[1]:
+                    bbox['miny'] = point[1]
+                
+                if   bbox['maxx'] < point[0]:
+                    bbox['maxx'] = point[0]
+                elif bbox['minx'] > point[0]:
+                    bbox['minx'] = point[0]  
+        
+        self._debug("_computeBbox", "finished -> %s" % bbox)
+
+        # Ordering of coordinates axis of geographic coordinate
+        # systems in WMS 1.3.0 is fliped. If self.flip_coords is 
+        # True, coords in bbox need to be flipped in WMS query.
+
+        self.flip_coords = False  
+        hasLongLat = self.proj_srs.find("+proj=longlat")   
+        hasLatLong = self.proj_srs.find("+proj=latlong")   
+
+        if (hasLongLat != -1 or hasLatLong != -1) and self.o_wms_version == "1.3.0":
+            self.flip_coords = True
+
+        return bbox
+
+    def _createOutputMap(self): 
+        """!Import downloaded data into GRASS, reproject data if needed
+        using gdalwarp
+        """
+        # reprojection of raster
+        if self.proj_srs != self.proj_location: # TODO: do it better
+            grass.message(_("Reprojecting raster..."))
+            temp_warpmap = self._tempfile()
+            
+            if int(os.getenv('GRASS_VERBOSE', '2')) <= 2:
+                nuldev = file(os.devnull, 'w+')
+            else:
+                nuldev = None
+            
+            # RGB rasters - alpha layer is added for cropping edges of projected raster
+            if self.temp_map_bands_num == 3:
+                ps = grass.Popen(['gdalwarp',
+                                  '-s_srs', '%s' % self.proj_srs,
+                                  '-t_srs', '%s' % self.proj_location,
+                                  '-r', self.o_method, '-dstalpha',
+                                  self.temp_map, temp_warpmap], stdout = nuldev)
+            # RGBA rasters
+            else:
+                ps = grass.Popen(['gdalwarp',
+                                  '-s_srs', '%s' % self.proj_srs,
+                                  '-t_srs', '%s' % self.proj_location,
+                                  '-r', self.o_method,
+                                  self.temp_map, temp_warpmap], stdout = nuldev)
+            ps.wait()
+            
+            if nuldev:
+                nuldev.close()
+            
+            if ps.returncode != 0:
+                grass.fatal(_('%s failed') % 'gdalwarp')
+        # raster projection is same as projection of location
+        else:
+            temp_warpmap = self.temp_map
+        
+        grass.message(_("Importing raster map into GRASS..."))
+        # importing temp_map into GRASS
+        if grass.run_command('r.in.gdal',
+                             quiet = True,
+                             input = temp_warpmap,
+                             output = self.o_output) != 0:
+            grass.fatal(_('%s failed') % 'r.in.gdal')
+        
+        # information for destructor to cleanup temp_layers, created
+        # with r.in.gdal
+        self.cleanup_layers = True
+        
+        # setting region for full extend of imported raster
+        os.environ['GRASS_REGION'] = grass.region_env(rast = self.o_output + '.red')
+        
+        # mask created from alpha layer, which describes real extend
+        # of warped layer (may not be a rectangle), also mask contains
+        # transparent parts of raster
+        if grass.find_file( self.o_output + '.alpha', element = 'cell', mapset = '.' )['name']:
+            # saving current mask (if exists) into temp raster
+            if grass.find_file('MASK', element = 'cell', mapset = '.' )['name']:
+                if grass.run_command('g.copy',
+                                     quiet = True,
+                                     rast = 'MASK,' + self.o_output + self.original_mask_suffix) != 0:    
+                    grass.fatal(_('%s failed') % 'g.copy')
+            
+            # info for destructor
+            self.cleanup_mask = True
+            if grass.run_command('r.mask',
+                                 quiet = True,
+                                 overwrite = True,
+                                 maskcats = "0",
+                                 flags = 'i',
+                                 input = self.o_output + '.alpha') != 0: 
+                grass.fatal(_('%s failed') % 'r.mask')
+        
+        if grass.run_command('r.composite',
+                             quiet = True,
+                             red = self.o_output + '.red',
+                             green = self.o_output +  '.green',
+                             blue = self.o_output + '.blue',
+                             output = self.o_output ) != 0:
+                grass.fatal(_('%s failed') % 'r.composite')
+        
+        grass.try_remove(temp_warpmap)
+        grass.try_remove(self.temp_map) 
+
+    def _flipBbox(self, bbox):
+        """ 
+        flips items in dictionary 
+        value flips between this keys:
+        maxy -> maxx
+        maxx -> maxy
+        miny -> minx
+        minx -> miny
+        @return copy of bbox with fliped cordinates
+        """  
+        temp_bbox = dict(bbox)
+        new_bbox = {}
+        new_bbox['maxy'] = temp_bbox['maxx']
+        new_bbox['miny'] = temp_bbox['minx']
+        new_bbox['maxx'] = temp_bbox['maxy']
+        new_bbox['minx'] = temp_bbox['miny']
+
+        return new_bbox
+
+    def _tempfile(self):
+        """!Create temp_file and append list self.temp_files_to_cleanup 
+            with path of file 
+     
+        @return string path to temp_file
+        """
+        temp_file = grass.tempfile()
+        if temp_file is None:
+            grass.fatal(_("Unable to create temporary files"))
+        
+        # list of created tempfiles for destructor
+        self.temp_files_to_cleanup.append(temp_file)
+        
+        return temp_file

+ 0 - 69
scripts/r.in.wms/wms_download.py

@@ -1,69 +0,0 @@
-############################################################################
-#
-# MODULE:       r.in.wms / wms_download.py
-#
-# AUTHOR(S):    Cedric Shock, 2006
-#               Updated for GRASS 7 by Martin Landa <landa.martin gmail.com>, 2009
-#
-# PURPOSE:      To import data from web mapping servers
-#               (based on Bash script by Cedric Shock)
-#
-# COPYRIGHT:    (C) 2009 Martin Landa, and 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.
-#
-#############################################################################
-
-import os
-import urllib
-
-from grass.script import core as grass
-
-class WMSDownload:
-    def __init__(self, flags, options):
-        self.flags   = flags
-        self.options = options
-        
-    def GetTiles(self, requests):
-        grass.message(_("Downloading tiles..."))
-        
-        i = 0
-        for item in requests:
-            if os.path.exists(item['output']) and \
-                    os.path.getsize(item['output']) > 0:
-                grass.verbose("Tile already downloaded")
-            else:
-                self.GetData(i, item['server'], item['string'], item['output'])
-            i += 1
-        
-    def GetData(self, idx, server, query, output):
-        """Download data"""
-        grass.message(_("Downloading data (tile %d)...") % idx)
-        grass.verbose("Requesting data: %s" % self.options['mapserver'])
-
-        if not self.flags['g']: # -> post
-            try:
-                urllib.urlretrieve(server, output, data = query)
-            except IOError:
-                grass.fatal(_("Failed while downloading the data"))
-            
-            if not os.path.exists(output):
-                grass.fatal(_("Failed while downloading the data"))
-            
-            # work-around for brain-dead ArcIMS servers which want POST-data as part of the GET URL
-            #   (this is technically allowed by OGC WMS def v1.3.0 Sec6.3.4)
-            if os.path.getsize(output) == 0:
-                grass.warning(_("Downloaded image file is empty -- trying another method"))
-                self.flags['g'] = True
-            
-        if self.flags['g']: # -> get
-            try:
-                urllib.urlretrieve(server + '?' + query, output, data = None)
-            except IOError:
-                grass.fatal(_("Failed while downloading the data"))
-            
-            if not os.path.exists(output) or os.path.getsize(output) == 0:
-                grass.fatal(_("Failed while downloading the data"))
-

+ 222 - 0
scripts/r.in.wms/wms_drv.py

@@ -0,0 +1,222 @@
+try:
+    from osgeo import gdal
+    from osgeo import gdalconst 
+except:
+    grass.fatal(_("Unable to load GDAL python bindings"))
+
+from urllib2 import urlopen
+
+import numpy as Numeric
+Numeric.arrayrange = Numeric.arange
+
+import grass.script as grass
+
+from wms_base import WMSBase
+
+class WMSDrv(WMSBase):
+    def _download(self):
+        """!Downloads data from WMS server using own driver
+        
+        @return temp_map with stored downloaded data
+        """ 
+        grass.message(_("Downloading data from WMS server..."))
+        
+
+        proj = self.projection_name + "=EPSG:"+ str(self.o_srs)
+        url = self.o_mapserver_url + "REQUEST=GetMap&VERSION=%s&LAYERS=%s&WIDTH=%s&HEIGHT=%s&STYLES=%s&BGCOLOR=%s&TRANSPARENT=%s" %\
+                  (self.o_wms_version, self.o_layers, self.tile_cols, self.tile_rows, self.o_styles, self.o_bgcolor, self.transparent)
+        url += "&" +proj+ "&" + "FORMAT=" + self.mime_format
+        
+        if self.o_urlparams != "":
+            url +="&" + self.o_urlparams
+        
+        cols = int(self.region['cols'])
+        rows = int(self.region['rows'])
+        
+        # computes parameters of tiles 
+        num_tiles_x = cols / self.tile_cols 
+        last_tile_x_size = cols % self.tile_cols
+        tile_x_length =  float(self.tile_cols) / float(cols ) * (self.bbox['maxx'] - self.bbox['minx']) 
+        
+        last_tile_x = False
+        if last_tile_x_size != 0:
+            last_tile_x = True
+            num_tiles_x = num_tiles_x + 1
+        
+        num_tiles_y = rows / self.tile_rows 
+        last_tile_y_size = rows % self.tile_rows
+        tile_y_length =  float(self.tile_rows) / float(rows) * (self.bbox['maxy'] - self.bbox['miny']) 
+        
+        last_tile_y = False
+        if last_tile_y_size != 0:
+            last_tile_y = True
+            num_tiles_y = num_tiles_y + 1
+        
+        # each tile is downloaded and written into temp_map 
+        tile_bbox = dict(self.bbox)
+        tile_bbox['maxx'] = self.bbox['minx']  + tile_x_length
+        
+        tile_to_temp_map_size_x = self.tile_cols
+        for i_x in range(num_tiles_x):
+            # set bbox for tile i_x,i_y (E, W)
+            if i_x != 0:
+                tile_bbox['maxx'] += tile_x_length 
+                tile_bbox['minx'] += tile_x_length            
+            
+            if i_x == num_tiles_x - 1 and last_tile_x:
+                tile_to_temp_map_size_x = last_tile_x_size 
+            
+            tile_bbox['maxy'] = self.bbox['maxy']                    
+            tile_bbox['miny'] = self.bbox['maxy'] - tile_y_length 
+            tile_to_temp_map_size_y = self.tile_rows       
+            
+            for i_y in range(num_tiles_y):
+                # set bbox for tile i_x,i_y (N, S)
+                if i_y != 0:
+                    tile_bbox['miny'] -= tile_y_length 
+                    tile_bbox['maxy'] -= tile_y_length
+                
+                if i_y == num_tiles_y - 1 and last_tile_y:
+                    tile_to_temp_map_size_y = last_tile_y_size 
+                
+                if self.flip_coords:
+                    # flips coordinates if WMS strandard is 1.3.0 and 
+                    # projection is geographic (see:wms_base.py _computeBbox)
+                    query_bbox = dict(self._flipBbox(tile_bbox))
+                else:
+                    query_bbox = tile_bbox
+
+                query_url = url + "&" + "BBOX=%s,%s,%s,%s" % ( query_bbox['minx'],  query_bbox['miny'],  query_bbox['maxx'],  query_bbox['maxy'])
+                grass.debug(query_url)
+                try: 
+                    wms_data = urlopen(query_url)
+                except IOError:
+                    grass.fatal(_("Unable to fetch data from mapserver"))
+                
+                temp_tile = self._tempfile()
+                
+                # download data into temporary file
+                try:
+                    temp_tile_opened = open(temp_tile, 'w')
+                    temp_tile_opened.write(wms_data.read())
+                except IOError:
+                    grass.fatal(_("Unable to write data into tempfile"))
+                finally:
+                    temp_tile_opened.close()
+                
+                tile_dataset_info = gdal.Open(temp_tile, gdal.GA_ReadOnly) 
+                if tile_dataset_info is None:
+                    # print error xml returned from server
+                    try:
+                        error_xml_opened = open(temp_tile, 'r')
+                        err_str = error_xml_opened.read()     
+                    except IOError:
+                        grass.fatal(_("Unable to read data from tempfile"))
+                    finally:
+                        error_xml_opened.close()
+
+                    if  err_str is not None:
+                        grass.fatal(_("WMS server error: %s") %  err_str)
+                    else:
+                        grass.fatal(_("WMS server unknown error") )
+                
+                band = tile_dataset_info.GetRasterBand(1) 
+                cell_type_func = band.__swig_getmethods__["DataType"]#??
+                bands_number_func = tile_dataset_info.__swig_getmethods__["RasterCount"]
+                
+                ##### see original r.in.wms - file gdalwarp.py line 117 ####
+                temp_tile_pct2rgb = None
+                if bands_number_func(tile_dataset_info) == 1 and band.GetRasterColorTable() is not None:
+                    # expansion of color table into bands 
+                    temp_tile_pct2rgb = self._tempfile()
+                    tile_dataset = self._pct2rgb(temp_tile, temp_tile_pct2rgb)
+                else: 
+                    tile_dataset = tile_dataset_info
+                
+                # initialization of temp_map_dataset, where all tiles are merged
+                if i_x == 0 and i_y == 0:
+                    temp_map = self._tempfile()
+                    
+                    driver = gdal.GetDriverByName(self.gdal_drv_format)
+                    metadata = driver.GetMetadata()
+                    if not metadata.has_key(gdal.DCAP_CREATE) or \
+                           metadata[gdal.DCAP_CREATE] == 'NO':
+                        grass.fatal(_('Driver %s does not supports Create() method') % drv_format)  
+                    
+                    self.temp_map_bands_num = bands_number_func(tile_dataset)
+                    temp_map_dataset = driver.Create(temp_map, int(cols), int(rows),
+                                                     self.temp_map_bands_num, cell_type_func(band));
+                
+                # tile written into temp_map
+                tile_to_temp_map = tile_dataset.ReadRaster(0, 0, tile_to_temp_map_size_x, tile_to_temp_map_size_y,
+                                                                 tile_to_temp_map_size_x, tile_to_temp_map_size_y)
+                
+                temp_map_dataset.WriteRaster(self.tile_cols * i_x, self.tile_rows * i_y,
+                                             tile_to_temp_map_size_x,  tile_to_temp_map_size_y, tile_to_temp_map) 
+                
+                tile_dataset = None
+                tile_dataset_info = None
+                grass.try_remove(temp_tile)
+                grass.try_remove(temp_tile_pct2rgb)    
+        
+        # georeferencing and setting projection of temp_map
+        projection = grass.read_command('g.proj', 
+                                        flags = 'wf',
+                                        epsg =self.o_srs).rstrip('\n')
+        temp_map_dataset.SetProjection(projection)
+        
+
+
+        pixel_x_length = (self.bbox['maxx'] - self.bbox['minx']) / int(cols)
+        pixel_y_length = (self.bbox['miny'] - self.bbox['maxy']) / int(rows)
+        geo_transform = [ self.bbox['minx'] , pixel_x_length  , 0.0 ,  self.bbox['maxy'] , 0.0 , pixel_y_length ] 
+        temp_map_dataset.SetGeoTransform(geo_transform )
+        temp_map_dataset = None
+        
+        return temp_map
+    
+    def _pct2rgb(self, src_filename, dst_filename):
+        """!Create new dataset with data in dst_filename with bands according to src_filename 
+        raster color table - modified code from gdal utility pct2rgb
+        
+        @return new dataset
+        """  
+        out_bands = 4
+        band_number = 1
+        
+        # open source file
+        src_ds = gdal.Open(src_filename)
+        if src_ds is None:
+            grass.fatal(_('Unable to open %s ' % src_filename))
+            
+        src_band = src_ds.GetRasterBand(band_number)
+        
+        # Build color table
+        lookup = [ Numeric.arrayrange(256), 
+                   Numeric.arrayrange(256), 
+                   Numeric.arrayrange(256), 
+                   Numeric.ones(256)*255 ]
+        
+        ct = src_band.GetRasterColorTable()	
+        if ct is not None:
+            for i in range(min(256,ct.GetCount())):
+                entry = ct.GetColorEntry(i)
+                for c in range(4):
+                    lookup[c][i] = entry[c]
+        
+        # create the working file
+        gtiff_driver = gdal.GetDriverByName(self.gdal_drv_format)
+        tif_ds = gtiff_driver.Create(dst_filename,
+                                     src_ds.RasterXSize, src_ds.RasterYSize, out_bands)
+        
+        # do the processing one scanline at a time
+        for iY in range(src_ds.RasterYSize):
+            src_data = src_band.ReadAsArray(0,iY,src_ds.RasterXSize,1)
+            
+            for iBand in range(out_bands):
+                band_lookup = lookup[iBand]
+                
+                dst_data = Numeric.take(band_lookup,src_data)
+                tif_ds.GetRasterBand(iBand+1).WriteArray(dst_data,0,iY)
+        
+        return tif_ds       

+ 0 - 93
scripts/r.in.wms/wms_gdal.py

@@ -1,93 +0,0 @@
-############################################################################
-#
-# MODULE:       r.in.wms / wms_gdal
-#
-# AUTHOR(S):    Martin Landa <landa.martin gmail.com>
-#
-# PURPOSE:      To import data from web mapping servers
-#
-# COPYRIGHT:    (C) 2009 Martin Landa, and 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.
-#
-#############################################################################
-
-import os
-import subprocess
-
-def checkGdalWms():
-    """Check if GDAL WMS driver is available"""
-    ps = subprocess.Popen(['gdalinfo',
-                            '--formats'], stdout = subprocess.PIPE)
-    
-    for line in ps.communicate()[0].splitlines():
-        driver, desc = line.split(':')
-        if 'WMS' in driver:
-            return True
-    
-    return False
-
-class GdalWms:
-    def __init__(self, options, request):
-        self.options = options
-
-        # service description XML file path
-        self.descFile = None
-        self.__createDescFile(request)
-        
-    def __createDescFile(self, request):
-        """Create local service description XML file"""
-        # first create directory where to store XML file
-        dir = os.path.join(self.options['folder'], self.options['output'])
-        if not os.path.exists(self.options['folder']):
-            os.mkdir(self.options['folder'])
-        if not os.path.exists(dir):
-            os.mkdir(dir)
-
-        self.descFile = os.path.join(dir, self.options['output'] + '.xml')
-        file = open(self.descFile, 'w')
-        try:
-            indent = 0
-            file.write('<GDAL_WMS>\n')
-            indent += 4
-            file.write('%s<Service name="WMS">\n' % (' ' * indent))
-            indent += 4
-            if self.options['wmsquery'] and 'version=' in self.options['wmsquery']:
-                for item in self.options['wmsquery'].split(';'):
-                    key, value = item.split('=')
-                    if key == 'version':
-                        file.write('%s<Version>%s</Version>\n' % (' ' * indent, value))
-                        break
-            else:
-                file.write('%s<Version>1.1.1</Version>\n' % (' ' * indent)) # -> default 1.1.1
-            file.write('%s<ServerURL>%s?</ServerURL>\n' % (' ' * indent, self.options['mapserver']))
-            file.write('%s<SRS>%s</SRS>\n' % (' ' * indent, self.options['srs']))
-            file.write('%s<ImageFormat>image/%s</ImageFormat>\n' % (' ' * indent, self.options['format']))
-            file.write('%s<Layers>%s</Layers>\n' % (' ' * indent, self.options['layers']))
-            file.write('%s<Styles>%s</Styles>\n' % (' ' * indent, self.options['styles']))
-            indent -= 4
-            file.write('%s</Service>\n' % (' ' * indent))
-            file.write('%s<DataWindow>\n' % (' ' * indent))
-            indent += 4
-            file.write('%s<UpperLeftX>%s</UpperLeftX>\n' % (' ' * indent, request.Get('w')))
-            file.write('%s<UpperLeftY>%s</UpperLeftY>\n' % (' ' * indent, request.Get('n')))
-            file.write('%s<LowerRightX>%s</LowerRightX>\n' % (' ' * indent, request.Get('e')))
-            file.write('%s<LowerRightY>%s</LowerRightY>\n' % (' ' * indent, request.Get('s')))
-            file.write('%s<SizeX>%s</SizeX>\n' % (' ' * indent, request.Get('width'))) #
-            file.write('%s<SizeY>%s</SizeY>\n' % (' ' * indent, request.Get('height'))) #
-            indent -= 4
-            file.write('%s</DataWindow>\n' % (' ' * indent))
-            file.write('%s<Projection>%s</Projection>\n' % (' ' * indent, self.options['srs']))
-            file.write('%s<BandsCount>3</BandsCount>\n' % (' ' * indent))
-            file.write('%s<BlockSizeX>%s</BlockSizeX>\n' % (' ' * indent, self.options['maxcols']))
-            file.write('%s<BlockSizeY>%s</BlockSizeY>\n' % (' ' * indent, self.options['maxrows']))
-            file.write('</GDAL_WMS>\n')
-        finally:
-            file.close()
-
-    def GetFile(self):
-        """Get path of service description XML file"""
-        return self.descFile
-

+ 138 - 0
scripts/r.in.wms/wms_gdal_drv.py

@@ -0,0 +1,138 @@
+import os
+
+try:
+    from osgeo import gdal
+    from osgeo import gdalconst
+except:
+    grass.fatal(_("Unable to load GDAL Python bindings"))
+
+import xml.etree.ElementTree as etree
+
+import grass.script as grass
+
+from wms_base import WMSBase
+
+class NullDevice():
+    def write(self, s):
+        pass
+
+class WMSGdalDrv(WMSBase):
+    def _createXML(self):
+        """!Create XML for GDAL WMS driver
+        
+        @return path to XML file
+        """
+        self._debug("_createXML", "started")
+        
+        gdal_wms = etree.Element("GDAL_WMS")
+        service = etree.SubElement(gdal_wms, "Service")
+        name = etree.Element("name")
+        service.set("name","WMS")
+        
+        version = etree.SubElement(service, "Version")
+        version.text =self.o_wms_version
+        
+        server_url = etree.SubElement(service, "ServerUrl")
+        server_url.text =self.o_mapserver_url
+        
+        srs = etree.SubElement(service, self.projection_name)   
+        srs.text = 'EPSG:' + str(self.o_srs)
+        
+        image_format = etree.SubElement(service, "ImageFormat")
+        image_format.text = self.mime_format
+        
+        image_format = etree.SubElement(service, "Transparent")
+        image_format.text = self.transparent
+        
+        layers = etree.SubElement(service, "Layers")
+        layers.text = self.o_layers
+        
+        styles = etree.SubElement(service, "Styles")
+        styles.text = self.o_styles
+        
+        data_window = etree.SubElement(gdal_wms, "DataWindow")
+        
+        upper_left_x = etree.SubElement(data_window, "UpperLeftX")
+        upper_left_x.text = str(self.bbox['minx']) 
+        
+        upper_left_y = etree.SubElement(data_window, "UpperLeftY")
+        upper_left_y.text = str(self.bbox['maxy']) 
+        
+        lower_right_x = etree.SubElement(data_window, "LowerRightX")
+        lower_right_x.text = str(self.bbox['maxx']) 
+        
+        lower_right_y = etree.SubElement(data_window, "LowerRightY")
+        lower_right_y.text = str(self.bbox['miny'])
+        
+        size_x = etree.SubElement(data_window, "SizeX")
+        size_x.text = str(self.region['cols']) 
+        
+        size_y = etree.SubElement(data_window, "SizeY")
+        size_y.text = str(self.region['rows']) 
+        
+        # RGB + alpha
+        self.temp_map_bands_num = 4
+        block_size_x = etree.SubElement(gdal_wms, "BandsCount")
+        block_size_x.text = str(self.temp_map_bands_num)
+        
+        block_size_x = etree.SubElement(gdal_wms, "BlockSizeX")
+        block_size_x.text = str(self.tile_cols) 
+        
+        block_size_y = etree.SubElement(gdal_wms, "BlockSizeY")
+        block_size_y.text = str(self.tile_rows)
+        
+        xml_file = self._tempfile()
+        
+        etree.ElementTree(gdal_wms).write(xml_file)
+        
+        self._debug("_createXML", "finished -> %s" % xml_file)
+        
+        return xml_file
+    
+    def _download(self):
+        """!Downloads data from WMS server using GDAL WMS driver
+        
+        @return temp_map with stored downloaded data
+        """
+        grass.message("Downloading data from WMS server...")
+
+        # GDAL WMS driver does not flip geographic coordinates 
+        # according to WMS standard 1.3.0.
+        if self.flip_coords and self.o_wms_version == "1.3.0":
+            grass.warning(_("If module will not be able to fetch the data in this\
+                           geographic projection, \n try flag -d or use WMS version 1.1.1."))
+
+        self._debug("_download", "started")
+        
+        temp_map = self._tempfile()        
+
+        xml_file = self._createXML()
+        wms_dataset = gdal.Open(xml_file, gdal.GA_ReadOnly)
+        grass.try_remove(xml_file)
+        if wms_dataset is None:
+            grass.fatal(_("Unable to open GDAL WMS driver"))
+        
+        self._debug("_download", "GDAL dataset created")
+        
+        driver = gdal.GetDriverByName(self.gdal_drv_format)
+        if driver is None:
+            grass.fatal(_("Unable to find %s driver" % format))
+        
+        metadata = driver.GetMetadata()
+        if not metadata.has_key(gdal.DCAP_CREATECOPY) or \
+           metadata[gdal.DCAP_CREATECOPY] == 'NO':
+            grass.fatal(_('Driver %s supports CreateCopy() method.') % self.gdal_drv_name)
+        
+        self._debug("_download", "calling GDAL CreateCopy...")
+        
+        temp_map_dataset = driver.CreateCopy(temp_map, wms_dataset, 0)
+        
+        if temp_map_dataset is None:
+            grass.fatal(_("Incorrect WMS query"))
+        
+        temp_map_dataset  = None
+        wms_dataset = None
+        
+        self._debug("_download", "finished")
+        
+        return temp_map

+ 0 - 84
scripts/r.in.wms/wms_parse.py

@@ -1,84 +0,0 @@
-############################################################################
-#
-# MODULE:       r.in.wms / wms_parse
-#
-# AUTHOR(S):    Cedric Shock, 2006
-#               Upgraded for GRASS 7 by Martin Landa <landa.martin gmail.com>, 2009
-#
-# PURPOSE:      To import data from web mapping servers
-#               (based on Bash script by Cedric Shock)
-#
-# COPYRIGHT:    (C) 2009 Martin Landa, and 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.
-#
-#############################################################################
-
-import xml.sax
-import xml.sax.handler
-HandlerBase=xml.sax.handler.ContentHandler
-from xml.sax import make_parser
-
-class ProcessCapFile(HandlerBase):
-    """
-    A SAX handler for the capabilities file
-    """
-    def __init__(self):
-        self.inTag = {}
-        for tag in ('layer', 'name', 'style',
-                    'title', 'srs'):
-            self.inTag[tag] = False
-        self.value = ''
-        
-        self.layers = []
-        
-    def startElement(self, name, attrs):
-        if self.inTag.has_key(name.lower()):
-            self.inTag[name.lower()] = True
-        
-        if name.lower() == 'layer':
-            self.layers.append({})
-        
-    def endElement(self, name):
-        if self.inTag.has_key(name.lower()):
-            self.inTag[name.lower()] = False
-        
-        for tag in ('name', 'title', 'srs'):
-            if name.lower() != tag:
-                continue
-            if self.inTag['style']:
-                if not self.layers[-1].has_key('style'):
-                    self.layers[-1]['style'] = {}
-                if not self.layers[-1]['style'].has_key(tag):
-                    self.layers[-1]['style'][tag] = []
-                self.layers[-1]['style'][tag].append(self.value)
-            elif self.inTag['layer']:
-                self.layers[-1][tag] = self.value
-            
-        if name.lower() in ('name', 'title', 'srs'):
-            self.value = ''
-        
-    def characters(self, ch):
-        if self.inTag['name'] or \
-                self.inTag['title'] or \
-                self.inTag['srs']:
-            self.value += ch
-        
-    def getLayers(self):
-        """Print list of layers"""
-        for ly in self.layers:
-            print "\n\n-=-=-=-=-=-\n"
-	    if ly.has_key('name'):
-                print "LAYER: " + ly['name']
-            else:
-                print "LAYER: unknown"
-            if ly.has_key('title'):
-                print "  Title: " + ly['title']
-            if ly.has_key('srs'):
-                print "  SRS: " + ly['srs']
-            if ly.has_key('style'):
-                for idx in range(len(ly['style']['name'])):
-                    print "  STYLE: " + ly['style']['name'][idx]
-                    print "    Style title: " + ly['style']['title'][idx]

+ 0 - 187
scripts/r.in.wms/wms_request.py

@@ -1,187 +0,0 @@
-############################################################################
-#
-# MODULE:       r.in.wms / wms_request.py
-#
-# AUTHOR(S):    Cedric Shock, 2006
-#               Update for GRASS 7 by Martin Landa <landa.martin gmail.com>, 2009
-#
-# PURPOSE:      To import data from web mapping servers
-#               (based on Bash script by Cedric Shock)
-#
-# COPYRIGHT:    (C) 2009 Martin Landa, and 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.
-#
-#############################################################################
-
-import os
-import glob
-from grass.script import core as grass
-
-class WMSRequest:
-    def __init__(self, flags, options):
-        self.flags   = flags
-        self.options = options
-        
-        self.__set_options()
-
-        self.data = {}
-        
-    def __set_options(self):
-        # if the user asserts that this projection is the same as the
-        # source use this projection as the source to get a trivial
-        # tiling from r.tileset
-        if self.flags['p']:
-            self.proj_srs = grass.read_command('g.proj', flags='j')
-            if not self.proj_srs:
-                grass.fatal(_('g.proj failed'))
-            self.srs_scale = int(grass.parse_key_val(proj_srs['+to_meter']))
-        else:
-            self.proj_srs = '+init=%s' % self.options['srs'].lower()
-            self.srs_scale = 1
-        
-        # options for r.tileset
-        self.tileset_options = grass.parse_key_val(self.options['tileoptions'])
-        if self.options['region']:
-            self.tileset_options['region'] = self.options['region']
-        
-        # set transparency
-        if self.flags['o']:
-            self.transparency = "transparent=FALSE"
-        else:
-            self.transparency = "transparent=FALSE"
-        
-        # image format
-        format_opt = self.options['format']
-        if format_opt == "geotiff":
-            self.format      = "image/geotiff"
-            self.worldfile   = ".tfw"
-            self.file_extent = ".geotiff"
-        elif format_opt == "tiff":
-            self.format      = "image/tiff"
-            self.worldfile   = ".tfw"
-            self.file_extent = ".tiff"
-        elif format_opt == "png":
-            self.format      = "image/png"
-            self.worldfile   = ".pgw"
-            self.file_extent = ".png"
-        elif format_opt == "jpeg":
-            self.format      = "image/jpeg"
-            self.worldfile   = ".jgw"
-            self.file_extent = ".jpeg"
-        elif format_opt == "gif":
-            self.format      = "image/gif"
-            self.worldfile   = ".gfw"
-            self.file_extent = ".gif"
-        else:
-            grass.fatal(_("Uknown image format '%s'") % format_opt)
-        
-        # create download directory
-        if not os.path.exists(self.options['folder']):
-            os.mkdir(self.options['folder'])
-        odir = os.path.join(self.options['folder'], self.options['output'])
-        if not os.path.exists(odir):
-            os.mkdir(odir)
-        self._tdir = os.path.join(self.options['folder'], self.options['output'],
-                                  self.options['region'])
-        if not os.path.exists(self._tdir):
-            os.mkdir(self._tdir)
-        
-        self.request_file = os.path.join(self._tdir, 'request')
-        
-    def GetRequestFile(self):
-        return self.request_file
-    
-    def GetRequests(self):
-        ret = []
-        rf = open(self.request_file)
-        try:
-            for line in rf.readlines():
-                ret.append(grass.parse_key_val(line, vsep = ';'))
-        finally:
-            rf.close()
-        
-        return ret
-    
-    def GetTiles(self):
-        grass.message(_("Calculating tiles..."))
-        tiles = grass.read_command('r.tileset',
-                                quiet = True,
-                                flags = 'g',
-                                sourceproj = self.proj_srs,
-                                sourcescale = self.srs_scale,
-                                overlap = 2,
-                                maxcols = int(self.options['maxcols']),
-                                maxrows = int(self.options['maxrows']),
-                                **self.tileset_options)
-        if not tiles:
-            grass.fatal(_("r.tileset failed"))
-        tiles = tiles.splitlines()
-        
-        if self.flags['c']:
-            rmfiles = os.path.join(self._tdir, '*')
-            grass.verbose("Removing files '%s'" % rmfiles)
-            for file in glob.glob(rmfiles):
-                if os.path.isdir(file):
-                    os.rmdir(file)
-                else:
-                    os.remove(file)
-        
-        rf = open(self.request_file, 'w')
-        i = 0
-        for tile in tiles:
-            outputfile = os.path.join(self._tdir, str(i) + self.file_extent)
-            worldfile = os.path.join(self._tdir, str(i) + self.worldfile)
-            dtile = grass.parse_key_val(tile, vsep=';')
-            n = float(dtile['n'])
-            self.data['n'] = n
-            s = float(dtile['s'])
-            self.data['s'] = s
-            e = float(dtile['e'])
-            self.data['e'] = e
-            w = float(dtile['w'])
-            self.data['w'] = w
-            nr = int(dtile['rows'])
-            nc = int(dtile['cols'])
-            self.data['width'] = nc
-            self.data['height'] = nr
-            
-            size = "bbox=%f,%f,%f,%f&width=%d&height=%d" % \
-                (w, s, e, n, nc, nr)
-            xres = (e - w) / nc
-            yres = (s - n) / nr
-            # center of top left cell
-            top_left_cell_center_x = w + xres / 2
-            top_left_cell_center_y = n + yres / 2
-            
-            # write the world file
-            wf = open(worldfile, 'w')
-            try:
-                wf.write("%f\n0.0\n0.0\n%f\n%f\n%f\n" % \
-                             (xres, yres, top_left_cell_center_x, top_left_cell_center_y))
-            finally:
-                wf.close()
-            
-            # request for data
-            string = "service=WMS&request=GetMap&layers=%s&styles=%s&srs=%s&%s&format=%s&%s&%s" % \
-                (self.options['layers'], self.options['styles'], self.options['srs'],
-                 size, self.format, self.transparency, self.options['wmsquery'])
-            rf.write('output=%s;server=%s;string=%s\n' % \
-                         (outputfile, self.options['mapserver'], string))
-            i += 1
-            
-        rf.close()
-        grass.message(_("Done: requesting %d tiles") % len(tiles))
-        if len(tiles) > 200:
-	    grass.warning("Proceed with care. This number of tiles may \
-	      exceed the maximum command line arguments available from \
-	      the operating system later on in the r.in.gdalwarp step. \
-	      In addition it may be considered abusive behaivor by the \
-	      server providers - check their terms of use.")
-
-
-    def Get(self, key):
-        """Get value"""
-        return self.data[key]