v.clip.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #!/usr/bin/env python3
  2. ############################################################################
  3. #
  4. # MODULE: v.clip
  5. # AUTHOR: Zofie Cimburova, CTU Prague, Czech Republic
  6. # PURPOSE: Clips vector features
  7. # COPYRIGHT: (C) 2016 Zofie Cimburova
  8. # This program is free software under the GNU General
  9. # Public License (>=v2). Read the file COPYING that
  10. # comes with GRASS for details.
  11. #
  12. #############################################################################
  13. # %module
  14. # % description: Extracts features of input map which overlay features of clip map.
  15. # % keyword: vector
  16. # % keyword: clip
  17. # % keyword: area
  18. # %end
  19. # %option G_OPT_V_INPUT
  20. # % label: Name of vector map to be clipped
  21. # % key: input
  22. # %end
  23. # %option G_OPT_V_INPUT
  24. # % key: clip
  25. # % label: Name of clip vector map
  26. # %end
  27. # %option G_OPT_V_OUTPUT
  28. # % key: output
  29. # %end
  30. # %flag
  31. # % key: d
  32. # % description: Do not dissolve clip map
  33. # %end
  34. # %flag
  35. # % key: r
  36. # % description: Clip by region
  37. # % suppress_required: yes
  38. # % guisection: Region
  39. # %end
  40. # flags -d and -r are mutualy exclusive
  41. # with flag -r, suppress_required: yes, but input and output must be defined
  42. # %rules
  43. # % exclusive: -d, -r
  44. # % requires_all: -r, input, output
  45. # %end
  46. import os
  47. import sys
  48. import atexit
  49. from grass.script import parser
  50. import grass.script as grass
  51. from grass.exceptions import CalledModuleError
  52. TMP = []
  53. def cleanup():
  54. for name in TMP:
  55. try:
  56. grass.run_command(
  57. "g.remove", flags="f", type="vector", name=name, quiet=True
  58. )
  59. except CalledModuleError as e:
  60. grass.fatal(
  61. _(
  62. "Deleting of temporary layer failed. "
  63. "Check above error messages and "
  64. "see following details:\n%s"
  65. )
  66. % e
  67. )
  68. def section_message(msg):
  69. grass.message("{delim}\n{msg}\n{delim}".format(msg=msg, delim="-" * 80))
  70. def main():
  71. input_map = opt["input"]
  72. clip_map = opt["clip"]
  73. output_map = opt["output"]
  74. flag_dissolve = flg["d"]
  75. flag_region = flg["r"]
  76. # ======================================== #
  77. # ========== INPUT MAP TOPOLOGY ========== #
  78. # ======================================== #
  79. vinfo = grass.vector_info_topo(input_map)
  80. # ==== only points ==== #
  81. if vinfo["points"] > 0 and vinfo["lines"] == 0 and vinfo["areas"] == 0:
  82. # ==================================== #
  83. # ========== CLIP BY REGION ========== #
  84. # ==================================== #
  85. if flag_region:
  86. clip_by_region(input_map, output_map, clip_select)
  87. # ================================== #
  88. # ========== DEFAULT CLIP ========== #
  89. # ================================== #
  90. else:
  91. section_message("Clipping.")
  92. # perform clipping
  93. clip_select(input_map, clip_map, output_map)
  94. # ==== lines, areas, lines + areas ==== #
  95. # ==== points + areas, points + lines, points + areas + lines ==== #
  96. else:
  97. if vinfo["points"] > 0:
  98. grass.warning(
  99. "Input map contains multiple geometry, "
  100. "only lines and areas will be clipped."
  101. )
  102. # ==================================== #
  103. # ========== CLIP BY REGION ========== #
  104. # ==================================== #
  105. if flag_region:
  106. clip_by_region(input_map, output_map, clip_overlay)
  107. # ===================================================== #
  108. # ========== CLIP WITHOUT DISSOLVED CLIP MAP ========== #
  109. # ===================================================== #
  110. elif flag_dissolve:
  111. section_message("Clipping without dissolved clip map.")
  112. clip_overlay(input_map, clip_map, output_map)
  113. # ========================================================== #
  114. # ========== DEFAULT CLIP WITH DISSOLVED CLIP MAP ========== #
  115. # ========================================================== #
  116. else:
  117. section_message("Default clipping with dissolved clip map.")
  118. # setup temporary map
  119. temp_clip_map = "%s_%s" % ("temp", str(os.getpid()))
  120. TMP.append(temp_clip_map)
  121. # dissolve clip_map
  122. grass.run_command("v.dissolve", input=clip_map, output=temp_clip_map)
  123. # perform clipping
  124. clip_overlay(input_map, temp_clip_map, output_map)
  125. # ======================================== #
  126. # ========== OUTPUT MAP TOPOLOGY========== #
  127. # ======================================== #
  128. vinfo = grass.vector_info_topo(output_map)
  129. if vinfo["primitives"] == 0:
  130. grass.warning("Output map is empty.")
  131. return 0
  132. # clip input map by computational region
  133. # clip_select for points, clip_overlay for areas and lines
  134. def clip_by_region(input_map, output_map, clip_fn):
  135. section_message("Clipping by region.")
  136. # setup temporary map
  137. temp_region_map = "%s_%s" % ("temp", str(os.getpid()))
  138. TMP.append(temp_region_map)
  139. # create a map covering current computational region
  140. grass.run_command("v.in.region", output=temp_region_map)
  141. # perform clipping
  142. clip_fn(input_map, temp_region_map, output_map)
  143. def clip_overlay(input_data, clip_data, out_data):
  144. try:
  145. grass.run_command(
  146. "v.overlay",
  147. ainput=input_data,
  148. binput=clip_data,
  149. operator="and",
  150. output=out_data,
  151. olayer="0,1,0",
  152. )
  153. except CalledModuleError as e:
  154. grass.fatal(
  155. _(
  156. "Clipping steps failed."
  157. " Check above error messages and"
  158. " see following details:\n%s"
  159. )
  160. % e
  161. )
  162. def clip_select(input_data, clip_data, out_data):
  163. try:
  164. grass.run_command(
  165. "v.select",
  166. ainput=input_data,
  167. binput=clip_data,
  168. output=out_data,
  169. operator="overlap",
  170. )
  171. except CalledModuleError as e:
  172. grass.fatal(
  173. _(
  174. "Clipping steps failed."
  175. " Check above error messages and"
  176. " see following details:\n%s"
  177. )
  178. % e
  179. )
  180. if __name__ == "__main__":
  181. atexit.register(cleanup)
  182. opt, flg = parser()
  183. sys.exit(main())