v.to.lines.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #!/usr/bin/env python3
  2. ############################################################################
  3. #
  4. # MODULE: v.to.lines (former v.polytoline)
  5. # AUTHOR(S): Luca Delucchi
  6. # point support added by Markus Neteler
  7. #
  8. # PURPOSE: Converts polygons and points to lines
  9. # COPYRIGHT: (C) 2013-2014 by the GRASS Development Team
  10. #
  11. # This program is free software under the GNU General Public
  12. # License (version 2). Read the file COPYING that comes with GRASS
  13. # for details.
  14. # TODO
  15. # support centroids (treat as points)?
  16. #############################################################################
  17. # %module
  18. # % description: Converts vector polygons or points to lines.
  19. # % keyword: vector
  20. # % keyword: geometry
  21. # % keyword: area
  22. # % keyword: line
  23. # % keyword: point
  24. # %end
  25. # %option G_OPT_V_INPUT
  26. # %end
  27. # %option G_OPT_V_OUTPUT
  28. # %end
  29. # %option
  30. # % key: method
  31. # % type: string
  32. # % description: Method used for point interpolation
  33. # % options: delaunay
  34. # % answer: delaunay
  35. # % guisection: Area
  36. # %end
  37. import grass.script as grass
  38. from grass.script.utils import decode
  39. from grass.exceptions import CalledModuleError
  40. import os
  41. def main():
  42. # Get the options
  43. input = options["input"]
  44. input_name = input.split("@")[0]
  45. output = options["output"]
  46. method = options["method"]
  47. min_cat = None
  48. max_cat = None
  49. point = None
  50. overwrite = grass.overwrite()
  51. quiet = True
  52. if grass.verbosity() > 2:
  53. quiet = False
  54. in_info = grass.vector_info(input)
  55. # check for wild mixture of vector types
  56. if in_info["points"] > 0 and in_info["boundaries"] > 0:
  57. grass.fatal(
  58. _(
  59. "The input vector map contains both polygons and points,"
  60. " cannot handle mixed types"
  61. )
  62. )
  63. pid = os.getpid()
  64. # process points via triangulation, then exit
  65. if in_info["points"] > 0:
  66. point = True
  67. layer = 1 # hardcoded for now
  68. out_temp = "{inp}_point_tmp_{pid}".format(inp=input_name, pid=pid)
  69. if method == "delaunay":
  70. grass.message(
  71. _("Processing point data (%d points found)...") % in_info["points"]
  72. )
  73. grass.run_command(
  74. "v.delaunay", input=input, layer=layer, output=out_temp, quiet=quiet
  75. )
  76. grass.run_command("v.db.addtable", map=out_temp, quiet=True)
  77. input = out_temp
  78. in_info = grass.vector_info(input)
  79. # process areas
  80. if in_info["areas"] == 0 and in_info["boundaries"] == 0:
  81. grass.fatal(_("The input vector map does not contain polygons"))
  82. out_type = "{inp}_type_{pid}".format(inp=input_name, pid=pid)
  83. input_tmp = "{inp}_tmp_{pid}".format(inp=input_name, pid=pid)
  84. remove_names = "%s,%s" % (out_type, input_tmp)
  85. grass.message(_("Processing area data (%d areas found)...") % in_info["areas"])
  86. try:
  87. grass.run_command(
  88. "v.category",
  89. layer="2",
  90. type="boundary",
  91. option="add",
  92. input=input,
  93. out=input_tmp,
  94. quiet=quiet,
  95. )
  96. except CalledModuleError:
  97. grass.run_command(
  98. "g.remove", flags="f", type="vector", name=input_tmp, quiet=quiet
  99. )
  100. grass.fatal(_("Error creating layer 2"))
  101. try:
  102. grass.run_command("v.db.addtable", map=input_tmp, layer="2", quiet=quiet)
  103. except CalledModuleError:
  104. grass.run_command(
  105. "g.remove", flags="f", type="vector", name=input_tmp, quiet=quiet
  106. )
  107. grass.fatal(_("Error creating new table for layer 2"))
  108. try:
  109. grass.run_command(
  110. "v.to.db",
  111. map=input_tmp,
  112. option="sides",
  113. columns="left,right",
  114. layer="2",
  115. quiet=quiet,
  116. )
  117. except CalledModuleError:
  118. grass.run_command(
  119. "g.remove", flags="f", type="vector", name=input_tmp, quiet=quiet
  120. )
  121. grass.fatal(_("Error populating new table for layer 2"))
  122. try:
  123. grass.run_command(
  124. "v.type",
  125. input=input_tmp,
  126. output=out_type,
  127. from_type="boundary",
  128. to_type="line",
  129. quiet=quiet,
  130. layer="2",
  131. )
  132. except CalledModuleError:
  133. grass.run_command(
  134. "g.remove", flags="f", type="vector", name=remove_names, quiet=quiet
  135. )
  136. grass.fatal(_("Error converting polygon to line"))
  137. report = grass.read_command(
  138. "v.category", flags="g", input=out_type, option="report", quiet=quiet
  139. )
  140. report = decode(report).split("\n")
  141. for r in report:
  142. if r.find("centroid") != -1:
  143. min_cat = report[0].split()[-2]
  144. max_cat = report[0].split()[-1]
  145. break
  146. if min_cat and max_cat:
  147. try:
  148. grass.run_command(
  149. "v.edit",
  150. map=out_type,
  151. tool="delete",
  152. type="centroid",
  153. layer=2,
  154. quiet=quiet,
  155. cats="{mi}-{ma}".format(mi=min_cat, ma=max_cat),
  156. )
  157. except CalledModuleError:
  158. grass.run_command(
  159. "g.remove", flags="f", type="vector", name=remove_names, quiet=quiet
  160. )
  161. grass.fatal(_("Error removing centroids"))
  162. try:
  163. try:
  164. # TODO: fix magic numbers for layer here and there
  165. grass.run_command(
  166. "v.db.droptable", map=out_type, layer=1, flags="f", quiet=True
  167. )
  168. except CalledModuleError:
  169. grass.run_command(
  170. "g.remove", flags="f", type="vector", name=remove_names, quiet=quiet
  171. )
  172. grass.fatal(_("Error removing table from layer 1"))
  173. # TODO: when this except is happaning, it seems that never, so it seems wrong
  174. except:
  175. grass.warning(_("No table for layer %d" % 1))
  176. try:
  177. grass.run_command(
  178. "v.category",
  179. input=out_type,
  180. option="transfer",
  181. output=output,
  182. layer="2,1",
  183. quiet=quiet,
  184. overwrite=overwrite,
  185. )
  186. except CalledModuleError:
  187. grass.run_command(
  188. "g.remove", flags="f", type="vector", name=remove_names, quiet=quiet
  189. )
  190. grass.fatal(_("Error adding categories"))
  191. grass.run_command(
  192. "g.remove", flags="f", type="vector", name=remove_names, quiet=quiet
  193. )
  194. if point:
  195. grass.run_command(
  196. "g.remove", flags="f", type="vector", name=out_temp, quiet=quiet
  197. )
  198. if __name__ == "__main__":
  199. options, flags = grass.parser()
  200. main()