main.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /***************************************************************
  2. *
  3. * MODULE: v.split
  4. *
  5. * AUTHOR(S): Radim Blazek
  6. * OGR support by Martin Landa <landa.martin gmail.com>
  7. *
  8. * PURPOSE: Split lines to segments
  9. *
  10. * COPYRIGHT: (C) 2001-2009 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General
  13. * Public License (>=v2). Read the file COPYING that
  14. * comes with GRASS for details.
  15. *
  16. **************************************************************/
  17. #include <stdlib.h>
  18. #include <math.h>
  19. #include <grass/gis.h>
  20. #include <grass/vector.h>
  21. #include <grass/glocale.h>
  22. int main(int argc, char *argv[])
  23. {
  24. struct GModule *module;
  25. struct Option *in_opt, *layer_opt, *out_opt, *length_opt, *vertices_opt;
  26. struct Map_info In, Out;
  27. struct line_pnts *Points, *Points2;
  28. struct line_cats *Cats;
  29. int line, nlines, layer;
  30. double length;
  31. int vertices;
  32. G_gisinit(argv[0]);
  33. module = G_define_module();
  34. G_add_keyword(_("vector"));
  35. G_add_keyword(_("geometry"));
  36. module->description = _("Splits vector lines to shorter segments.");
  37. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  38. layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
  39. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  40. length_opt = G_define_option();
  41. length_opt->key = "length";
  42. length_opt->type = TYPE_DOUBLE;
  43. length_opt->required = NO;
  44. length_opt->multiple = NO;
  45. length_opt->description = _("Maximum segment length");
  46. vertices_opt = G_define_option();
  47. vertices_opt->key = "vertices";
  48. vertices_opt->type = TYPE_INTEGER;
  49. vertices_opt->required = NO;
  50. vertices_opt->multiple = NO;
  51. vertices_opt->description = _("Maximum number of vertices in segment");
  52. if (G_parser(argc, argv))
  53. exit(EXIT_FAILURE);
  54. if ((length_opt->answer && vertices_opt->answer) ||
  55. !(length_opt->answer || vertices_opt->answer))
  56. G_fatal_error(_("Use either length or vertices"));
  57. if (length_opt->answer)
  58. length = atof(length_opt->answer);
  59. if (vertices_opt->answer) {
  60. vertices = atoi(vertices_opt->answer);
  61. if (vertices < 2)
  62. G_fatal_error(_("Number of vertices must be at least 2"));
  63. }
  64. Vect_set_open_level(2);
  65. Vect_open_old2(&In, in_opt->answer, "", layer_opt->answer);
  66. layer = Vect_get_field_number(&In, layer_opt->answer);
  67. Vect_open_new(&Out, out_opt->answer, Vect_is_3d(&In));
  68. Vect_copy_head_data(&In, &Out);
  69. Vect_hist_copy(&In, &Out);
  70. Vect_hist_command(&Out);
  71. Points = Vect_new_line_struct();
  72. Points2 = Vect_new_line_struct();
  73. Cats = Vect_new_cats_struct();
  74. nlines = Vect_get_num_lines(&In);
  75. for (line = 1; line <= nlines; line++) {
  76. int ltype;
  77. G_percent(line, nlines, 1);
  78. ltype = Vect_read_line(&In, Points, Cats, line);
  79. if (layer != -1 && !Vect_cat_get(Cats, layer, NULL))
  80. continue;
  81. if (ltype & GV_LINES) {
  82. if (length_opt->answer) {
  83. double l, from, to, step;
  84. l = Vect_line_length(Points);
  85. if (l <= length) {
  86. Vect_write_line(&Out, ltype, Points, Cats);
  87. }
  88. else {
  89. int n, i;
  90. n = ceil(l / length);
  91. step = l / n;
  92. from = 0.;
  93. for (i = 0; i < n; i++) {
  94. int ret;
  95. double x, y;
  96. if (i == n - 1) {
  97. to = l; /* to be sure that it goes to end */
  98. }
  99. else {
  100. to = from + step;
  101. }
  102. ret = Vect_line_segment(Points, from, to, Points2);
  103. if (ret == 0) {
  104. G_warning(_("Unable to make line segment: %f - %f (line length = %f)"),
  105. from, to, l);
  106. continue;
  107. }
  108. /* To be sure that the coordinates are identical */
  109. if (i > 0) {
  110. Points2->x[0] = x;
  111. Points2->y[0] = y;
  112. }
  113. if (i == n - 1) {
  114. Points2->x[Points2->n_points - 1] =
  115. Points->x[Points->n_points - 1];
  116. Points2->y[Points2->n_points - 1] =
  117. Points->y[Points->n_points - 1];
  118. }
  119. Vect_write_line(&Out, ltype, Points2, Cats);
  120. /* last point */
  121. x = Points2->x[Points2->n_points - 1];
  122. y = Points2->y[Points2->n_points - 1];
  123. from += step;
  124. }
  125. }
  126. }
  127. else {
  128. int start = 0; /* number of coordinates written */
  129. while (start < Points->n_points - 1) {
  130. int i, v;
  131. Vect_reset_line(Points2);
  132. for (i = 0; i < vertices; i++) {
  133. v = start + i;
  134. if (v == Points->n_points)
  135. break;
  136. Vect_append_point(Points2, Points->x[v], Points->y[v],
  137. Points->z[v]);
  138. }
  139. Vect_write_line(&Out, ltype, Points2, Cats);
  140. start = v;
  141. }
  142. }
  143. }
  144. else {
  145. Vect_write_line(&Out, ltype, Points, Cats);
  146. }
  147. }
  148. Vect_close(&In);
  149. Vect_build(&Out);
  150. Vect_close(&Out);
  151. exit(EXIT_SUCCESS);
  152. }