main.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. /****************************************************************
  2. *
  3. * MODULE: v.net.alloc
  4. *
  5. * AUTHOR(S): Radim Blazek
  6. * Stepan Turek <stepan.turek seznam.cz> (turns support)
  7. * Markus Metz (costs from/to centers; attributes)
  8. *
  9. * PURPOSE: Allocate subnets for nearest centers
  10. *
  11. * COPYRIGHT: (C) 2001, 2016,2017 by the GRASS Development Team
  12. *
  13. * This program is free software under the
  14. * GNU General Public License (>=v2).
  15. * Read the file COPYING that comes with GRASS
  16. * for details.
  17. *
  18. ****************************************************************/
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <time.h>
  22. #include <grass/gis.h>
  23. #include <grass/vector.h>
  24. #include <grass/dbmi.h>
  25. #include <grass/glocale.h>
  26. #include "alloc.h"
  27. int main(int argc, char **argv)
  28. {
  29. int i, ret, line, center1, center2;
  30. int nlines, nnodes, type, ltype, afield, nfield, geo, cat;
  31. int tfield, tucfield;
  32. int node1, node2;
  33. double e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1, l2;
  34. struct Option *map, *output, *method_opt;
  35. struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt,
  36. *term_opt, *tfield_opt, *tucfield_opt;
  37. struct Flag *geo_f, *turntable_f, *ucat_f;
  38. struct GModule *module;
  39. struct Map_info Map, Out;
  40. struct cat_list *catlist;
  41. CENTER *Centers = NULL;
  42. int acenters = 0, ncenters = 0;
  43. NODE *Nodes;
  44. struct line_cats *Cats, *ICats, *OCats;
  45. struct line_pnts *Points, *SPoints;
  46. int graph_version;
  47. int from_centers;
  48. /* Attribute table */
  49. int unique_cats, ucat, ocat, n;
  50. char buf[2000];
  51. dbString sql;
  52. dbDriver *driver;
  53. struct field_info *Fi;
  54. /* initialize GIS environment */
  55. G_gisinit(argv[0]);
  56. /* initialize module */
  57. module = G_define_module();
  58. G_add_keyword(_("vector"));
  59. G_add_keyword(_("network"));
  60. G_add_keyword(_("cost allocation"));
  61. module->label = _("Allocates subnets for nearest centers.");
  62. module->description =
  63. _("Center node must be opened (costs >= 0). "
  64. "Costs of center node are used in calculation.");
  65. map = G_define_standard_option(G_OPT_V_INPUT);
  66. output = G_define_standard_option(G_OPT_V_OUTPUT);
  67. method_opt = G_define_option();
  68. method_opt->key = "method";
  69. method_opt->type = TYPE_STRING;
  70. method_opt->required = NO;
  71. method_opt->options = "from,to";
  72. method_opt->answer = "from";
  73. method_opt->description = _("Use costs from centers or costs to centers");
  74. method_opt->guisection = _("Cost");
  75. term_opt = G_define_standard_option(G_OPT_V_CATS);
  76. term_opt->key = "center_cats";
  77. term_opt->required = YES;
  78. term_opt->description =
  79. _("Categories of centers (points on nodes) to which net "
  80. "will be allocated, "
  81. "layer for this categories is given by nlayer option");
  82. afield_opt = G_define_standard_option(G_OPT_V_FIELD);
  83. afield_opt->key = "arc_layer";
  84. afield_opt->answer = "1";
  85. afield_opt->required = YES;
  86. afield_opt->label = _("Arc layer");
  87. type_opt = G_define_standard_option(G_OPT_V_TYPE);
  88. type_opt->key = "arc_type";
  89. type_opt->options = "line,boundary";
  90. type_opt->answer = "line,boundary";
  91. type_opt->required = YES;
  92. type_opt->label = _("Arc type");
  93. nfield_opt = G_define_standard_option(G_OPT_V_FIELD);
  94. nfield_opt->key = "node_layer";
  95. nfield_opt->answer = "2";
  96. nfield_opt->required = YES;
  97. nfield_opt->label = _("Node layer");
  98. afcol = G_define_standard_option(G_OPT_DB_COLUMN);
  99. afcol->key = "arc_column";
  100. afcol->description =
  101. _("Arc forward/both direction(s) cost column (number)");
  102. afcol->guisection = _("Cost");
  103. abcol = G_define_standard_option(G_OPT_DB_COLUMN);
  104. abcol->key = "arc_backward_column";
  105. abcol->description = _("Arc backward direction cost column (number)");
  106. abcol->guisection = _("Cost");
  107. ncol = G_define_standard_option(G_OPT_DB_COLUMN);
  108. ncol->key = "node_column";
  109. ncol->description = _("Node cost column (number)");
  110. ncol->guisection = _("Cost");
  111. turntable_f = G_define_flag();
  112. turntable_f->key = 't';
  113. turntable_f->description = _("Use turntable");
  114. turntable_f->guisection = _("Turntable");
  115. tfield_opt = G_define_standard_option(G_OPT_V_FIELD);
  116. tfield_opt->key = "turn_layer";
  117. tfield_opt->answer = "3";
  118. tfield_opt->label = _("Layer with turntable");
  119. tfield_opt->description =
  120. _("Relevant only with -t flag");
  121. tfield_opt->guisection = _("Turntable");
  122. tucfield_opt = G_define_standard_option(G_OPT_V_FIELD);
  123. tucfield_opt->key = "turn_cat_layer";
  124. tucfield_opt->answer = "4";
  125. tucfield_opt->label = _("Layer with unique categories used in turntable");
  126. tucfield_opt->description =
  127. _("Relevant only with -t flag");
  128. tucfield_opt->guisection = _("Turntable");
  129. geo_f = G_define_flag();
  130. geo_f->key = 'g';
  131. geo_f->description =
  132. _("Use geodesic calculation for longitude-latitude locations");
  133. ucat_f = G_define_flag();
  134. ucat_f->key = 'u';
  135. ucat_f->label =
  136. _("Create unique categories and attribute table");
  137. ucat_f->description =
  138. _("Default: same category like nearest center");
  139. if (G_parser(argc, argv))
  140. exit(EXIT_FAILURE);
  141. Vect_check_input_output_name(map->answer, output->answer, G_FATAL_EXIT);
  142. Cats = Vect_new_cats_struct();
  143. ICats = Vect_new_cats_struct();
  144. OCats = Vect_new_cats_struct();
  145. Points = Vect_new_line_struct();
  146. SPoints = Vect_new_line_struct();
  147. type = Vect_option_to_types(type_opt);
  148. catlist = Vect_new_cat_list();
  149. Vect_str_to_cat_list(term_opt->answer, catlist);
  150. unique_cats = ucat_f->answer;
  151. if (geo_f->answer)
  152. geo = 1;
  153. else
  154. geo = 0;
  155. Vect_set_open_level(2);
  156. if (Vect_open_old(&Map, map->answer, "") < 0)
  157. G_fatal_error(_("Unable to open vector map <%s>"), map->answer);
  158. afield = Vect_get_field_number(&Map, afield_opt->answer);
  159. nfield = Vect_get_field_number(&Map, nfield_opt->answer);
  160. tfield = Vect_get_field_number(&Map, tfield_opt->answer);
  161. tucfield = Vect_get_field_number(&Map, tucfield_opt->answer);
  162. /* Build graph */
  163. graph_version = 1;
  164. from_centers = 1;
  165. if (method_opt->answer[0] == 't') {
  166. from_centers = 0;
  167. if (!turntable_f->answer)
  168. graph_version = 2;
  169. }
  170. if (turntable_f->answer)
  171. Vect_net_ttb_build_graph(&Map, type, afield, nfield, tfield, tucfield,
  172. afcol->answer, abcol->answer, ncol->answer,
  173. geo, 0);
  174. else
  175. Vect_net_build_graph(&Map, type, afield, nfield, afcol->answer,
  176. abcol->answer, ncol->answer, geo, graph_version);
  177. nnodes = Vect_get_num_nodes(&Map);
  178. nlines = Vect_get_num_lines(&Map);
  179. /* Create list of centers based on list of categories */
  180. for (i = 1; i <= nlines; i++) {
  181. int node;
  182. ltype = Vect_get_line_type(&Map, i);
  183. if (!(ltype & GV_POINT))
  184. continue;
  185. Vect_read_line(&Map, Points, Cats, i);
  186. node =
  187. Vect_find_node(&Map, Points->x[0], Points->y[0], Points->z[0], 0,
  188. 0);
  189. if (!node) {
  190. G_warning(_("Point is not connected to the network"));
  191. continue;
  192. }
  193. if (!(Vect_cat_get(Cats, nfield, &cat)))
  194. continue;
  195. if (Vect_cat_in_cat_list(cat, catlist)) {
  196. Vect_net_get_node_cost(&Map, node, &n1cost);
  197. if (n1cost == -1) { /* closed */
  198. G_warning(_("Center at closed node (costs = -1) ignored"));
  199. }
  200. else {
  201. if (acenters == ncenters) {
  202. acenters += 1;
  203. Centers =
  204. (CENTER *) G_realloc(Centers,
  205. acenters * sizeof(CENTER));
  206. }
  207. Centers[ncenters].cat = cat;
  208. Centers[ncenters].node = node;
  209. G_debug(2, "center = %d node = %d cat = %d", ncenters,
  210. node, cat);
  211. ncenters++;
  212. }
  213. }
  214. }
  215. G_message(_("Number of centers: %d (nlayer %d)"), ncenters, nfield);
  216. if (ncenters == 0)
  217. G_warning(_("Not enough centers for selected nlayer. Nothing will be allocated."));
  218. /* alloc and reset space for all nodes */
  219. if (turntable_f->answer) {
  220. /* if turntable is used we are looking for lines as destinations, instead of the intersections (nodes) */
  221. Nodes = (NODE *) G_calloc((nlines * 2 + 2), sizeof(NODE));
  222. for (i = 2; i <= (nlines * 2 + 2); i++) {
  223. Nodes[i].center = -1;/* NOTE: first two items of Nodes are not used */
  224. }
  225. }
  226. else {
  227. Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE));
  228. for (i = 1; i <= nnodes; i++) {
  229. Nodes[i].center = -1;
  230. }
  231. }
  232. /* Fill Nodes by nearest center and costs from that center */
  233. if (turntable_f->answer) {
  234. if (from_centers) {
  235. G_message(_("Calculating costs from centers ..."));
  236. alloc_from_centers_loop_tt(&Map, Nodes, Centers, ncenters,
  237. tucfield);
  238. }
  239. else {
  240. G_message(_("Calculating costs to centers ..."));
  241. alloc_to_centers_loop_tt(&Map, Nodes, Centers, ncenters,
  242. tucfield);
  243. }
  244. }
  245. else {
  246. if (from_centers) {
  247. G_message(_("Calculating costs from centers ..."));
  248. alloc_from_centers(Vect_net_get_graph(&Map), Nodes, Centers, ncenters);
  249. }
  250. else {
  251. G_message(_("Calculating costs to centers ..."));
  252. alloc_to_centers(Vect_net_get_graph(&Map), Nodes, Centers, ncenters);
  253. }
  254. }
  255. /* Write arcs to new map */
  256. if (Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)) < 0)
  257. G_fatal_error(_("Unable to create vector map <%s>"), output->answer);
  258. Vect_hist_command(&Out);
  259. Fi = NULL;
  260. driver = NULL;
  261. if (unique_cats) {
  262. /* create attribute table:
  263. * cat: new category
  264. * ocat: original category in afield
  265. * center: nearest center
  266. */
  267. Fi = Vect_default_field_info(&Out, 1, NULL, GV_MTABLE);
  268. Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
  269. Fi->driver);
  270. driver = db_start_driver_open_database(Fi->driver, Fi->database);
  271. if (driver == NULL)
  272. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  273. Fi->database, Fi->driver);
  274. db_set_error_handler_driver(driver);
  275. sprintf(buf,
  276. "create table %s ( %s integer, ocat integer, center integer )",
  277. Fi->table, GV_KEY_COLUMN);
  278. db_init_string(&sql);
  279. db_set_string(&sql, buf);
  280. G_debug(2, "%s", db_get_string(&sql));
  281. if (db_execute_immediate(driver, &sql) != DB_OK) {
  282. G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
  283. }
  284. if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
  285. G_warning(_("Cannot create index"));
  286. if (db_grant_on_table
  287. (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
  288. G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table);
  289. db_begin_transaction(driver);
  290. }
  291. G_message(_("Allocating subnets..."));
  292. nlines = Vect_get_num_lines(&Map);
  293. ucat = 1;
  294. for (line = 1; line <= nlines; line++) {
  295. G_percent(line, nlines, 2);
  296. ltype = Vect_read_line(&Map, Points, ICats, line);
  297. if (!(ltype & type)) {
  298. continue;
  299. }
  300. if (unique_cats) {
  301. Vect_reset_cats(OCats);
  302. for (n = 0; n < ICats->n_cats; n++) {
  303. if (ICats->field[n] == afield) {
  304. Vect_cat_set(OCats, 2, ICats->cat[n]);
  305. }
  306. }
  307. }
  308. if (turntable_f->answer) {
  309. center1 = Nodes[line * 2].center;
  310. center2 = Nodes[line * 2 + 1].center;
  311. s1cost = Nodes[line * 2].cost;
  312. s2cost = Nodes[line * 2 + 1].cost;
  313. n1cost = n2cost = 0;
  314. }
  315. else {
  316. Vect_get_line_nodes(&Map, line, &node1, &node2);
  317. center1 = Nodes[node1].center;
  318. center2 = Nodes[node2].center;
  319. s1cost = Nodes[node1].cost;
  320. s2cost = Nodes[node2].cost;
  321. if (s1cost > 0)
  322. s1cost /= Map.dgraph.cost_multip;
  323. if (s2cost > 0)
  324. s2cost /= Map.dgraph.cost_multip;
  325. Vect_net_get_node_cost(&Map, node1, &n1cost);
  326. Vect_net_get_node_cost(&Map, node2, &n2cost);
  327. }
  328. if (from_centers) {
  329. Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost);
  330. Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost);
  331. }
  332. else {
  333. /* from node to center */
  334. Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e2cost);
  335. Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e1cost);
  336. }
  337. G_debug(3, "Line %d:", line);
  338. G_debug(3, "Arc centers: %d %d (nodes: %d %d)", center1, center2,
  339. node1, node2);
  340. G_debug(3, " s1cost = %f n1cost = %f e1cost = %f", s1cost, n1cost,
  341. e1cost);
  342. G_debug(3, " s2cost = %f n2cost = %f e2cost = %f", s2cost, n2cost,
  343. e2cost);
  344. Vect_reset_cats(Cats);
  345. /* First check if arc is reachable from at least one side */
  346. if ((center1 != -1 && n1cost != -1 && e1cost != -1) ||
  347. (center2 != -1 && n2cost != -1 && e2cost != -1)) {
  348. /* Line is reachable at least from one side */
  349. G_debug(3, " -> arc is reachable");
  350. if (center1 == center2) { /* both nodes in one area -> whole arc in one area */
  351. if (center1 != -1)
  352. cat = Centers[center1].cat; /* line reachable */
  353. else
  354. cat = Centers[center2].cat;
  355. if (unique_cats) {
  356. Vect_cat_set(Cats, 1, ucat);
  357. for (n = 0; n < OCats->n_cats; n++) {
  358. Vect_cat_set(Cats, 2, OCats->cat[n]);
  359. }
  360. ocat = -1;
  361. Vect_cat_get(ICats, afield, &ocat);
  362. sprintf(buf,
  363. "insert into %s values ( %d, %d, %d )",
  364. Fi->table, ucat, ocat, cat);
  365. db_set_string(&sql, buf);
  366. G_debug(3, "%s", db_get_string(&sql));
  367. if (db_execute_immediate(driver, &sql) != DB_OK) {
  368. G_fatal_error(_("Cannot insert new record: %s"),
  369. db_get_string(&sql));
  370. }
  371. ucat++;
  372. }
  373. else
  374. Vect_cat_set(Cats, 1, cat);
  375. Vect_write_line(&Out, ltype, Points, Cats);
  376. }
  377. else { /* each node in different area */
  378. /* Check if line is reachable from center */
  379. if (center1 == -1 || n1cost == -1 || e1cost == -1) { /* closed from first node */
  380. G_debug(3,
  381. " -> arc is not reachable from 1. node -> alloc to 2. node");
  382. cat = Centers[center2].cat;
  383. if (unique_cats) {
  384. Vect_cat_set(Cats, 1, ucat);
  385. for (n = 0; n < OCats->n_cats; n++) {
  386. Vect_cat_set(Cats, 2, OCats->cat[n]);
  387. }
  388. ocat = -1;
  389. Vect_cat_get(ICats, afield, &ocat);
  390. sprintf(buf,
  391. "insert into %s values ( %d, %d, %d )",
  392. Fi->table, ucat, ocat, cat);
  393. db_set_string(&sql, buf);
  394. G_debug(3, "%s", db_get_string(&sql));
  395. if (db_execute_immediate(driver, &sql) != DB_OK) {
  396. G_fatal_error(_("Cannot insert new record: %s"),
  397. db_get_string(&sql));
  398. }
  399. ucat++;
  400. }
  401. else
  402. Vect_cat_set(Cats, 1, cat);
  403. Vect_write_line(&Out, ltype, Points, Cats);
  404. continue;
  405. }
  406. else if (center2 == -1 || n2cost == -1 || e2cost == -1) { /* closed from second node */
  407. G_debug(3,
  408. " -> arc is not reachable from 2. node -> alloc to 1. node");
  409. cat = Centers[center1].cat;
  410. if (unique_cats) {
  411. Vect_cat_set(Cats, 1, ucat);
  412. for (n = 0; n < OCats->n_cats; n++) {
  413. Vect_cat_set(Cats, 2, OCats->cat[n]);
  414. }
  415. ocat = -1;
  416. Vect_cat_get(ICats, afield, &ocat);
  417. sprintf(buf,
  418. "insert into %s values ( %d, %d, %d )",
  419. Fi->table, ucat, ocat, cat);
  420. db_set_string(&sql, buf);
  421. G_debug(3, "%s", db_get_string(&sql));
  422. if (db_execute_immediate(driver, &sql) != DB_OK) {
  423. G_fatal_error(_("Cannot insert new record: %s"),
  424. db_get_string(&sql));
  425. }
  426. ucat++;
  427. }
  428. else
  429. Vect_cat_set(Cats, 1, cat);
  430. Vect_write_line(&Out, ltype, Points, Cats);
  431. continue;
  432. }
  433. /* Now we know that arc is reachable from both sides */
  434. /* Add costs of node to starting costs */
  435. s1cost += n1cost;
  436. s2cost += n2cost;
  437. /* Check if s1cost + e1cost <= s2cost or s2cost + e2cost <= s1cost !
  438. * Note this check also possibility of (e1cost + e2cost) = 0 */
  439. if (s1cost + e1cost <= s2cost) { /* whole arc reachable from node1 */
  440. cat = Centers[center1].cat;
  441. Vect_reset_cats(Cats);
  442. if (unique_cats) {
  443. Vect_cat_set(Cats, 1, ucat);
  444. for (n = 0; n < OCats->n_cats; n++) {
  445. Vect_cat_set(Cats, 2, OCats->cat[n]);
  446. }
  447. ocat = -1;
  448. Vect_cat_get(ICats, afield, &ocat);
  449. sprintf(buf,
  450. "insert into %s values ( %d, %d, %d )",
  451. Fi->table, ucat, ocat, cat);
  452. db_set_string(&sql, buf);
  453. G_debug(3, "%s", db_get_string(&sql));
  454. if (db_execute_immediate(driver, &sql) != DB_OK) {
  455. G_fatal_error(_("Cannot insert new record: %s"),
  456. db_get_string(&sql));
  457. }
  458. ucat++;
  459. }
  460. else
  461. Vect_cat_set(Cats, 1, cat);
  462. Vect_write_line(&Out, ltype, Points, Cats);
  463. }
  464. else if (s2cost + e2cost <= s1cost) { /* whole arc reachable from node2 */
  465. cat = Centers[center2].cat;
  466. if (unique_cats) {
  467. Vect_cat_set(Cats, 1, ucat);
  468. for (n = 0; n < OCats->n_cats; n++) {
  469. Vect_cat_set(Cats, 2, OCats->cat[n]);
  470. }
  471. ocat = -1;
  472. Vect_cat_get(ICats, afield, &ocat);
  473. sprintf(buf,
  474. "insert into %s values ( %d, %d, %d )",
  475. Fi->table, ucat, ocat, cat);
  476. db_set_string(&sql, buf);
  477. G_debug(3, "%s", db_get_string(&sql));
  478. if (db_execute_immediate(driver, &sql) != DB_OK) {
  479. G_fatal_error(_("Cannot insert new record: %s"),
  480. db_get_string(&sql));
  481. }
  482. ucat++;
  483. }
  484. else
  485. Vect_cat_set(Cats, 1, cat);
  486. Vect_write_line(&Out, ltype, Points, Cats);
  487. }
  488. else { /* split */
  489. /* Calculate relative costs - we expect that costs along the line do not change */
  490. l = Vect_line_length(Points);
  491. e1cost /= l;
  492. e2cost /= l;
  493. G_debug(3, " -> s1cost = %f e1cost = %f", s1cost,
  494. e1cost);
  495. G_debug(3, " -> s2cost = %f e2cost = %f", s2cost,
  496. e2cost);
  497. /* Costs from both centers to the splitting point must be equal:
  498. * s1cost + l1 * e1cost = s2cost + l2 * e2cost */
  499. l1 = (l * e2cost - s1cost + s2cost) / (e1cost + e2cost);
  500. l2 = l - l1;
  501. G_debug(3, "l = %f l1 = %f l2 = %f", l, l1, l2);
  502. /* First segment */
  503. ret = Vect_line_segment(Points, 0, l1, SPoints);
  504. if (ret == 0) {
  505. G_warning(_
  506. ("Cannot get line segment, segment out of line"));
  507. }
  508. else {
  509. cat = Centers[center1].cat;
  510. if (unique_cats) {
  511. Vect_cat_set(Cats, 1, ucat);
  512. for (n = 0; n < OCats->n_cats; n++) {
  513. Vect_cat_set(Cats, 2, OCats->cat[n]);
  514. }
  515. ocat = -1;
  516. Vect_cat_get(ICats, afield, &ocat);
  517. sprintf(buf,
  518. "insert into %s values ( %d, %d, %d )",
  519. Fi->table, ucat, ocat, cat);
  520. db_set_string(&sql, buf);
  521. G_debug(3, "%s", db_get_string(&sql));
  522. if (db_execute_immediate(driver, &sql) != DB_OK) {
  523. G_fatal_error(_("Cannot insert new record: %s"),
  524. db_get_string(&sql));
  525. }
  526. ucat++;
  527. }
  528. else
  529. Vect_cat_set(Cats, 1, cat);
  530. Vect_write_line(&Out, ltype, SPoints, Cats);
  531. }
  532. /* Second segment */
  533. ret = Vect_line_segment(Points, l1, l, SPoints);
  534. if (ret == 0) {
  535. G_warning(_
  536. ("Cannot get line segment, segment out of line"));
  537. }
  538. else {
  539. Vect_reset_cats(Cats);
  540. cat = Centers[center2].cat;
  541. if (unique_cats) {
  542. Vect_cat_set(Cats, 1, ucat);
  543. for (n = 0; n < OCats->n_cats; n++) {
  544. Vect_cat_set(Cats, 2, OCats->cat[n]);
  545. }
  546. ocat = -1;
  547. Vect_cat_get(ICats, afield, &ocat);
  548. sprintf(buf,
  549. "insert into %s values ( %d, %d, %d )",
  550. Fi->table, ucat, ocat, cat);
  551. db_set_string(&sql, buf);
  552. G_debug(3, "%s", db_get_string(&sql));
  553. if (db_execute_immediate(driver, &sql) != DB_OK) {
  554. G_fatal_error(_("Cannot insert new record: %s"),
  555. db_get_string(&sql));
  556. }
  557. ucat++;
  558. }
  559. else
  560. Vect_cat_set(Cats, 1, cat);
  561. Vect_write_line(&Out, ltype, SPoints, Cats);
  562. }
  563. }
  564. }
  565. }
  566. else {
  567. /* arc is not reachable */
  568. G_debug(3, " -> arc is not reachable");
  569. if (unique_cats) {
  570. Vect_cat_set(Cats, 1, ucat);
  571. for (n = 0; n < OCats->n_cats; n++) {
  572. Vect_cat_set(Cats, 2, OCats->cat[n]);
  573. }
  574. ocat = -1;
  575. Vect_cat_get(ICats, afield, &ocat);
  576. sprintf(buf,
  577. "insert into %s values ( %d, %d, %d )",
  578. Fi->table, ucat, ocat, -1);
  579. db_set_string(&sql, buf);
  580. G_debug(3, "%s", db_get_string(&sql));
  581. if (db_execute_immediate(driver, &sql) != DB_OK) {
  582. G_fatal_error(_("Cannot insert new record: %s"),
  583. db_get_string(&sql));
  584. }
  585. ucat++;
  586. }
  587. Vect_write_line(&Out, ltype, Points, Cats);
  588. }
  589. }
  590. if (unique_cats) {
  591. db_commit_transaction(driver);
  592. db_close_database_shutdown_driver(driver);
  593. Vect_copy_table(&Map, &Out, afield, 2, NULL, GV_MTABLE);
  594. }
  595. Vect_build(&Out);
  596. /* Free, ... */
  597. G_free(Nodes);
  598. G_free(Centers);
  599. Vect_close(&Map);
  600. Vect_close(&Out);
  601. exit(EXIT_SUCCESS);
  602. }