wms_request.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. ############################################################################
  2. #
  3. # MODULE: r.in.wms / wms_request.py
  4. #
  5. # AUTHOR(S): Cedric Shock, 2006
  6. # Update for GRASS 7 by Martin Landa <landa.martin gmail.com>, 2009
  7. #
  8. # PURPOSE: To import data from web mapping servers
  9. # (based on Bash script by Cedric Shock)
  10. #
  11. # COPYRIGHT: (C) 2009 Martin Landa, and GRASS development team
  12. #
  13. # This program is free software under the GNU General
  14. # Public License (>=v2). Read the file COPYING that
  15. # comes with GRASS for details.
  16. #
  17. #############################################################################
  18. import os
  19. import glob
  20. from grass.script import core as grass
  21. class WMSRequest:
  22. def __init__(self, flags, options):
  23. self.flags = flags
  24. self.options = options
  25. self.__set_options()
  26. self.data = {}
  27. def __set_options(self):
  28. # if the user asserts that this projection is the same as the
  29. # source use this projection as the source to get a trivial
  30. # tiling from r.tileset
  31. if self.flags['p']:
  32. self.proj_srs = grass.read_command('g.proj', flags='j')
  33. if not self.proj_srs:
  34. grass.fatal(_('g.proj failed'))
  35. self.srs_scale = int(grass.parse_key_val(proj_srs['+to_meter']))
  36. else:
  37. self.proj_srs = '+init=%s' % self.options['srs'].lower()
  38. self.srs_scale = 1
  39. # options for r.tileset
  40. self.tileset_options = grass.parse_key_val(self.options['tileoptions'])
  41. if self.options['region']:
  42. self.tileset_options['region'] = self.options['region']
  43. # set transparency
  44. if self.flags['o']:
  45. self.transparency = "transparent=FALSE"
  46. else:
  47. self.transparency = "transparent=FALSE"
  48. # image format
  49. format_opt = self.options['format']
  50. if format_opt == "geotiff":
  51. self.format = "image/geotiff"
  52. self.worldfile = ".tfw"
  53. self.file_extent = ".geotiff"
  54. elif format_opt == "tiff":
  55. self.format = "image/tiff"
  56. self.worldfile = ".tfw"
  57. self.file_extent = ".tiff"
  58. elif format_opt == "png":
  59. self.format = "image/png"
  60. self.worldfile = ".pgw"
  61. self.file_extent = ".png"
  62. elif format_opt == "jpeg":
  63. self.format = "image/jpeg"
  64. self.worldfile = ".jgw"
  65. self.file_extent = ".jpeg"
  66. elif format_opt == "gif":
  67. self.format = "image/gif"
  68. self.worldfile = ".gfw"
  69. self.file_extent = ".gif"
  70. else:
  71. grass.fatal(_("Uknown image format '%s'") % format_opt)
  72. # create download directory
  73. if not os.path.exists(self.options['folder']):
  74. os.mkdir(self.options['folder'])
  75. odir = os.path.join(self.options['folder'], self.options['output'])
  76. if not os.path.exists(odir):
  77. os.mkdir(odir)
  78. self._tdir = os.path.join(self.options['folder'], self.options['output'],
  79. self.options['region'])
  80. if not os.path.exists(self._tdir):
  81. os.mkdir(self._tdir)
  82. self.request_file = os.path.join(self._tdir, 'request')
  83. def GetRequestFile(self):
  84. return self.request_file
  85. def GetRequests(self):
  86. ret = []
  87. rf = open(self.request_file)
  88. try:
  89. for line in rf.readlines():
  90. ret.append(grass.parse_key_val(line, vsep = ';'))
  91. finally:
  92. rf.close()
  93. return ret
  94. def GetTiles(self):
  95. grass.message(_("Calculating tiles..."))
  96. tiles = grass.read_command('r.tileset',
  97. quiet = True,
  98. flags = 'g',
  99. sourceproj = self.proj_srs,
  100. sourcescale = self.srs_scale,
  101. overlap = 2,
  102. maxcols = int(self.options['maxcols']),
  103. maxrows = int(self.options['maxrows']),
  104. **self.tileset_options)
  105. if not tiles:
  106. grass.fatal(_("r.tileset failed"))
  107. tiles = tiles.splitlines()
  108. if self.flags['c']:
  109. rmfiles = os.path.join(self._tdir, '*')
  110. grass.verbose("Removing files '%s'" % rmfiles)
  111. for file in glob.glob(rmfiles):
  112. if os.path.isdir(file):
  113. os.rmdir(file)
  114. else:
  115. os.remove(file)
  116. rf = open(self.request_file, 'w')
  117. i = 0
  118. for tile in tiles:
  119. outputfile = os.path.join(self._tdir, str(i) + self.file_extent)
  120. worldfile = os.path.join(self._tdir, str(i) + self.worldfile)
  121. dtile = grass.parse_key_val(tile, vsep=';')
  122. n = float(dtile['n'])
  123. self.data['n'] = n
  124. s = float(dtile['s'])
  125. self.data['s'] = s
  126. e = float(dtile['e'])
  127. self.data['e'] = e
  128. w = float(dtile['w'])
  129. self.data['w'] = w
  130. nr = int(dtile['rows'])
  131. nc = int(dtile['cols'])
  132. self.data['width'] = nc
  133. self.data['height'] = nr
  134. size = "bbox=%f,%f,%f,%f&width=%d&height=%d" % \
  135. (w, s, e, n, nc, nr)
  136. xres = (e - w) / nc
  137. yres = (s - n) / nr
  138. # center of top left cell
  139. top_left_cell_center_x = w + xres / 2
  140. top_left_cell_center_y = n + yres / 2
  141. # write the world file
  142. wf = open(worldfile, 'w')
  143. try:
  144. wf.write("%f\n0.0\n0.0\n%f\n%f\n%f\n" % \
  145. (xres, yres, top_left_cell_center_x, top_left_cell_center_y))
  146. finally:
  147. wf.close()
  148. # request for data
  149. string = "service=WMS&request=GetMap&layers=%s&styles=%s&srs=%s&%s&format=%s&%s&%s" % \
  150. (self.options['layers'], self.options['styles'], self.options['srs'],
  151. size, self.format, self.transparency, self.options['wmsquery'])
  152. rf.write('output=%s;server=%s;string=%s\n' % \
  153. (outputfile, self.options['mapserver'], string))
  154. i += 1
  155. rf.close()
  156. grass.message(_("Done: requesting %d tiles") % len(tiles))
  157. if len(tiles) > 200:
  158. grass.warning("Proceed with care. This number of tiles may \
  159. exceed the maximum command line arguments available from \
  160. the operating system later on in the r.in.gdalwarp step. \
  161. In addition it may be considered abusive behaivor by the \
  162. server providers - check their terms of use.")
  163. def Get(self, key):
  164. """Get value"""
  165. return self.data[key]