main.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /****************************************************************
  2. *
  3. * MODULE: v.net.flow
  4. *
  5. * AUTHOR(S): Daniel Bundala
  6. *
  7. * PURPOSE: Max flow and min cut between two sets of nodes
  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 main(int argc, char *argv[])
  25. {
  26. struct Map_info In, Out, cut_map;
  27. static struct line_pnts *Points;
  28. struct line_cats *Cats;
  29. struct GModule *module; /* GRASS module for parsing arguments */
  30. struct Option *map_in, *map_out, *cut_out;
  31. struct Option *afield_opt, *nfield_opt, *abcol, *afcol, *ncol;
  32. struct Option *catsource_opt, *wheresource_opt;
  33. struct Option *catsink_opt, *wheresink_opt;
  34. int with_z;
  35. int afield, nfield, mask_type;
  36. struct varray *varray_source, *varray_sink;
  37. dglGraph_s *graph;
  38. int i, nlines, *flow, total_flow;
  39. struct ilist *source_list, *sink_list, *cut;
  40. int find_cut;
  41. char buf[2000];
  42. /* Attribute table */
  43. dbString sql;
  44. dbDriver *driver;
  45. struct field_info *Fi;
  46. /* initialize GIS environment */
  47. G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */
  48. /* initialize module */
  49. module = G_define_module();
  50. G_add_keyword(_("vector"));
  51. G_add_keyword(_("network"));
  52. G_add_keyword(_("flow"));
  53. module->description =
  54. _("Computes the maximum flow between two sets of nodes in the network.");
  55. /* Define the different options as defined in gis.h */
  56. map_in = G_define_standard_option(G_OPT_V_INPUT);
  57. afield_opt = G_define_standard_option(G_OPT_V_FIELD);
  58. afield_opt->key = "arc_layer";
  59. afield_opt->answer = "1";
  60. afield_opt->label = _("Arc layer");
  61. afield_opt->guisection = _("Cost");
  62. nfield_opt = G_define_standard_option(G_OPT_V_FIELD);
  63. nfield_opt->key = "node_layer";
  64. nfield_opt->answer = "2";
  65. nfield_opt->label = _("Node layer");
  66. nfield_opt->guisection = _("Cost");
  67. map_out = G_define_standard_option(G_OPT_V_OUTPUT);
  68. cut_out = G_define_standard_option(G_OPT_V_OUTPUT);
  69. cut_out->key = "cut";
  70. cut_out->description =
  71. _("Name for output vector map containing a minimum cut");
  72. afcol = G_define_standard_option(G_OPT_DB_COLUMN);
  73. afcol->key = "arc_column";
  74. afcol->required = NO;
  75. afcol->description =
  76. _("Arc forward/both direction(s) cost column (number)");
  77. afcol->guisection = _("Cost");
  78. abcol = G_define_standard_option(G_OPT_DB_COLUMN);
  79. abcol->key = "arc_backward_column";
  80. abcol->required = NO;
  81. abcol->description = _("Arc backward direction cost column (number)");
  82. abcol->guisection = _("Cost");
  83. ncol = G_define_standard_option(G_OPT_DB_COLUMN);
  84. ncol->key = "node_column";
  85. ncol->required = NO;
  86. ncol->description = _("Node cost column (number)");
  87. ncol->guisection = _("Cost");
  88. catsource_opt = G_define_standard_option(G_OPT_V_CATS);
  89. catsource_opt->key = "source_cats";
  90. catsource_opt->label = _("Source category values");
  91. catsource_opt->guisection = _("Source");
  92. wheresource_opt = G_define_standard_option(G_OPT_DB_WHERE);
  93. wheresource_opt->key = "source_where";
  94. wheresource_opt->label =
  95. _("Source WHERE conditions of SQL statement without 'where' keyword");
  96. wheresource_opt->guisection = _("Source");
  97. catsink_opt = G_define_standard_option(G_OPT_V_CATS);
  98. catsink_opt->key = "sink_cats";
  99. catsink_opt->label = _("Sink category values");
  100. catsink_opt->guisection = _("Sink");
  101. wheresink_opt = G_define_standard_option(G_OPT_DB_WHERE);
  102. wheresink_opt->key = "sink_where";
  103. wheresink_opt->label =
  104. _("Sink WHERE conditions of SQL statement without 'where' keyword");
  105. wheresink_opt->guisection = _("Sink");
  106. /* options and flags parser */
  107. if (G_parser(argc, argv))
  108. exit(EXIT_FAILURE);
  109. find_cut = (cut_out->answer[0]);
  110. /* TODO: make an option for this */
  111. mask_type = GV_LINE | GV_BOUNDARY;
  112. Points = Vect_new_line_struct();
  113. Cats = Vect_new_cats_struct();
  114. Vect_check_input_output_name(map_in->answer, map_out->answer,
  115. G_FATAL_EXIT);
  116. Vect_set_open_level(2);
  117. if (1 > Vect_open_old(&In, map_in->answer, ""))
  118. G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer);
  119. with_z = Vect_is_3d(&In);
  120. if (0 > Vect_open_new(&Out, map_out->answer, with_z)) {
  121. Vect_close(&In);
  122. G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer);
  123. }
  124. if (find_cut && 0 > Vect_open_new(&cut_map, cut_out->answer, with_z)) {
  125. Vect_close(&In);
  126. Vect_close(&Out);
  127. G_fatal_error(_("Unable to create vector map <%s>"), cut_out->answer);
  128. }
  129. /* parse filter option and select appropriate lines */
  130. afield = Vect_get_field_number(&In, afield_opt->answer);
  131. nfield = Vect_get_field_number(&In, nfield_opt->answer);
  132. /* Create table */
  133. Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
  134. Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
  135. Fi->driver);
  136. db_init_string(&sql);
  137. driver = db_start_driver_open_database(Fi->driver, Fi->database);
  138. if (driver == NULL)
  139. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  140. Fi->database, Fi->driver);
  141. db_set_error_handler_driver(driver);
  142. sprintf(buf, "create table %s (cat integer, flow double precision)",
  143. Fi->table);
  144. db_set_string(&sql, buf);
  145. G_debug(2, "%s", db_get_string(&sql));
  146. if (db_execute_immediate(driver, &sql) != DB_OK) {
  147. db_close_database_shutdown_driver(driver);
  148. G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
  149. }
  150. if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
  151. G_warning(_("Cannot create index"));
  152. if (db_grant_on_table
  153. (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
  154. G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table);
  155. db_begin_transaction(driver);
  156. source_list = Vect_new_list();
  157. sink_list = Vect_new_list();
  158. if (NetA_initialise_varray
  159. (&In, nfield, GV_POINT,
  160. wheresource_opt->answer, catsource_opt->answer, &varray_source) <= 0) {
  161. G_fatal_error(_("No source features selected. "
  162. "Please check options '%s', '%s'."),
  163. catsource_opt->key, wheresource_opt->key);
  164. }
  165. if (NetA_initialise_varray
  166. (&In, nfield, GV_POINT, wheresink_opt->answer,
  167. catsink_opt->answer, &varray_sink) <= 0) {
  168. G_fatal_error(_("No sink features selected. "
  169. "Please check options '%s', '%s'."),
  170. catsink_opt->key, wheresink_opt->key);
  171. }
  172. NetA_varray_to_nodes(&In, varray_source, source_list, NULL);
  173. NetA_varray_to_nodes(&In, varray_sink, sink_list, NULL);
  174. if (source_list->n_values == 0)
  175. G_fatal_error(_("No sources"));
  176. if (sink_list->n_values == 0)
  177. G_fatal_error(_("No sinks"));
  178. Vect_copy_head_data(&In, &Out);
  179. Vect_hist_copy(&In, &Out);
  180. Vect_hist_command(&Out);
  181. if (0 != Vect_net_build_graph(&In, mask_type, afield, nfield, afcol->answer, abcol->answer,
  182. ncol->answer, 0, 0))
  183. G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In));
  184. graph = Vect_net_get_graph(&In);
  185. nlines = Vect_get_num_lines(&In);
  186. flow = (int *)G_calloc(nlines + 1, sizeof(int));
  187. if (!flow)
  188. G_fatal_error(_("Out of memory"));
  189. total_flow = NetA_flow(graph, source_list, sink_list, flow);
  190. G_debug(3, "Max flow: %d", total_flow);
  191. if (find_cut) {
  192. cut = Vect_new_list();
  193. total_flow = NetA_min_cut(graph, source_list, sink_list, flow, cut);
  194. G_debug(3, "Min cut: %d", total_flow);
  195. }
  196. G_message(_("Writing the output..."));
  197. G_percent_reset();
  198. for (i = 1; i <= nlines; i++) {
  199. G_percent(i, nlines, 1);
  200. int type = Vect_read_line(&In, Points, Cats, i);
  201. Vect_write_line(&Out, type, Points, Cats);
  202. if (type == GV_LINE) {
  203. int cat;
  204. Vect_cat_get(Cats, afield, &cat);
  205. if (cat == -1)
  206. continue; /*TODO: warning? */
  207. sprintf(buf, "insert into %s values (%d, %f)", Fi->table, cat,
  208. flow[i] / (double)In.dgraph.cost_multip);
  209. db_set_string(&sql, buf);
  210. G_debug(3, "%s", db_get_string(&sql));
  211. if (db_execute_immediate(driver, &sql) != DB_OK) {
  212. db_close_database_shutdown_driver(driver);
  213. G_fatal_error(_("Cannot insert new record: %s"),
  214. db_get_string(&sql));
  215. };
  216. }
  217. }
  218. if (find_cut) {
  219. for (i = 0; i < cut->n_values; i++) {
  220. int type = Vect_read_line(&In, Points, Cats, cut->value[i]);
  221. Vect_write_line(&cut_map, type, Points, Cats);
  222. }
  223. Vect_destroy_list(cut);
  224. Vect_build(&cut_map);
  225. Vect_close(&cut_map);
  226. }
  227. db_commit_transaction(driver);
  228. db_close_database_shutdown_driver(driver);
  229. G_free(flow);
  230. Vect_destroy_list(source_list);
  231. Vect_destroy_list(sink_list);
  232. Vect_build(&Out);
  233. Vect_close(&In);
  234. Vect_close(&Out);
  235. exit(EXIT_SUCCESS);
  236. }