r.buffer.lowmem.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #!/usr/bin/env python
  2. #
  3. ############################################################################
  4. #
  5. # MODULE: r.buffer.lowmem
  6. # AUTHOR(S): Glynn Clements
  7. # PURPOSE: Low-memory replacement for r.buffer using r.grow.distance
  8. #
  9. # COPYRIGHT: (C) 2008, 2010 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. #% label: Creates a raster map showing buffer zones surrounding cells that contain non-NULL category values.
  18. #% description: This is the low-memory alternative to the classic r.buffer module.
  19. #% keywords: raster
  20. #% keywords: buffer
  21. #%end
  22. #%flag
  23. #% key: z
  24. #% description: Ignore zero (0) data cells instead of NULL cells
  25. #%end
  26. #%option G_OPT_R_INPUT
  27. #%end
  28. #%option G_OPT_R_OUTPUT
  29. #%end
  30. #%option
  31. #% key: distances
  32. #% type: double
  33. #% required: yes
  34. #% multiple: yes
  35. #% description: Distance zone(s)
  36. #%end
  37. #%option G_OPT_M_UNITS
  38. #% options: meters,kilometers,feet,miles,nautmiles
  39. #% description: Units of distance
  40. #% answer: meters
  41. #%end
  42. import sys
  43. import os
  44. import atexit
  45. import math
  46. import grass.script as grass
  47. scales = {
  48. 'meters': 1.0,
  49. 'kilometers': 1000.0,
  50. 'feet': 0.3048,
  51. 'miles': 1609.344,
  52. 'nautmiles': 1852.0
  53. }
  54. # what to do in case of user break:
  55. def cleanup():
  56. if grass.find_file(temp_src)['file']:
  57. grass.run_command('g.remove', quiet = True, flags = 'fb', type = 'rast', pattern = temp_src)
  58. if grass.find_file(temp_dist)['file']:
  59. grass.run_command('g.remove', quiet = True, flags = 'fb', type = 'rast', pattern = temp_dist)
  60. def main():
  61. global temp_dist, temp_src
  62. input = options['input']
  63. output = options['output']
  64. distances = options['distances']
  65. units = options['units']
  66. zero = flags['z']
  67. tmp = str(os.getpid())
  68. temp_dist = "r.buffer.tmp.%s.dist" % tmp
  69. temp_src = "r.buffer.tmp.%s.src" % tmp
  70. #check if input file exists
  71. if not grass.find_file(input)['file']:
  72. grass.fatal(_("Raster map <%s> not found") % input)
  73. scale = scales[units]
  74. distances = distances.split(',')
  75. distances1 = [scale * float(d) for d in distances]
  76. distances2 = [d * d for d in distances1]
  77. s = grass.read_command("g.proj", flags='j')
  78. kv = grass.parse_key_val(s)
  79. if kv['+proj'] == 'longlat':
  80. metric = 'geodesic'
  81. else:
  82. metric = 'squared'
  83. grass.run_command('r.grow.distance', input = input, metric = metric,
  84. distance = temp_dist, flags = 'm')
  85. if zero:
  86. exp = "$temp_src = if($input == 0,null(),1)"
  87. else:
  88. exp = "$temp_src = if(isnull($input),null(),1)"
  89. grass.message(_("Extracting buffers (1/2)..."))
  90. grass.mapcalc(exp, temp_src = temp_src, input = input)
  91. exp = "$output = if(!isnull($input),$input,%s)"
  92. if metric == 'squared':
  93. for n, dist2 in enumerate(distances2):
  94. exp %= "if($dist <= %f,%d,%%s)" % (dist2,n + 2)
  95. else:
  96. for n, dist2 in enumerate(distances1):
  97. exp %= "if($dist <= %f,%d,%%s)" % (dist2,n + 2)
  98. exp %= "null()"
  99. grass.message(_("Extracting buffers (2/2)..."))
  100. grass.mapcalc(exp, output = output, input = temp_src, dist = temp_dist)
  101. p = grass.feed_command('r.category', map = output,
  102. separator=':', rules = '-')
  103. p.stdin.write("1:distances calculated from these locations\n")
  104. d0 = "0"
  105. for n, d in enumerate(distances):
  106. p.stdin.write("%d:%s-%s %s\n" % (n + 2, d0, d, units))
  107. d0 = d
  108. p.stdin.close()
  109. p.wait()
  110. grass.run_command('r.colors', map = output, color = 'rainbow')
  111. # write cmd history:
  112. grass.raster_history(output)
  113. if __name__ == "__main__":
  114. options, flags = grass.parser()
  115. atexit.register(cleanup)
  116. main()