main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /****************************************************************
  2. *
  3. * MODULE: v.net.alloc
  4. *
  5. * AUTHOR(S): Radim Blazek
  6. *
  7. * PURPOSE: Allocate subnets for nearest centres.
  8. *
  9. * COPYRIGHT: (C) 2001 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 <stdlib.h>
  18. #include <string.h>
  19. #include <time.h>
  20. #include <grass/gis.h>
  21. #include <grass/Vect.h>
  22. #include <grass/dbmi.h>
  23. #include <grass/glocale.h>
  24. typedef struct
  25. {
  26. int cat; /* category number */
  27. int node; /* node number */
  28. } CENTER;
  29. typedef struct
  30. {
  31. int centre; /* neares centre, initialy -1 */
  32. double cost; /* costs from this centre, initialy not undefined */
  33. } NODE;
  34. int main(int argc, char **argv)
  35. {
  36. int i, j, ret, centre, line, centre1, centre2;
  37. int nlines, nnodes, type, ltype, afield, nfield, geo, cat;
  38. int node, node1, node2;
  39. double cost, e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1, l2;
  40. struct Option *map, *output;
  41. struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt,
  42. *term_opt;
  43. struct Flag *geo_f;
  44. struct GModule *module;
  45. char *mapset;
  46. struct Map_info Map, Out;
  47. struct cat_list *catlist;
  48. CENTER *Centers = NULL;
  49. int acentres = 0, ncentres = 0;
  50. NODE *Nodes;
  51. struct line_cats *Cats;
  52. struct line_pnts *Points, *SPoints;
  53. G_gisinit(argv[0]);
  54. module = G_define_module();
  55. module->keywords = _("vector, networking");
  56. module->label =
  57. _("Allocate subnets for nearest centres (direction from centre).");
  58. module->description =
  59. _("Centre node must be opened (costs >= 0). "
  60. "Costs of centre node are used in calculation");
  61. map = G_define_standard_option(G_OPT_V_INPUT);
  62. output = G_define_standard_option(G_OPT_V_OUTPUT);
  63. type_opt = G_define_standard_option(G_OPT_V_TYPE);
  64. type_opt->options = "line,boundary";
  65. type_opt->answer = "line,boundary";
  66. type_opt->description = _("Arc type");
  67. afield_opt = G_define_standard_option(G_OPT_V_FIELD);
  68. afield_opt->key = "alayer";
  69. afield_opt->answer = "1";
  70. afield_opt->description = _("Arc layer");
  71. nfield_opt = G_define_standard_option(G_OPT_V_FIELD);
  72. nfield_opt->key = "nlayer";
  73. nfield_opt->answer = "2";
  74. nfield_opt->description = _("Node layer");
  75. afcol = G_define_option();
  76. afcol->key = "afcolumn";
  77. afcol->type = TYPE_STRING;
  78. afcol->required = NO;
  79. afcol->description =
  80. _("Arc forward/both direction(s) cost column (number)");
  81. abcol = G_define_option();
  82. abcol->key = "abcolumn";
  83. abcol->type = TYPE_STRING;
  84. abcol->required = NO;
  85. abcol->description = _("Arc backward direction cost column (number)");
  86. ncol = G_define_option();
  87. ncol->key = "ncolumn";
  88. ncol->type = TYPE_STRING;
  89. ncol->required = NO;
  90. ncol->description = _("Node cost column (number)");
  91. term_opt = G_define_standard_option(G_OPT_V_CATS);
  92. term_opt->key = "ccats";
  93. term_opt->required = YES;
  94. term_opt->description =
  95. _("Categories of centres (points on nodes) to which net "
  96. "will be allocated, "
  97. "layer for this categories is given by nlayer option");
  98. geo_f = G_define_flag();
  99. geo_f->key = 'g';
  100. geo_f->description =
  101. _("Use geodesic calculation for longitude-latitude locations");
  102. if (G_parser(argc, argv))
  103. exit(EXIT_FAILURE);
  104. Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT);
  105. Cats = Vect_new_cats_struct();
  106. Points = Vect_new_line_struct();
  107. SPoints = Vect_new_line_struct();
  108. type = Vect_option_to_types(type_opt);
  109. afield = atoi(afield_opt->answer);
  110. nfield = atoi(nfield_opt->answer);
  111. catlist = Vect_new_cat_list();
  112. Vect_str_to_cat_list(term_opt->answer, catlist);
  113. if (geo_f->answer)
  114. geo = 1;
  115. else
  116. geo = 0;
  117. mapset = G_find_vector2(map->answer, NULL);
  118. if (mapset == NULL)
  119. G_fatal_error(_("Vector map <%s> not found"), map->answer);
  120. Vect_set_open_level(2);
  121. Vect_open_old(&Map, map->answer, mapset);
  122. /* Build graph */
  123. Vect_net_build_graph(&Map, type, afield, nfield, afcol->answer,
  124. abcol->answer, ncol->answer, geo, 0);
  125. nnodes = Vect_get_num_nodes(&Map);
  126. /* Create list of centres based on list of categories */
  127. for (node = 1; node <= nnodes; node++) {
  128. nlines = Vect_get_node_n_lines(&Map, node);
  129. for (j = 0; j < nlines; j++) {
  130. line = abs(Vect_get_node_line(&Map, node, j));
  131. ltype = Vect_read_line(&Map, NULL, Cats, line);
  132. if (!(ltype & GV_POINT))
  133. continue;
  134. if (!(Vect_cat_get(Cats, nfield, &cat)))
  135. continue;
  136. if (Vect_cat_in_cat_list(cat, catlist)) {
  137. Vect_net_get_node_cost(&Map, node, &n1cost);
  138. if (n1cost == -1) { /* closed */
  139. G_warning("Centre at closed node (costs = -1) ignored");
  140. }
  141. else {
  142. if (acentres == ncentres) {
  143. acentres += 1;
  144. Centers =
  145. (CENTER *) G_realloc(Centers,
  146. acentres * sizeof(CENTER));
  147. }
  148. Centers[ncentres].cat = cat;
  149. Centers[ncentres].node = node;
  150. G_debug(2, "centre = %d node = %d cat = %d", ncentres,
  151. node, cat);
  152. ncentres++;
  153. }
  154. }
  155. }
  156. }
  157. G_message(_("Number of centres: [%d] (nlayer: [%d])"), ncentres, nfield);
  158. if (ncentres == 0)
  159. G_warning(_("Not enough centres for selected nlayer. "
  160. "Nothing will be allocated."));
  161. /* alloc and reset space for all nodes */
  162. Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE));
  163. for (i = 1; i <= nnodes; i++) {
  164. Nodes[i].centre = -1;
  165. }
  166. /* Fill Nodes by neares centre and costs from that centre */
  167. G_message(_("Calculating costs from centres ..."));
  168. for (centre = 0; centre < ncentres; centre++) {
  169. G_percent(centre, ncentres, 1);
  170. node1 = Centers[centre].node;
  171. Vect_net_get_node_cost(&Map, node1, &n1cost);
  172. G_debug(2, "centre = %d node = %d cat = %d", centre, node1,
  173. Centers[centre].cat);
  174. for (node2 = 1; node2 <= nnodes; node2++) {
  175. G_debug(5, " node1 = %d node2 = %d", node1, node2);
  176. Vect_net_get_node_cost(&Map, node2, &n2cost);
  177. if (n2cost == -1) {
  178. continue;
  179. } /* closed, left it as not attached */
  180. ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &cost);
  181. if (ret == -1) {
  182. continue;
  183. } /* node unreachable */
  184. /* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but
  185. * only if centre and node are not identical, because at the end node cost is add later */
  186. if (node1 != node2)
  187. cost += n1cost;
  188. G_debug(5,
  189. "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
  190. node1, node2, cost, Nodes[node2].centre,
  191. Nodes[node2].cost);
  192. if (Nodes[node2].centre == -1 || cost < Nodes[node2].cost) {
  193. Nodes[node2].cost = cost;
  194. Nodes[node2].centre = centre;
  195. }
  196. }
  197. }
  198. G_percent(1, 1, 1);
  199. /* Write arcs to new map */
  200. Vect_open_new(&Out, output->answer, Vect_is_3d(&Map));
  201. Vect_hist_command(&Out);
  202. nlines = Vect_get_num_lines(&Map);
  203. for (line = 1; line <= nlines; line++) {
  204. ltype = Vect_read_line(&Map, Points, NULL, line);
  205. if (!(ltype & type)) {
  206. continue;
  207. }
  208. Vect_get_line_nodes(&Map, line, &node1, &node2);
  209. centre1 = Nodes[node1].centre;
  210. centre2 = Nodes[node2].centre;
  211. s1cost = Nodes[node1].cost;
  212. s2cost = Nodes[node2].cost;
  213. G_debug(3, "Line %d:", line);
  214. G_debug(3, "Arc centres: %d %d (nodes: %d %d)", centre1, centre2,
  215. node1, node2);
  216. Vect_net_get_node_cost(&Map, node1, &n1cost);
  217. Vect_net_get_node_cost(&Map, node2, &n2cost);
  218. Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost);
  219. Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost);
  220. G_debug(3, " s1cost = %f n1cost = %f e1cost = %f", s1cost, n1cost,
  221. e1cost);
  222. G_debug(3, " s2cost = %f n2cost = %f e2cost = %f", s2cost, n2cost,
  223. e2cost);
  224. Vect_reset_cats(Cats);
  225. /* First check if arc is reachable from at least one side */
  226. if ((centre1 != -1 && n1cost != -1 && e1cost != -1) ||
  227. (centre2 != -1 && n2cost != -1 && e2cost != -1)) {
  228. /* Line is reachable at least from one side */
  229. G_debug(3, " -> arc is reachable");
  230. if (centre1 == centre2) { /* both nodes in one area -> whole arc in one area */
  231. if (centre1 != -1)
  232. cat = Centers[centre1].cat; /* line reachable */
  233. else
  234. cat = Centers[centre2].cat;
  235. Vect_cat_set(Cats, 1, cat);
  236. Vect_write_line(&Out, ltype, Points, Cats);
  237. }
  238. else { /* each node in different area */
  239. /* Check if direction is reachable */
  240. if (centre1 == -1 || n1cost == -1 || e1cost == -1) { /* closed from first node */
  241. G_debug(3,
  242. " -> arc is not reachable from 1. node -> alloc to 2. node");
  243. cat = Centers[centre2].cat;
  244. Vect_cat_set(Cats, 1, cat);
  245. Vect_write_line(&Out, ltype, Points, Cats);
  246. continue;
  247. }
  248. else if (centre2 == -1 || n2cost == -1 || e2cost == -1) { /* closed from second node */
  249. G_debug(3,
  250. " -> arc is not reachable from 2. node -> alloc to 1. node");
  251. cat = Centers[centre1].cat;
  252. Vect_cat_set(Cats, 1, cat);
  253. Vect_write_line(&Out, ltype, Points, Cats);
  254. continue;
  255. }
  256. /* Now we know that arc is reachable from both sides */
  257. /* Add costs of node to starting costs */
  258. s1cost += n1cost;
  259. s2cost += n2cost;
  260. /* Check if s1cost + e1cost <= s2cost or s2cost + e2cost <= s1cost !
  261. * Note this check also possibility of (e1cost + e2cost) = 0 */
  262. if (s1cost + e1cost <= s2cost) { /* whole arc reachable from node1 */
  263. cat = Centers[centre1].cat;
  264. Vect_cat_set(Cats, 1, cat);
  265. Vect_write_line(&Out, ltype, Points, Cats);
  266. }
  267. else if (s2cost + e2cost <= s1cost) { /* whole arc reachable from node2 */
  268. cat = Centers[centre2].cat;
  269. Vect_cat_set(Cats, 1, cat);
  270. Vect_write_line(&Out, ltype, Points, Cats);
  271. }
  272. else { /* split */
  273. /* Calculate relative costs - we expect that costs along the line do not change */
  274. l = Vect_line_length(Points);
  275. e1cost /= l;
  276. e2cost /= l;
  277. G_debug(3, " -> s1cost = %f e1cost = %f", s1cost,
  278. e1cost);
  279. G_debug(3, " -> s2cost = %f e2cost = %f", s2cost,
  280. e2cost);
  281. /* Costs from both centres to the splitting point must be equal:
  282. * s1cost + l1 * e1cost = s2cost + l2 * e2cost */
  283. l1 = (l * e2cost - s1cost + s2cost) / (e1cost + e2cost);
  284. l2 = l - l1;
  285. G_debug(3, "l = %f l1 = %f l2 = %f", l, l1, l2);
  286. /* First segment */
  287. ret = Vect_line_segment(Points, 0, l1, SPoints);
  288. if (ret == 0) {
  289. G_warning(_("Cannot get line segment, segment out of line"));
  290. }
  291. else {
  292. cat = Centers[centre1].cat;
  293. Vect_cat_set(Cats, 1, cat);
  294. Vect_write_line(&Out, ltype, SPoints, Cats);
  295. }
  296. /* Second segment */
  297. ret = Vect_line_segment(Points, l1, l, SPoints);
  298. if (ret == 0) {
  299. G_warning(_("Cannot get line segment, segment out of line"));
  300. }
  301. else {
  302. Vect_reset_cats(Cats);
  303. cat = Centers[centre2].cat;
  304. Vect_cat_set(Cats, 1, cat);
  305. Vect_write_line(&Out, ltype, SPoints, Cats);
  306. }
  307. }
  308. }
  309. }
  310. else {
  311. /* arc is not reachable */
  312. G_debug(3, " -> arc is not reachable");
  313. Vect_write_line(&Out, ltype, Points, Cats);
  314. }
  315. }
  316. Vect_build(&Out, stderr);
  317. /* Free, ... */
  318. G_free(Nodes);
  319. G_free(Centers);
  320. Vect_close(&Map);
  321. Vect_close(&Out);
  322. exit(EXIT_SUCCESS);
  323. }