main.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /***************************************************************
  2. *
  3. * MODULE: v.split
  4. *
  5. * AUTHOR(S): Radim Blazek
  6. * OGR support by Martin Landa <landa.martin gmail.com>
  7. * update for GRASS 7 by Markus Metz
  8. *
  9. * PURPOSE: Split lines to segments
  10. *
  11. * COPYRIGHT: (C) 2001-2014 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General
  14. * Public License (>=v2). Read the file COPYING that
  15. * comes with GRASS for details.
  16. *
  17. **************************************************************/
  18. #include <stdlib.h>
  19. #include <math.h>
  20. #include <string.h>
  21. #include <grass/gis.h>
  22. #include <grass/vector.h>
  23. #include <grass/glocale.h>
  24. #define FROM_KILOMETERS 1000.0
  25. #define FROM_FEET 0.3048
  26. #define FROM_SFEET 1200.0 / 3937.0
  27. #define FROM_MILES 1609.344
  28. #define FROM_NAUTMILES 1852.0
  29. int main(int argc, char *argv[])
  30. {
  31. struct GModule *module;
  32. struct Option *in_opt, *layer_opt, *out_opt, *length_opt,
  33. *units_opt, *vertices_opt;
  34. struct Flag *nosplit_flag, *fixedlength_flag;
  35. struct Map_info In, Out;
  36. struct line_pnts *Points, *Points2, *Points3;
  37. struct line_cats *Cats;
  38. int line, nlines, layer, nosplit, fixedlength;
  39. double length = -1;
  40. int vertices = 0;
  41. double (*line_length) ();
  42. int geodesic = 0;
  43. G_gisinit(argv[0]);
  44. module = G_define_module();
  45. G_add_keyword(_("vector"));
  46. G_add_keyword(_("geometry"));
  47. G_add_keyword(_("densification"));
  48. G_add_keyword(_("node"));
  49. G_add_keyword(_("segment"));
  50. G_add_keyword(_("vertex"));
  51. module->description = _("Splits vector lines to shorter segments.");
  52. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  53. layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
  54. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  55. length_opt = G_define_option();
  56. length_opt->key = "length";
  57. length_opt->type = TYPE_DOUBLE;
  58. length_opt->required = NO;
  59. length_opt->multiple = NO;
  60. length_opt->description = _("Maximum segment length");
  61. units_opt = G_define_option();
  62. units_opt->key = "units";
  63. units_opt->type = TYPE_STRING;
  64. units_opt->required = NO;
  65. units_opt->multiple = NO;
  66. units_opt->options = "map,meters,kilometers,feet,surveyfeet,miles,nautmiles";
  67. units_opt->answer = "map";
  68. units_opt->description = _("Length units");
  69. vertices_opt = G_define_option();
  70. vertices_opt->key = "vertices";
  71. vertices_opt->type = TYPE_INTEGER;
  72. vertices_opt->required = NO;
  73. vertices_opt->multiple = NO;
  74. vertices_opt->description = _("Maximum number of vertices in segment");
  75. nosplit_flag = G_define_flag();
  76. nosplit_flag->key = 'n';
  77. nosplit_flag->label = _("Add new vertices, but do not split");
  78. nosplit_flag->description = _("Applies only to 'length' option");
  79. fixedlength_flag = G_define_flag();
  80. fixedlength_flag->key = 'f';
  81. fixedlength_flag->label = _("Force segments to be exactly of given length, except for last one");
  82. fixedlength_flag->description = _("Applies only to 'length' option");
  83. if (G_parser(argc, argv))
  84. exit(EXIT_FAILURE);
  85. if ((length_opt->answer && vertices_opt->answer) ||
  86. !(length_opt->answer || vertices_opt->answer))
  87. G_fatal_error(_("Use either length or vertices"));
  88. line_length = NULL;
  89. if (length_opt->answer) {
  90. length = atof(length_opt->answer);
  91. if (length <= 0)
  92. G_fatal_error(_("Length must be positive but is %g"), length);
  93. /* convert length to meters */
  94. if (strcmp(units_opt->answer, "meters") == 0)
  95. /* do nothing */ ;
  96. else if (strcmp(units_opt->answer, "kilometers") == 0)
  97. length *= FROM_KILOMETERS;
  98. else if (strcmp(units_opt->answer, "feet") == 0)
  99. length *= FROM_FEET;
  100. else if (strcmp(units_opt->answer, "surveyfeet") == 0)
  101. length *= FROM_SFEET;
  102. else if (strcmp(units_opt->answer, "miles") == 0)
  103. length *= FROM_MILES;
  104. else if (strcmp(units_opt->answer, "nautmiles") == 0)
  105. length *= FROM_NAUTMILES;
  106. else if (strcmp(units_opt->answer, "map") != 0)
  107. G_fatal_error(_("Unknown unit %s"), units_opt->answer);
  108. /* set line length function */
  109. if (G_projection() == PROJECTION_LL) {
  110. if (strcmp(units_opt->answer, "map") == 0)
  111. line_length = Vect_line_length;
  112. else {
  113. line_length = Vect_line_geodesic_length;
  114. geodesic = 1;
  115. }
  116. }
  117. else {
  118. double factor;
  119. line_length = Vect_line_length;
  120. /* convert length to map units */
  121. if ((factor = G_database_units_to_meters_factor()) == 0)
  122. G_fatal_error(_("Can not get projection units"));
  123. else if (strcmp(units_opt->answer, "map") != 0) {
  124. /* meters to units */
  125. length = length / factor;
  126. }
  127. }
  128. if (strcmp(units_opt->answer, "map") == 0)
  129. G_verbose_message(_("Length in map units: %g"), length);
  130. else
  131. G_verbose_message(_("Length in meters: %g"), length);
  132. }
  133. if (vertices_opt->answer) {
  134. vertices = atoi(vertices_opt->answer);
  135. if (vertices < 2)
  136. G_fatal_error(_("Number of vertices must be at least 2"));
  137. }
  138. nosplit = nosplit_flag->answer;
  139. fixedlength = fixedlength_flag->answer;
  140. Vect_set_open_level(2);
  141. if (Vect_open_old2(&In, in_opt->answer, "", layer_opt->answer) < 0)
  142. G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer);
  143. layer = Vect_get_field_number(&In, layer_opt->answer);
  144. if (Vect_open_new(&Out, out_opt->answer, Vect_is_3d(&In)) < 0)
  145. G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer);
  146. Vect_copy_head_data(&In, &Out);
  147. Vect_hist_copy(&In, &Out);
  148. Vect_hist_command(&Out);
  149. Vect_copy_tables(&In, &Out, layer);
  150. Points = Vect_new_line_struct();
  151. Points2 = Vect_new_line_struct();
  152. Points3 = Vect_new_line_struct();
  153. Cats = Vect_new_cats_struct();
  154. nlines = Vect_get_num_lines(&In);
  155. for (line = 1; line <= nlines; line++) {
  156. int ltype;
  157. G_percent(line, nlines, 1);
  158. if (!Vect_line_alive(&In, line))
  159. continue;
  160. ltype = Vect_read_line(&In, Points, Cats, line);
  161. if (layer != -1 && !Vect_cat_get(Cats, layer, NULL))
  162. continue;
  163. if (ltype & GV_LINES) {
  164. if (length > 0) {
  165. double l, from, to, step;
  166. l = line_length(Points);
  167. if (l <= length) {
  168. Vect_write_line(&Out, ltype, Points, Cats);
  169. }
  170. else {
  171. long n, i;
  172. G_debug(3, "l: %f, length: %f", l, length);
  173. n = ceil(l / length);
  174. if (geodesic)
  175. l = Vect_line_length(Points);
  176. if (fixedlength) {
  177. step = length;
  178. }
  179. else {
  180. step = l / n;
  181. }
  182. from = 0.;
  183. G_debug(3, "n: %ld, step: %f", n, step);
  184. if (nosplit)
  185. Vect_reset_line(Points3);
  186. for (i = 0; i < n; i++) {
  187. int ret;
  188. double x, y, z;
  189. if (i == n - 1) {
  190. to = l; /* to be sure that it goes to end */
  191. }
  192. else {
  193. to = from + step;
  194. }
  195. ret = Vect_line_segment(Points, from, to, Points2);
  196. if (ret == 0) {
  197. G_warning(_("Unable to make line segment: %f - %f (line length = %f)"),
  198. from, to, l);
  199. continue;
  200. }
  201. /* To be sure that the coordinates are identical */
  202. if (i > 0) {
  203. Points2->x[0] = x;
  204. Points2->y[0] = y;
  205. Points2->z[0] = z;
  206. }
  207. if (i == n - 1) {
  208. Points2->x[Points2->n_points - 1] =
  209. Points->x[Points->n_points - 1];
  210. Points2->y[Points2->n_points - 1] =
  211. Points->y[Points->n_points - 1];
  212. Points2->z[Points2->n_points - 1] =
  213. Points->z[Points->n_points - 1];
  214. }
  215. if (nosplit) {
  216. if (Points3->n_points > 0)
  217. Points3->n_points--;
  218. Vect_append_points(Points3, Points2, GV_FORWARD);
  219. }
  220. else
  221. Vect_write_line(&Out, ltype, Points2, Cats);
  222. /* last point */
  223. x = Points2->x[Points2->n_points - 1];
  224. y = Points2->y[Points2->n_points - 1];
  225. z = Points2->z[Points2->n_points - 1];
  226. from += step;
  227. }
  228. if (nosplit)
  229. Vect_write_line(&Out, ltype, Points3, Cats);
  230. }
  231. }
  232. else {
  233. int start = 0; /* number of coordinates written */
  234. while (start < Points->n_points - 1) {
  235. int i, v = 0;
  236. Vect_reset_line(Points2);
  237. for (i = 0; i < vertices; i++) {
  238. v = start + i;
  239. if (v == Points->n_points)
  240. break;
  241. Vect_append_point(Points2, Points->x[v], Points->y[v],
  242. Points->z[v]);
  243. }
  244. Vect_write_line(&Out, ltype, Points2, Cats);
  245. start = v;
  246. }
  247. }
  248. }
  249. else {
  250. Vect_write_line(&Out, ltype, Points, Cats);
  251. }
  252. }
  253. Vect_close(&In);
  254. Vect_build(&Out);
  255. Vect_close(&Out);
  256. exit(EXIT_SUCCESS);
  257. }