main.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /***************************************************************
  2. *
  3. * MODULE: v.parallel
  4. *
  5. * AUTHOR(S): Radim Blazek
  6. * Upgraded by Rosen Matev (Google Summer of Code 2008)
  7. * OGR support by Martin Landa <landa.martin gmail.com>
  8. *
  9. * PURPOSE: Create parallel lines
  10. *
  11. * COPYRIGHT: (C) 2008-2009 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. int main(int argc, char *argv[])
  25. {
  26. struct GModule *module;
  27. struct Option *in_opt, *layer_opt, *out_opt, *dista_opt;
  28. struct Option *distb_opt, *angle_opt, *side_opt;
  29. struct Option *tol_opt;
  30. struct Flag *round_flag, *buf_flag;
  31. struct Map_info In, Out;
  32. struct line_pnts *Points, *Points2, *oPoints, **iPoints;
  33. struct line_cats *Cats;
  34. char *desc;
  35. int line, nlines, inner_count, j;
  36. int layer;
  37. double da, db, dalpha, tolerance;
  38. int side;
  39. G_gisinit(argv[0]);
  40. module = G_define_module();
  41. G_add_keyword(_("vector"));
  42. G_add_keyword(_("geometry"));
  43. G_add_keyword(_("buffer"));
  44. G_add_keyword(_("line"));
  45. module->description = _("Creates parallel line to input vector lines.");
  46. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  47. layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
  48. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  49. dista_opt = G_define_option();
  50. dista_opt->key = "distance";
  51. dista_opt->type = TYPE_DOUBLE;
  52. dista_opt->required = YES;
  53. dista_opt->options = "0-100000000";
  54. dista_opt->multiple = NO;
  55. dista_opt->description = _("Offset along major axis in map units");
  56. distb_opt = G_define_option();
  57. distb_opt->key = "minordistance";
  58. distb_opt->type = TYPE_DOUBLE;
  59. distb_opt->required = NO;
  60. distb_opt->options = "0-100000000";
  61. distb_opt->multiple = NO;
  62. distb_opt->description = _("Offset along minor axis in map units");
  63. angle_opt = G_define_option();
  64. angle_opt->key = "angle";
  65. angle_opt->type = TYPE_DOUBLE;
  66. angle_opt->required = NO;
  67. angle_opt->answer = "0";
  68. angle_opt->multiple = NO;
  69. angle_opt->description = _("Angle of major axis in degrees"); /* CW or CCW? does this even work?? */
  70. side_opt = G_define_option();
  71. side_opt->key = "side";
  72. side_opt->type = TYPE_STRING;
  73. side_opt->required = YES;
  74. side_opt->answer = "right";
  75. side_opt->multiple = NO;
  76. side_opt->options = "left,right,both";
  77. side_opt->description = _("Side");
  78. desc = NULL;
  79. G_asprintf(&desc,
  80. "left;%s;right;%s;both;%s",
  81. _("Parallel line is on the left"),
  82. _("Parallel line is on the right"),
  83. _("Parallel lines on both sides"));
  84. side_opt->descriptions = desc;
  85. tol_opt = G_define_option();
  86. tol_opt->key = "tolerance";
  87. tol_opt->type = TYPE_DOUBLE;
  88. tol_opt->required = NO;
  89. tol_opt->options = "0-100000000";
  90. tol_opt->multiple = NO;
  91. tol_opt->description = _("Tolerance of arc polylines in map units");
  92. round_flag = G_define_flag();
  93. round_flag->key = 'r';
  94. round_flag->description = _("Make outside corners round");
  95. buf_flag = G_define_flag();
  96. buf_flag->key = 'b';
  97. buf_flag->description = _("Create buffer-like parallel lines");
  98. if (G_parser(argc, argv))
  99. exit(EXIT_FAILURE);
  100. da = atof(dista_opt->answer);
  101. if (distb_opt->answer)
  102. db = atof(distb_opt->answer);
  103. else
  104. db = da;
  105. if (angle_opt->answer)
  106. dalpha = atof(angle_opt->answer);
  107. else
  108. dalpha = 0;
  109. if (tol_opt->answer)
  110. tolerance = atof(tol_opt->answer);
  111. else
  112. tolerance = ((db < da) ? db : da) / 100.;
  113. if (strcmp(side_opt->answer, "right") == 0)
  114. side = 1;
  115. else if (strcmp(side_opt->answer, "left") == 0)
  116. side = -1;
  117. else
  118. side = 0;
  119. Vect_set_open_level(2);
  120. if (Vect_open_old2(&In, in_opt->answer, "", layer_opt->answer) < 0)
  121. G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer);
  122. layer = Vect_get_field_number(&In, layer_opt->answer);
  123. if (Vect_open_new(&Out, out_opt->answer, 0) < 0)
  124. G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer);
  125. Vect_copy_head_data(&In, &Out);
  126. Vect_hist_copy(&In, &Out);
  127. Vect_hist_command(&Out);
  128. Points = Vect_new_line_struct();
  129. Points2 = Vect_new_line_struct();
  130. Cats = Vect_new_cats_struct();
  131. nlines = Vect_get_num_lines(&In);
  132. for (line = 1; line <= nlines; line++) {
  133. int ltype;
  134. G_percent(line, nlines, 1);
  135. ltype = Vect_read_line(&In, Points, Cats, line);
  136. if (layer != -1 && !Vect_cat_get(Cats, layer, NULL))
  137. continue;
  138. if (ltype & GV_LINES) {
  139. if (!(buf_flag->answer)) {
  140. if (side != 0) {
  141. Vect_line_parallel2(Points, da, db, dalpha, side,
  142. round_flag->answer, tolerance,
  143. Points2);
  144. Vect_write_line(&Out, ltype, Points2, Cats);
  145. }
  146. else {
  147. Vect_line_parallel2(Points, da, db, dalpha, 1,
  148. round_flag->answer, tolerance,
  149. Points2);
  150. Vect_write_line(&Out, ltype, Points2, Cats);
  151. Vect_line_parallel2(Points, da, db, dalpha, -1,
  152. round_flag->answer, tolerance,
  153. Points2);
  154. Vect_write_line(&Out, ltype, Points2, Cats);
  155. }
  156. }
  157. else {
  158. Vect_line_buffer2(Points, da, db, dalpha, round_flag->answer,
  159. 1, tolerance, &oPoints, &iPoints,
  160. &inner_count);
  161. Vect_write_line(&Out, ltype, oPoints, Cats);
  162. for (j = 0; j < inner_count; j++) {
  163. Vect_write_line(&Out, ltype, iPoints[j], Cats);
  164. }
  165. }
  166. }
  167. else {
  168. Vect_write_line(&Out, ltype, Points, Cats);
  169. }
  170. }
  171. /* Vect_build_partial(&Out, GV_BUILD_BASE);
  172. Vect_snap_lines(&Out, GV_BOUNDARY, 1e-7, NULL);
  173. Vect_break_lines(&Out, GV_BOUNDARY, NULL);
  174. Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL);
  175. Vect_build_partial (&Out, GV_BUILD_NONE);
  176. */
  177. Vect_build(&Out);
  178. Vect_close(&In);
  179. Vect_close(&Out);
  180. exit(EXIT_SUCCESS);
  181. }