r.grow.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/env python
  2. #
  3. ############################################################################
  4. #
  5. # MODULE: r.grow
  6. # AUTHOR(S): Glynn Clements
  7. # PURPOSE: Fast replacement for r.grow using r.grow.distance
  8. #
  9. # COPYRIGHT: (C) 2008 by Glynn Clements
  10. #
  11. # This program is free software under the GNU General Public
  12. # License (>=v2). Read the file COPYING that comes with GRASS
  13. # for details.
  14. #
  15. #############################################################################
  16. #%Module
  17. #% description: Generates a raster map layer with contiguous areas grown by one cell.
  18. #% keyword: raster
  19. #% keyword: distance
  20. #% keyword: proximity
  21. #%end
  22. #%flag
  23. #% key: m
  24. #% description: Radius is in map units rather than cells
  25. #%end
  26. #%option G_OPT_R_INPUT
  27. #%end
  28. #%option G_OPT_R_OUTPUT
  29. #%end
  30. #%option
  31. #% key: radius
  32. #% type: double
  33. #% required: no
  34. #% multiple: no
  35. #% description: Radius of buffer in raster cells
  36. #% answer: 1.01
  37. #%end
  38. #%option
  39. #% key: metric
  40. #% type: string
  41. #% required: no
  42. #% multiple: no
  43. #% options: euclidean,maximum,manhattan
  44. #% description: Metric
  45. #% answer: euclidean
  46. #%end
  47. #%option
  48. #% key: old
  49. #% type: integer
  50. #% required: no
  51. #% multiple: no
  52. #% description: Value to write for input cells which are non-NULL (-1 => NULL)
  53. #%end
  54. #%option
  55. #% key: new
  56. #% type: integer
  57. #% required: no
  58. #% multiple: no
  59. #% description: Value to write for "grown" cells
  60. #%end
  61. import sys
  62. import os
  63. import atexit
  64. import math
  65. from string import split
  66. import grass.script as grass
  67. from grass.exceptions import CalledModuleError
  68. # i18N
  69. import gettext
  70. gettext.install('grassmods', os.path.join(os.getenv("GISBASE"), 'locale'))
  71. # what to do in case of user break:
  72. def cleanup():
  73. for map in [temp_dist, temp_val]:
  74. if map:
  75. grass.run_command('g.remove', flags='fb', quiet=True,
  76. type='rast', name=map)
  77. def main():
  78. global temp_dist, temp_val
  79. input = options['input']
  80. radius = float(options['radius'])
  81. metric = options['metric']
  82. old = options['old']
  83. new = options['new']
  84. mapunits = flags['m']
  85. tmp = str(os.getpid())
  86. temp_dist = "r.grow.tmp.%s.dist" % tmp
  87. shrink = False
  88. if radius < 0.0:
  89. shrink = True
  90. radius = -radius
  91. if new == '' and shrink == False:
  92. temp_val = "r.grow.tmp.%s.val" % tmp
  93. new = temp_val
  94. else:
  95. temp_val = None
  96. if old == '':
  97. old = input
  98. if not mapunits:
  99. kv = grass.region()
  100. scale = math.sqrt(float(kv['nsres']) * float(kv['ewres']))
  101. radius *= scale
  102. if metric == 'euclidean':
  103. metric = 'squared'
  104. radius = radius * radius
  105. # check if input file exists
  106. if not grass.find_file(input)['file']:
  107. grass.fatal(_("Raster map <%s> not found") % input)
  108. # Workaround for r.mapcalc bug #3475
  109. # Mapcalc will fail if output is a fully qualified map name
  110. out_name = split(options['output'], '@')
  111. if len(out_name) == 2:
  112. if out_name[1] != grass.gisenv()['MAPSET']:
  113. grass.fatal(_("Output can be written only to the current mapset"))
  114. output = out_name[0]
  115. else:
  116. output = out_name[0]
  117. if shrink == False:
  118. try:
  119. grass.run_command('r.grow.distance', input=input, metric=metric,
  120. distance=temp_dist, value=temp_val)
  121. except CalledModuleError:
  122. grass.fatal(_("Growing failed. Removing temporary maps."))
  123. grass.mapcalc(
  124. "$output = if(!isnull($input),$old,if($dist < $radius,$new,null()))",
  125. output=output, input=input, radius=radius,
  126. old=old, new=new, dist=temp_dist)
  127. else:
  128. # shrink
  129. try:
  130. grass.run_command('r.grow.distance', input=input, metric=metric,
  131. distance=temp_dist, value=temp_val, flags='n')
  132. except CalledModuleError:
  133. grass.fatal(_("Shrinking failed. Removing temporary maps."))
  134. grass.mapcalc(
  135. "$output = if($dist < $radius,null(),$old)",
  136. output=output, radius=radius, old=old, dist=temp_dist)
  137. grass.run_command('r.colors', map=output, raster=input)
  138. # write cmd history:
  139. grass.raster_history(output)
  140. if __name__ == "__main__":
  141. options, flags = grass.parser()
  142. atexit.register(cleanup)
  143. main()