r.shaded.relief.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #!/usr/bin/env python
  2. ############################################################################
  3. #
  4. # MODULE: r.shaded.relief
  5. # AUTHOR(S): CERL
  6. # parameters standardized: Markus Neteler, 2008
  7. # updates: Michael Barton, 2004
  8. # updates: Gordon Keith, 2003
  9. # updates: Andreas Lange, 2001
  10. # updates: David Finlayson, 2001
  11. # updates: Markus Neteler, 2001, 1999
  12. # Converted to Python by Glynn Clements
  13. # PURPOSE: Creates shaded relief map from raster elevation map (DEM)
  14. # COPYRIGHT: (C) 1999 - 2008, 2010 by the GRASS Development Team
  15. #
  16. # This program is free software under the GNU General Public
  17. # License (>=v2). Read the file COPYING that comes with GRASS
  18. # for details.
  19. #
  20. #############################################################################
  21. #
  22. # July 2007 - allow input from other mapsets (Brad Douglas)
  23. #
  24. # May 2005 - fixed wrong units parameter (Markus Neteler)
  25. #
  26. # September 2004 - Added z exaggeration control (Michael Barton)
  27. # April 2004 - updated for GRASS 5.7 by Michael Barton
  28. #
  29. # 9/2004 Adds scale factor input (as per documentation); units set scale only if specified for lat/long regions
  30. # Also, adds option of controlling z-exaggeration.
  31. #
  32. # 6/2003 fixes for Lat/Long Gordon Keith <gordon.keith@csiro.au>
  33. # If n is a number then the ewres and nsres are mulitplied by that scale
  34. # to calculate the shading.
  35. # If n is the letter M (either case) the number of metres is degree of
  36. # latitude is used as the scale.
  37. # If n is the letter f then the number of feet in a degree is used.
  38. # It scales latitude and longitude equally, so it's only approximately
  39. # right, but for shading its close enough. It makes the difference
  40. # between an unusable and usable shade.
  41. #
  42. # 10/2001 fix for testing for dashes in raster file name
  43. # by Andreas Lange <andreas.lange@rhein-main.de>
  44. # 10/2001 added parser support - Markus Neteler
  45. # 9/2001 fix to keep NULLs as is (was value 22 before) - Markus Neteler
  46. # 1/2001 fix for NULL by David Finlayson <david_finlayson@yahoo.com>
  47. # 11/99 updated $ewres to ewres() and $nsres to nsres()
  48. # updated number to FP in r.mapcalc statement Markus Neteler
  49. #%module
  50. #% description: Creates shaded relief map from an elevation map (DEM).
  51. #% keywords: raster
  52. #% keywords: elevation
  53. #%end
  54. #%option G_OPT_R_INPUT
  55. #% description: Name of input elevation raster map
  56. #%end
  57. #%option G_OPT_R_OUTPUT
  58. #%end
  59. #%option
  60. #% key: altitude
  61. #% type: double
  62. #% description: Altitude of the sun in degrees above the horizon
  63. #% required: no
  64. #% options : 0-90
  65. #% answer: 30
  66. #%end
  67. #%option
  68. #% key: azimuth
  69. #% type: double
  70. #% description: Azimuth of the sun in degrees to the east of north
  71. #% required: no
  72. #% options : 0-360
  73. #% answer: 270
  74. #%end
  75. #%option
  76. #% key: zmult
  77. #% type: double
  78. #% description: Factor for exaggerating relief
  79. #% required: no
  80. #% answer: 1
  81. #%end
  82. #%option
  83. #% key: scale
  84. #% type: double
  85. #% description: Scale factor for converting horizontal units to elevation units
  86. #% required: no
  87. #% answer: 1
  88. #% guisection: Scaling
  89. #%end
  90. #%option
  91. #% key: units
  92. #% type: string
  93. #% description: Set scaling factor (applies to lat./long. locations only, none: scale=1)
  94. #% required: no
  95. #% options: none,meters,feet
  96. #% answer: none
  97. #% guisection: Scaling
  98. #%end
  99. import sys
  100. import os
  101. import string
  102. import grass.script as grass
  103. def main():
  104. input = options['input']
  105. output = options['output']
  106. altitude = options['altitude']
  107. azimuth = options['azimuth']
  108. zmult = options['zmult']
  109. scale = float(options['scale'])
  110. units = options['units']
  111. verbose_level = os.getenv('GRASS_VERBOSE')
  112. if verbose_level is None:
  113. verbose_level = 2
  114. if not grass.find_file(input)['file']:
  115. grass.fatal(_("Raster map <%s> not found") % input)
  116. if input == output:
  117. grass.fatal(_("Input elevation map and output relief map must have different names"))
  118. # LatLong locations only:
  119. if units == 'meters':
  120. # scale=111120
  121. scale *= 1852 * 60
  122. # LatLong locations only:
  123. if units == 'feet':
  124. # scale=364567.2
  125. scale *= 6076.12 * 60
  126. #correct azimuth to East (GRASS convention):
  127. # this seems to be backwards, but in fact it works so leave it.
  128. az = float(azimuth) - 90
  129. t = string.Template(
  130. r'''eval( \
  131. x=($zmult*$input[-1,-1] + 2*$zmult*$input[0,-1] + $zmult*$input[1,-1] - \
  132. $zmult*$input[-1,1] - 2*$zmult*$input[0,1] - $zmult*$input[1,1])/(8.*ewres()*$scale), \
  133. y=($zmult*$input[-1,-1] + 2*$zmult*$input[-1,0] + $zmult*$input[-1,1] - \
  134. $zmult*$input[1,-1] - 2*$zmult*$input[1,0] - $zmult*$input[1,1])/(8.*nsres()*$scale), \
  135. slope=90.-atan(sqrt(x*x + y*y)), \
  136. a=round(atan(x,y)), \
  137. a=if(isnull(a),1,a), \
  138. aspect=if(x!=0||y!=0,if(a,a,360.)), \
  139. cang = sin($altitude)*sin(slope) + cos($altitude)*cos(slope) * cos($az-aspect) \
  140. )
  141. $output = if(isnull(cang), null(), 100.*cang)''')
  142. expr = t.substitute(altitude = altitude, az = az, input = input, output = output, scale = scale, zmult = zmult)
  143. p = grass.feed_command('r.mapcalc')
  144. p.stdin.write(expr)
  145. p.stdin.close()
  146. if p.wait() != 0:
  147. grass.fatal(_("In calculation, script aborted."))
  148. if verbose_level < 3:
  149. grass.run_command('r.colors', map = output, color = 'grey', quiet = True)
  150. else:
  151. grass.run_command('r.colors', map = output, color = 'grey')
  152. # record metadata
  153. grass.run_command('r.support', map = output, title = 'Shaded relief of "%s"' % input, history = '')
  154. grass.run_command('r.support', map = output, history = "r.shaded.relief settings:")
  155. t = string.Template("altitude=$altitude azimuth=$azimuth zmult=$zmult scale=$scale")
  156. parms = dict(altitude = altitude, azimuth = azimuth, zmult = zmult, scale = options['scale'])
  157. grass.run_command('r.support', map = output, history = t.substitute(parms))
  158. if units:
  159. grass.run_command('r.support', map = output, history = " units=%s (adjusted scale=%s)" % (units, scale))
  160. # write cmd history:
  161. grass.raster_history(output)
  162. if __name__ == "__main__":
  163. options, flags = grass.parser()
  164. main()