r.shaded.relief.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 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, elevation
  52. #% End
  53. #% option
  54. #% key: input
  55. #% type: string
  56. #% gisprompt: old,cell,raster
  57. #% description: Input elevation map
  58. #% required : yes
  59. #% end
  60. #% option
  61. #% key: output
  62. #% type: string
  63. #% gisprompt: new,cell,raster
  64. #% description: Output shaded relief map name
  65. #% required : no
  66. #% end
  67. #% option
  68. #% key: altitude
  69. #% type: integer
  70. #% description: Altitude of the sun in degrees above the horizon
  71. #% required : no
  72. #% options : 0-90
  73. #% answer: 30
  74. #% end
  75. #% option
  76. #% key: azimuth
  77. #% type: integer
  78. #% description: Azimuth of the sun in degrees to the east of north
  79. #% required : no
  80. #% options : 0-360
  81. #% answer: 270
  82. #% end
  83. #% option
  84. #% key: zmult
  85. #% type: double
  86. #% description: Factor for exaggerating relief
  87. #% required : no
  88. #% answer: 1
  89. #% end
  90. #% option
  91. #% key: scale
  92. #% type: double
  93. #% description: Scale factor for converting horizontal units to elevation units
  94. #% required : no
  95. #% answer: 1
  96. #% end
  97. #% option
  98. #% key: units
  99. #% type: string
  100. #% description: Set scaling factor (applies to lat./long. locations only, none: scale=1)
  101. #% required : no
  102. #% options: none,meters,feet
  103. #% answer: none
  104. #% end
  105. import sys
  106. import os
  107. import string
  108. import grass
  109. def main():
  110. input = options['input']
  111. output = options['output']
  112. altitude = options['altitude']
  113. azimuth = options['azimuth']
  114. zmult = options['zmult']
  115. scale = options['scale']
  116. units = options['units']
  117. if not grass.find_file(input)['file']:
  118. grass.fatal("Map <%s> not found." % input)
  119. if input == output:
  120. grass.fatal("Input elevation map and output relief map must have different names")
  121. elev = input
  122. if not output:
  123. elevshade = elev.split('@')[0] + '.shade'
  124. else:
  125. elevshade = output
  126. elev_out = "'%s'" % elevshade
  127. alt = altitude
  128. scale = float(scale)
  129. # LatLong locations only:
  130. if units == 'meters':
  131. #scale=111120
  132. scale *= 1852 * 60
  133. # LatLong locations only:
  134. if units == 'feet':
  135. #scale=364567.2
  136. scale *= 6076.12 * 60
  137. #correct azimuth to East (GRASS convention):
  138. az = float(azimuth) - 90
  139. grass.message("Calculating shading, please stand by.")
  140. t = string.Template(
  141. r'''eval( \
  142. x=($zmult*$elev[-1,-1] + 2*$zmult*$elev[0,-1] + $zmult*$elev[1,-1] - \
  143. $zmult*$elev[-1,1] - 2*$zmult*$elev[0,1] - $zmult*$elev[1,1])/(8.*ewres()*$scale), \
  144. y=($zmult*$elev[-1,-1] + 2*$zmult*$elev[-1,0] + $zmult*$elev[-1,1] - \
  145. $zmult*$elev[1,-1] - 2*$zmult*$elev[1,0] - $zmult*$elev[1,1])/(8.*nsres()*$scale), \
  146. slope=90.-atan(sqrt(x*x + y*y)), \
  147. a=round(atan(x,y)), \
  148. a=if(isnull(a),1,a), \
  149. aspect=if(x!=0||y!=0,if(a,a,360.)), \
  150. cang = sin($alt)*sin(slope) + cos($alt)*cos(slope) * cos($az-aspect), \
  151. )
  152. $elev_out = if(isnull(cang), null(), 100.*cang)''')
  153. expr = t.substitute(alt = alt, az = az, elev = elev, elev_out = elev_out, scale = scale, zmult = zmult)
  154. p = grass.feed_command('r.mapcalc')
  155. p.stdin.write(expr)
  156. p.stdin.close()
  157. if p.wait() != 0:
  158. grass.fatal("In calculation, script aborted.")
  159. grass.run_command('r.colors', map = elevshade, color = 'grey')
  160. # record metadata
  161. grass.run_command('r.support', map = elevshade, title = 'Shaded relief of "%s"' % input, history = '')
  162. grass.run_command('r.support', map = elevshade, history = "r.shaded.relief settings:")
  163. t = string.Template("altitude=$alt azimuth=$azimuth zmult=$zmult scale=$scale")
  164. parms = dict(alt = alt, azimuth = azimuth, zmult = zmult, scale = options['scale'])
  165. grass.run_command('r.support', map = elevshade, history = t.substitute(parms))
  166. if units:
  167. grass.run_command('r.support', map = elevshade, history = " units=%s (adjusted scale=%s)" % (units, scale))
  168. if output:
  169. grass.message("Shaded relief map created and named <%s>." % elevshade)
  170. else:
  171. grass.message("Shaded relief map created and named <%s>. Consider renaming." % elevshade)
  172. # write cmd history:
  173. grass.raster_history(elevshade)
  174. if __name__ == "__main__":
  175. options, flags = grass.parser()
  176. main()