main.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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-2005 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, 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 *field_opt, *method_opt;
  46. struct Flag *add_f;
  47. int with_z;
  48. int layer, mask_type;
  49. dglGraph_s *graph;
  50. int *component, nnodes, type, i, nlines, components, j, max_cat;
  51. char buf[2000], *covered;
  52. /* Attribute table */
  53. dbString sql;
  54. dbDriver *driver;
  55. struct field_info *Fi;
  56. /* initialize GIS environment */
  57. G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */
  58. /* initialize module */
  59. module = G_define_module();
  60. G_add_keyword(_("vector"));
  61. G_add_keyword(_("network"));
  62. G_add_keyword(_("components"));
  63. module->description =
  64. _("Computes strongly and weakly connected components in the network.");
  65. /* Define the different options as defined in gis.h */
  66. map_in = G_define_standard_option(G_OPT_V_INPUT);
  67. field_opt = G_define_standard_option(G_OPT_V_FIELD);
  68. map_out = G_define_standard_option(G_OPT_V_OUTPUT);
  69. method_opt = G_define_option();
  70. method_opt->key = "method";
  71. method_opt->type = TYPE_STRING;
  72. method_opt->required = YES;
  73. method_opt->multiple = NO;
  74. method_opt->options = "weak,strong";
  75. method_opt->descriptions = _("weak;Weakly connected components;"
  76. "strong;Strongly connected components;");
  77. method_opt->description = _("Type of components");
  78. add_f = G_define_flag();
  79. add_f->key = 'a';
  80. add_f->description = _("Add points on nodes");
  81. /* options and flags parser */
  82. if (G_parser(argc, argv))
  83. exit(EXIT_FAILURE);
  84. /* TODO: make an option for this */
  85. mask_type = GV_LINE | GV_BOUNDARY;
  86. Points = Vect_new_line_struct();
  87. Cats = Vect_new_cats_struct();
  88. Vect_check_input_output_name(map_in->answer, map_out->answer,
  89. GV_FATAL_EXIT);
  90. Vect_set_open_level(2);
  91. if (1 > Vect_open_old(&In, map_in->answer, ""))
  92. G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer);
  93. with_z = Vect_is_3d(&In);
  94. if (0 > Vect_open_new(&Out, map_out->answer, with_z)) {
  95. Vect_close(&In);
  96. G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer);
  97. }
  98. /* parse filter option and select appropriate lines */
  99. layer = atoi(field_opt->answer);
  100. Vect_net_build_graph(&In, mask_type, 0, 0, NULL, NULL, NULL, 0, 0);
  101. graph = &(In.graph);
  102. nnodes = Vect_get_num_nodes(&In);
  103. component = (int *)G_calloc(nnodes + 1, sizeof(int));
  104. covered = (char *)G_calloc(nnodes + 1, sizeof(char));
  105. if (!component || !covered) {
  106. G_fatal_error(_("Out of memory"));
  107. exit(EXIT_FAILURE);
  108. }
  109. /* Create table */
  110. Fi = Vect_default_field_info(&Out, layer, NULL, GV_1TABLE);
  111. Vect_map_add_dblink(&Out, layer, NULL, Fi->table, "cat", Fi->database,
  112. Fi->driver);
  113. db_init_string(&sql);
  114. driver = db_start_driver_open_database(Fi->driver, Fi->database);
  115. if (driver == NULL)
  116. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  117. Fi->database, Fi->driver);
  118. sprintf(buf, "create table %s ( cat integer, comp integer)", Fi->table);
  119. db_set_string(&sql, buf);
  120. G_debug(2, db_get_string(&sql));
  121. if (db_execute_immediate(driver, &sql) != DB_OK) {
  122. db_close_database_shutdown_driver(driver);
  123. G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
  124. }
  125. if (db_create_index2(driver, Fi->table, "cat") != DB_OK)
  126. G_warning(_("Cannot create index"));
  127. if (db_grant_on_table
  128. (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
  129. G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table);
  130. db_begin_transaction(driver);
  131. if (method_opt->answer[0] == 'w')
  132. components = NetA_weakly_connected_components(graph, component);
  133. else
  134. components = NetA_strongly_connected_components(graph, component);
  135. G_debug(3, "Components: %d", components);
  136. Vect_copy_head_data(&In, &Out);
  137. Vect_hist_copy(&In, &Out);
  138. Vect_hist_command(&Out);
  139. nlines = Vect_get_num_lines(&In);
  140. for (i = 1; i <= nlines; i++) {
  141. int comp, cat;
  142. type = Vect_read_line(&In, Points, Cats, i);
  143. if (!Vect_cat_get(Cats, layer, &cat))
  144. continue;
  145. if (type == GV_LINE || type == GV_BOUNDARY) {
  146. int node1, node2;
  147. Vect_get_line_nodes(&In, i, &node1, &node2);
  148. if (component[node1] == component[node2]) {
  149. comp = component[node1];
  150. }
  151. else {
  152. continue;
  153. }
  154. }
  155. else if (type == GV_POINT) {
  156. int node;
  157. Vect_get_line_nodes(&In, i, &node, NULL);
  158. comp = component[node];
  159. covered[node] = 1;
  160. }
  161. else
  162. continue;
  163. Vect_write_line(&Out, type, Points, Cats);
  164. insert_new_record(driver, Fi, &sql, cat, comp);
  165. /* for(j=0;j<Cats->n_cats;j++)
  166. * if(Cats->field[j] == layer)
  167. * insert_new_record(driver, Fi, &sql, Cats->cat[j], comp);
  168. */
  169. };
  170. /*add points on nodes not covered by any point in the network */
  171. /*find the maximum cat number */
  172. if (add_f->answer) {
  173. max_cat = 0;
  174. for (i = 1; i <= nlines; i++) {
  175. Vect_read_line(&In, NULL, Cats, i);
  176. for (j = 0; j < Cats->n_cats; j++)
  177. if (Cats->cat[j] > max_cat)
  178. max_cat = Cats->cat[j];
  179. }
  180. max_cat++;
  181. for (i = 1; i <= nnodes; i++)
  182. if (!covered[i]) {
  183. Vect_reset_cats(Cats);
  184. Vect_cat_set(Cats, layer, max_cat);
  185. NetA_add_point_on_node(&In, &Out, i, Cats);
  186. insert_new_record(driver, Fi, &sql, max_cat++, component[i]);
  187. }
  188. }
  189. db_commit_transaction(driver);
  190. db_close_database_shutdown_driver(driver);
  191. Vect_build(&Out);
  192. Vect_close(&In);
  193. Vect_close(&Out);
  194. exit(EXIT_SUCCESS);
  195. }