main.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /****************************************************************
  2. *
  3. * MODULE: v.net.components
  4. *
  5. * AUTHOR(S): Daniel Bundala
  6. *
  7. * PURPOSE: Computes strongly and weakly connected components
  8. *
  9. * COPYRIGHT: (C) 2002-2014 by the GRASS Development Team
  10. *
  11. * This program is free software under the
  12. * GNU General Public License (>=v2).
  13. * Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. ****************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <grass/gis.h>
  20. #include <grass/vector.h>
  21. #include <grass/glocale.h>
  22. #include <grass/dbmi.h>
  23. #include <grass/neta.h>
  24. int insert_new_record(dbDriver * driver, struct field_info *Fi,
  25. dbString * sql, int cat, int comp)
  26. {
  27. char buf[2000];
  28. sprintf(buf, "insert into %s values (%d, %d)", Fi->table, cat, comp);
  29. db_set_string(sql, buf);
  30. G_debug(3, "%s", db_get_string(sql));
  31. if (db_execute_immediate(driver, sql) != DB_OK) {
  32. db_close_database_shutdown_driver(driver);
  33. G_fatal_error(_("Cannot insert new record: %s"), db_get_string(sql));
  34. return 0;
  35. };
  36. return 1;
  37. }
  38. int main(int argc, char *argv[])
  39. {
  40. struct Map_info In, Out;
  41. static struct line_pnts *Points;
  42. struct line_cats *Cats;
  43. struct GModule *module; /* GRASS module for parsing arguments */
  44. struct Option *map_in, *map_out;
  45. struct Option *method_opt, *afield_opt, *nfield_opt, *abcol,
  46. *afcol, *ncol;
  47. struct Flag *add_f;
  48. int with_z;
  49. int afield, nfield, mask_type;
  50. dglGraph_s *graph;
  51. int *component, nnodes, type, i, nlines, components, j, max_cat;
  52. char buf[2000], *covered;
  53. char *desc;
  54. /* Attribute table */
  55. dbString sql;
  56. dbDriver *driver;
  57. struct field_info *Fi;
  58. /* initialize GIS environment */
  59. G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */
  60. /* initialize module */
  61. module = G_define_module();
  62. G_add_keyword(_("vector"));
  63. G_add_keyword(_("network"));
  64. G_add_keyword(_("components"));
  65. module->description =
  66. _("Computes strongly and weakly connected components in the network.");
  67. /* Define the different options as defined in gis.h */
  68. map_in = G_define_standard_option(G_OPT_V_INPUT);
  69. afield_opt = G_define_standard_option(G_OPT_V_FIELD);
  70. afield_opt->key = "arc_layer";
  71. afield_opt->answer = "1";
  72. afield_opt->label = _("Arc layer");
  73. afield_opt->guisection = _("Cost");
  74. nfield_opt = G_define_standard_option(G_OPT_V_FIELD);
  75. nfield_opt->key = "node_layer";
  76. nfield_opt->answer = "2";
  77. nfield_opt->label = _("Node layer");
  78. nfield_opt->guisection = _("Cost");
  79. afcol = G_define_standard_option(G_OPT_DB_COLUMN);
  80. afcol->key = "arc_column";
  81. afcol->required = NO;
  82. afcol->description =
  83. _("Arc forward/both direction(s) cost column (number)");
  84. afcol->guisection = _("Cost");
  85. abcol = G_define_standard_option(G_OPT_DB_COLUMN);
  86. abcol->key = "arc_backward_column";
  87. abcol->required = NO;
  88. abcol->description = _("Arc backward direction cost column (number)");
  89. abcol->guisection = _("Cost");
  90. ncol = G_define_option();
  91. ncol->key = "node_column";
  92. ncol->type = TYPE_STRING;
  93. ncol->required = NO;
  94. ncol->description = _("Node cost column (number)");
  95. ncol->guisection = _("Cost");
  96. map_out = G_define_standard_option(G_OPT_V_OUTPUT);
  97. method_opt = G_define_option();
  98. method_opt->key = "method";
  99. method_opt->type = TYPE_STRING;
  100. method_opt->required = YES;
  101. method_opt->multiple = NO;
  102. method_opt->options = "weak,strong";
  103. desc = NULL;
  104. G_asprintf(&desc,
  105. "weak;%s;strong;%s",
  106. _("Weakly connected components"),
  107. _("Strongly connected components"));
  108. method_opt->descriptions = desc;
  109. method_opt->description = _("Type of components");
  110. add_f = G_define_flag();
  111. add_f->key = 'a';
  112. add_f->description = _("Add points on nodes");
  113. /* options and flags parser */
  114. if (G_parser(argc, argv))
  115. exit(EXIT_FAILURE);
  116. /* TODO: make an option for this */
  117. mask_type = GV_LINE | GV_BOUNDARY;
  118. Points = Vect_new_line_struct();
  119. Cats = Vect_new_cats_struct();
  120. Vect_check_input_output_name(map_in->answer, map_out->answer,
  121. G_FATAL_EXIT);
  122. Vect_set_open_level(2);
  123. if (1 > Vect_open_old(&In, map_in->answer, ""))
  124. G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer);
  125. with_z = Vect_is_3d(&In);
  126. if (0 > Vect_open_new(&Out, map_out->answer, with_z)) {
  127. Vect_close(&In);
  128. G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer);
  129. }
  130. /* parse filter option and select appropriate lines */
  131. afield = Vect_get_field_number(&In, afield_opt->answer);
  132. nfield = Vect_get_field_number(&In, nfield_opt->answer);
  133. if (0 != Vect_net_build_graph(&In, mask_type, afield, nfield, afcol->answer,
  134. abcol->answer, ncol->answer, 0, 0))
  135. G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In));
  136. graph = Vect_net_get_graph(&In);
  137. nnodes = Vect_get_num_nodes(&In);
  138. component = (int *)G_calloc(nnodes + 1, sizeof(int));
  139. covered = (char *)G_calloc(nnodes + 1, sizeof(char));
  140. if (!component || !covered) {
  141. G_fatal_error(_("Out of memory"));
  142. exit(EXIT_FAILURE);
  143. }
  144. /* Create table */
  145. Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
  146. Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
  147. Fi->driver);
  148. db_init_string(&sql);
  149. driver = db_start_driver_open_database(Fi->driver, Fi->database);
  150. if (driver == NULL)
  151. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  152. Fi->database, Fi->driver);
  153. sprintf(buf, "create table %s ( cat integer, comp integer)", Fi->table);
  154. db_set_string(&sql, buf);
  155. G_debug(2, "%s", db_get_string(&sql));
  156. if (db_execute_immediate(driver, &sql) != DB_OK) {
  157. db_close_database_shutdown_driver(driver);
  158. G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
  159. }
  160. if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
  161. G_warning(_("Cannot create index"));
  162. if (db_grant_on_table
  163. (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
  164. G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table);
  165. db_begin_transaction(driver);
  166. if (method_opt->answer[0] == 'w')
  167. components = NetA_weakly_connected_components(graph, component);
  168. else
  169. components = NetA_strongly_connected_components(graph, component);
  170. G_debug(3, "Components: %d", components);
  171. Vect_copy_head_data(&In, &Out);
  172. Vect_hist_copy(&In, &Out);
  173. Vect_hist_command(&Out);
  174. nlines = Vect_get_num_lines(&In);
  175. for (i = 1; i <= nlines; i++) {
  176. int comp, cat;
  177. type = Vect_read_line(&In, Points, Cats, i);
  178. if (!Vect_cat_get(Cats, afield, &cat))
  179. continue;
  180. if (type == GV_LINE || type == GV_BOUNDARY) {
  181. int node1, node2;
  182. Vect_get_line_nodes(&In, i, &node1, &node2);
  183. if (component[node1] == component[node2]) {
  184. comp = component[node1];
  185. }
  186. else {
  187. continue;
  188. }
  189. }
  190. else if (type == GV_POINT) {
  191. int node;
  192. /* Vect_get_line_nodes(&In, i, &node, NULL); */
  193. node = Vect_find_node(&In, Points->x[0], Points->y[0], Points->z[0], 0, 0);
  194. comp = component[node];
  195. covered[node] = 1;
  196. }
  197. else
  198. continue;
  199. Vect_write_line(&Out, type, Points, Cats);
  200. insert_new_record(driver, Fi, &sql, cat, comp);
  201. /* for(j=0;j<Cats->n_cats;j++)
  202. * if(Cats->field[j] == layer)
  203. * insert_new_record(driver, Fi, &sql, Cats->cat[j], comp);
  204. */
  205. };
  206. /*add points on nodes not covered by any point in the network */
  207. /*find the maximum cat number */
  208. if (add_f->answer) {
  209. max_cat = 0;
  210. for (i = 1; i <= nlines; i++) {
  211. Vect_read_line(&In, NULL, Cats, i);
  212. for (j = 0; j < Cats->n_cats; j++)
  213. if (Cats->cat[j] > max_cat)
  214. max_cat = Cats->cat[j];
  215. }
  216. max_cat++;
  217. for (i = 1; i <= nnodes; i++)
  218. if (!covered[i]) {
  219. Vect_reset_cats(Cats);
  220. Vect_cat_set(Cats, 1, max_cat);
  221. NetA_add_point_on_node(&In, &Out, i, Cats);
  222. insert_new_record(driver, Fi, &sql, max_cat++, component[i]);
  223. }
  224. }
  225. db_commit_transaction(driver);
  226. db_close_database_shutdown_driver(driver);
  227. Vect_build(&Out);
  228. Vect_close(&In);
  229. Vect_close(&Out);
  230. exit(EXIT_SUCCESS);
  231. }