main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /****************************************************************
  2. *
  3. * MODULE: v.net.timetable
  4. *
  5. * AUTHOR(S): Daniel Bundala
  6. *
  7. * PURPOSE: Routing with timetables
  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/neta.h>
  23. struct Map_info In, Out;
  24. neta_timetable_result result;
  25. neta_timetable timetable;
  26. struct segment
  27. {
  28. int from_stop, to_stop;
  29. int from_time, to_time;
  30. int route;
  31. struct segment *next;
  32. } head;
  33. double *stop_x, *stop_y, *stop_z;
  34. int *stop_ids, *route_ids;
  35. int *found, *stop_node, *edges, nnodes;
  36. struct ilist **lines;
  37. dglGraph_s *graph;
  38. void init_route(int connection, int stop)
  39. {
  40. if (result.prev_stop[connection][stop] == -1)
  41. return;
  42. struct segment *seg =
  43. (struct segment *)G_calloc(1, sizeof(struct segment));
  44. int prev_conn = result.prev_conn[connection][stop];
  45. seg->next = head.next;
  46. head.next = seg;
  47. seg->route = result.prev_route[connection][stop];
  48. seg->from_stop = result.prev_stop[connection][stop];
  49. seg->to_stop = stop;
  50. if (seg->route == -2)
  51. seg->from_time = result.dst[prev_conn][seg->from_stop];
  52. else
  53. seg->from_time =
  54. NetA_timetable_get_route_time(&timetable, seg->from_stop,
  55. seg->route);
  56. seg->to_time = result.dst[connection][stop];
  57. init_route(prev_conn, seg->from_stop);
  58. }
  59. void release_route(struct segment *seg)
  60. {
  61. if (!seg)
  62. return;
  63. release_route(seg->next);
  64. G_free(seg->next);
  65. }
  66. static int int_cmp(const void *a, const void *b)
  67. {
  68. return *(int *)a - *(int *)b;
  69. }
  70. void init_database(struct Map_info *Out, dbDriver ** driver,
  71. struct field_info **Fi, int layer, char *columns)
  72. {
  73. dbString sql;
  74. char buf[2000];
  75. /* Create table */
  76. *Fi = Vect_default_field_info(Out, layer, NULL, GV_MTABLE);
  77. Vect_map_add_dblink(Out, layer, NULL, (*Fi)->table, "cat",
  78. (*Fi)->database, (*Fi)->driver);
  79. db_init_string(&sql);
  80. *driver = db_start_driver_open_database((*Fi)->driver, (*Fi)->database);
  81. if (*driver == NULL)
  82. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  83. (*Fi)->database, (*Fi)->driver);
  84. sprintf(buf, "create table %s (%s)", (*Fi)->table, columns);
  85. db_set_string(&sql, buf);
  86. G_debug(2, db_get_string(&sql));
  87. if (db_execute_immediate(*driver, &sql) != DB_OK) {
  88. db_close_database_shutdown_driver(*driver);
  89. G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
  90. }
  91. if (db_create_index2(*driver, (*Fi)->table, "cat") != DB_OK)
  92. G_warning(_("Cannot create index"));
  93. if (db_grant_on_table
  94. (*driver, (*Fi)->table, DB_PRIV_SELECT,
  95. DB_GROUP | DB_PUBLIC) != DB_OK)
  96. G_fatal_error(_("Cannot grant privileges on table <%s>"),
  97. (*Fi)->table);
  98. db_free_string(&sql);
  99. db_begin_transaction(*driver);
  100. }
  101. void insert_point(dbDriver * driver, char *table, int cat, int path,
  102. int stop_id, int index, int arrival_time,
  103. int departure_time)
  104. {
  105. char buf[2000];
  106. dbString sql;
  107. db_init_string(&sql);
  108. sprintf(buf, "insert into %s values (%d, %d, %d, %d, %d, %d)", table, cat,
  109. path, stop_id, index, arrival_time, departure_time);
  110. db_set_string(&sql, buf);
  111. G_debug(3, db_get_string(&sql));
  112. if (db_execute_immediate(driver, &sql) != DB_OK) {
  113. db_close_database_shutdown_driver(driver);
  114. G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql));
  115. };
  116. db_free_string(&sql);
  117. }
  118. void insert_line(dbDriver * driver, char *table, int cat, int path,
  119. int from_id, int to_id, int route_id, int index,
  120. int from_time, int to_time)
  121. {
  122. char buf[2000];
  123. dbString sql;
  124. db_init_string(&sql);
  125. sprintf(buf, "insert into %s values (%d, %d, %d, %d, %d, %d, %d, %d)",
  126. table, cat, path, from_id, to_id, route_id, index, from_time,
  127. to_time);
  128. db_set_string(&sql, buf);
  129. G_debug(3, db_get_string(&sql));
  130. if (db_execute_immediate(driver, &sql) != DB_OK) {
  131. db_close_database_shutdown_driver(driver);
  132. G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql));
  133. };
  134. db_free_string(&sql);
  135. }
  136. int get_nearest_stop(double x, double y, double z, int with_z)
  137. {
  138. int i, mini = -1;
  139. double mind, d;
  140. for (i = 0; i < timetable.stops; i++) {
  141. if (!found[i])
  142. continue;
  143. d = Vect_points_distance(x, y, z, stop_x[i], stop_y[i], stop_z[i],
  144. with_z);
  145. if (mini == -1 || d < mind) {
  146. mind = d;
  147. mini = i;
  148. }
  149. }
  150. return mini;
  151. }
  152. void write_subroute(struct segment *seg, struct line_pnts *line, int line_id)
  153. {
  154. int i, j, r;
  155. struct line_pnts *Points;
  156. struct line_cats *Cats;
  157. struct ilist *list;
  158. Points = Vect_new_line_struct();
  159. Cats = Vect_new_cats_struct();
  160. list = Vect_new_list();
  161. r = seg->route;
  162. Vect_cat_set(Cats, 2, line_id);
  163. if (r < 0) {
  164. Vect_write_line(&Out, GV_LINE, line, Cats);
  165. return;
  166. }
  167. for (i = 0; i < nnodes; i++)
  168. edges[i] = 0;
  169. for (i = 0; i < lines[r]->n_values; i++)
  170. edges[lines[r]->value[i]] = 1;
  171. for (i = 0; i < timetable.route_length[r]; i++)
  172. if (timetable.route_stops[r][i] == seg->from_stop)
  173. break;
  174. for (; timetable.route_stops[r][i] != seg->to_stop; i++)
  175. if (NetA_find_path
  176. (graph, stop_node[timetable.route_stops[r][i]],
  177. stop_node[timetable.route_stops[r][i + 1]], edges, list) != -1) {
  178. for (j = 0; j < list->n_values; j++) {
  179. int type = Vect_read_line(&In, Points, NULL, list->value[j]);
  180. Vect_write_line(&Out, type, Points, Cats);
  181. }
  182. }
  183. else {
  184. G_warning(_("Could not find a path between stops %d and %d"),
  185. stop_ids[timetable.route_stops[r][i]],
  186. stop_ids[timetable.route_stops[r][i + 1]]);
  187. }
  188. Vect_destroy_list(list);
  189. Vect_destroy_cats_struct(Cats);
  190. Vect_destroy_line_struct(Points);
  191. }
  192. int main(int argc, char *argv[])
  193. {
  194. static struct line_pnts *Points, *Cur, *Prev;
  195. struct line_cats *Counter_Cats, *Cats;
  196. struct GModule *module; /* GRASS module for parsing arguments */
  197. struct Option *map_in, *map_out;
  198. struct Option *field_opt, *walk_layer_opt, *path_layer_opt, *route_id_opt,
  199. *stop_time_opt, *to_stop_opt, *walk_length_opt;
  200. int with_z;
  201. int layer, mask_type, path_layer;
  202. int from_stop, to_stop, start_time, min_change, max_changes,
  203. walking_change, ret;
  204. int *stop_pnt, i, nlines, point_counter, *route_pnt;
  205. int line_counter, index, j;
  206. struct segment *cur;
  207. char buf[2000];
  208. /* Attribute table */
  209. dbDriver *point_driver, *line_driver;
  210. struct field_info *point_Fi, *line_Fi;
  211. /* initialize GIS environment */
  212. G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */
  213. /* initialize module */
  214. module = G_define_module();
  215. G_add_keyword(_("vector"));
  216. G_add_keyword(_("network"));
  217. G_add_keyword(_("shortest path"));
  218. module->description = _("Finds shortest path using timetables.");
  219. /* Define the different options as defined in gis.h */
  220. map_in = G_define_standard_option(G_OPT_V_INPUT);
  221. field_opt = G_define_standard_option(G_OPT_V_FIELD);
  222. map_out = G_define_standard_option(G_OPT_V_OUTPUT);
  223. walk_layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
  224. walk_layer_opt->key = "walk_layer";
  225. walk_layer_opt->answer = "-1";
  226. walk_layer_opt->label =
  227. _("Layer number or name with walking connections or -1");
  228. path_layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
  229. path_layer_opt->key = "path_layer";
  230. path_layer_opt->answer = "-1";
  231. path_layer_opt->label = _("Layer number or name with route paths or -1");
  232. route_id_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  233. route_id_opt->key = "route_id";
  234. route_id_opt->required = YES;
  235. route_id_opt->answer = "route_id";
  236. route_id_opt->description = _("Name of column name with route ids");
  237. stop_time_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  238. stop_time_opt->key = "stop_time";
  239. stop_time_opt->required = YES;
  240. stop_time_opt->answer = "stop_time";
  241. stop_time_opt->description =
  242. _("Name of column name with stop timestamps");
  243. to_stop_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  244. to_stop_opt->key = "to_stop";
  245. to_stop_opt->required = YES;
  246. to_stop_opt->answer = "to_stop";
  247. to_stop_opt->description = _("Name of column name with stop ids");
  248. walk_length_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  249. walk_length_opt->key = "walk_length";
  250. walk_length_opt->required = YES;
  251. walk_length_opt->answer = "length";
  252. walk_length_opt->description = _("Name of column name with walk lengths");
  253. /* options and flags parser */
  254. if (G_parser(argc, argv))
  255. exit(EXIT_FAILURE);
  256. /* TODO: make an option for this */
  257. mask_type = GV_LINE | GV_BOUNDARY;
  258. Points = Vect_new_line_struct();
  259. Cats = Vect_new_cats_struct();
  260. Counter_Cats = Vect_new_cats_struct();
  261. Cur = Vect_new_line_struct();
  262. Prev = Vect_new_line_struct();
  263. Vect_check_input_output_name(map_in->answer, map_out->answer,
  264. GV_FATAL_EXIT);
  265. Vect_set_open_level(2);
  266. if (1 > Vect_open_old(&In, map_in->answer, ""))
  267. G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer);
  268. with_z = Vect_is_3d(&In);
  269. if (0 > Vect_open_new(&Out, map_out->answer, with_z)) {
  270. Vect_close(&In);
  271. G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer);
  272. }
  273. /* parse filter option and select appropriate lines */
  274. layer = atoi(field_opt->answer);
  275. path_layer = atoi(path_layer_opt->answer);
  276. init_database(&Out, &point_driver, &point_Fi, 1,
  277. "cat integer, path_id integer, stop_id integer, index integer, arr_time integer, dep_time integer");
  278. init_database(&Out, &line_driver, &line_Fi, 2,
  279. "cat integer, path_id integer, from_id integer, to_id integer, route_id integer, index integer, from_time integer, to_time integer");
  280. Vect_copy_head_data(&In, &Out);
  281. Vect_hist_copy(&In, &Out);
  282. Vect_hist_command(&Out);
  283. if (NetA_init_timetable_from_db
  284. (&In, layer, atoi(walk_layer_opt->answer), route_id_opt->answer,
  285. stop_time_opt->answer, to_stop_opt->answer, walk_length_opt->answer,
  286. &timetable, &route_ids, &stop_ids) != 0)
  287. G_fatal_error(_("Could not initialize the timetables"));
  288. stop_x = (double *)G_calloc(timetable.stops, sizeof(double));
  289. stop_y = (double *)G_calloc(timetable.stops, sizeof(double));
  290. stop_z = (double *)G_calloc(timetable.stops, sizeof(double));
  291. found = (int *)G_calloc(timetable.stops, sizeof(int));
  292. if (!stop_x || !stop_y || !stop_z || !found)
  293. G_fatal_error(_("Out of memory"));
  294. if (path_layer > 0) {
  295. nnodes = Vect_get_num_nodes(&In);
  296. stop_node = (int *)G_calloc(timetable.stops, sizeof(int));
  297. lines =
  298. (struct ilist **)G_calloc(timetable.routes,
  299. sizeof(struct ilist *));
  300. edges = (int *)G_calloc(nnodes + 1, sizeof(int));
  301. if (!edges || !stop_node || !lines)
  302. G_fatal_error(_("Out of memory"));
  303. for (i = 0; i < timetable.routes; i++)
  304. lines[i] = Vect_new_list();
  305. Vect_net_build_graph(&In, mask_type, path_layer, 0, NULL, NULL, NULL,
  306. 0, 0);
  307. graph = &(In.graph);
  308. }
  309. nlines = Vect_get_num_lines(&In);
  310. for (i = 1; i <= nlines; i++) {
  311. int type = Vect_read_line(&In, Points, Cats, i);
  312. if (type == GV_POINT) {
  313. int cat, stop, node;
  314. for (j = 0; j < Cats->n_cats; j++) {
  315. if (Cats->field[j] != layer)
  316. continue;
  317. cat = Cats->cat[j];
  318. stop_pnt =
  319. (int *)bsearch(&cat, stop_ids, timetable.stops,
  320. sizeof(int), int_cmp);
  321. if (!stop_pnt)
  322. continue;
  323. stop = stop_pnt - stop_ids;
  324. stop_x[stop] = Points->x[0];
  325. stop_y[stop] = Points->y[0];
  326. stop_z[stop] = Points->z[0];
  327. if (path_layer > 0) {
  328. Vect_get_line_nodes(&In, i, &node, NULL);
  329. if (!stop_node[stop])
  330. stop_node[stop] = node;
  331. }
  332. found[stop] = 1;
  333. }
  334. }
  335. else if (type == GV_LINE && path_layer > 0) {
  336. int cat;
  337. for (j = 0; j < Cats->n_cats; j++) {
  338. if (Cats->field[j] != path_layer)
  339. continue;
  340. cat = Cats->cat[j];
  341. route_pnt =
  342. (int *)bsearch(&cat, route_ids, timetable.routes,
  343. sizeof(int), int_cmp);
  344. if (!route_pnt)
  345. continue;
  346. Vect_list_append(lines[route_pnt - route_ids], i);
  347. }
  348. }
  349. }
  350. for (i = 0; i < timetable.stops; i++)
  351. if (!found[i])
  352. G_warning(_("No stop with category: %d"), stop_ids[i]);
  353. point_counter = line_counter = 1;
  354. while (1) {
  355. double fx, fy, tx, ty;
  356. int path_id;
  357. if (fgets(buf, sizeof(buf), stdin) == NULL)
  358. break;
  359. ret =
  360. sscanf(buf, "%d %lf %lf %lf %lf %d %d %d %d", &path_id, &fx, &fy,
  361. &tx, &ty, &start_time, &min_change, &max_changes,
  362. &walking_change);
  363. if (ret == 9) {
  364. from_stop = get_nearest_stop(fx, fy, 0, with_z);
  365. to_stop = get_nearest_stop(tx, ty, 0, with_z);
  366. }
  367. else {
  368. ret =
  369. sscanf(buf, "%d %d %d %d %d %d %d", &path_id, &from_stop,
  370. &to_stop, &start_time, &min_change, &max_changes,
  371. &walking_change);
  372. if (ret < 7) {
  373. G_warning(_("Wrong input format: %s"), buf);
  374. continue;
  375. }
  376. stop_pnt =
  377. (int *)bsearch(&from_stop, stop_ids, timetable.stops,
  378. sizeof(int), int_cmp);
  379. if (!stop_pnt) {
  380. G_warning(_("No stop with category: %d"), from_stop);
  381. continue;
  382. }
  383. from_stop = stop_pnt - stop_ids;
  384. stop_pnt =
  385. (int *)bsearch(&to_stop, stop_ids, timetable.stops,
  386. sizeof(int), int_cmp);
  387. if (!stop_pnt) {
  388. G_warning(_("No stop with category: %d"), to_stop);
  389. continue;
  390. }
  391. to_stop = stop_pnt - stop_ids;
  392. }
  393. if (from_stop == to_stop) {
  394. G_warning(_("'From' and 'To' stops are the same"));
  395. continue;
  396. }
  397. ret =
  398. NetA_timetable_shortest_path(&timetable, from_stop, to_stop,
  399. start_time, min_change, max_changes,
  400. walking_change, &result);
  401. if (ret == -1) {
  402. G_warning(_("No path between the stops"));
  403. continue;
  404. }
  405. head.next = NULL;
  406. init_route(result.routes, to_stop);
  407. NetA_timetable_result_release(&result);
  408. Vect_reset_line(Points);
  409. Vect_reset_line(Cur);
  410. Vect_reset_line(Prev);
  411. Vect_append_point(Cur, stop_x[from_stop], stop_y[from_stop],
  412. stop_z[from_stop]);
  413. Vect_reset_cats(Cats);
  414. Vect_cat_set(Cats, 1, point_counter);
  415. Vect_write_line(&Out, GV_POINT, Cur, Cats);
  416. insert_point(point_driver, point_Fi->table, point_counter, path_id,
  417. stop_ids[from_stop], 1, start_time,
  418. head.next->from_time);
  419. point_counter++;
  420. Vect_append_points(Prev, Cur, GV_FORWARD);
  421. index = 1;
  422. for (cur = head.next; cur; cur = cur->next) {
  423. int dept_time, route_id;
  424. if (cur->route == -2) {
  425. printf("Walk ");
  426. route_id = -1;
  427. }
  428. else {
  429. printf("Route %d, ", route_ids[cur->route]);
  430. route_id = route_ids[cur->route];
  431. }
  432. printf("from %d leaving at %d arriving to %d at %d\n",
  433. stop_ids[cur->from_stop], cur->from_time,
  434. stop_ids[cur->to_stop], cur->to_time);
  435. Vect_reset_line(Cur);
  436. Vect_reset_line(Points);
  437. Vect_reset_cats(Cats);
  438. Vect_append_point(Cur, stop_x[cur->to_stop], stop_y[cur->to_stop],
  439. stop_z[cur->to_stop]);
  440. Vect_cat_set(Cats, 1, point_counter);
  441. Vect_write_line(&Out, GV_POINT, Cur, Cats);
  442. if (cur->next)
  443. dept_time = cur->next->from_time;
  444. else
  445. dept_time = cur->to_time;
  446. insert_point(point_driver, point_Fi->table, point_counter,
  447. path_id, stop_ids[cur->to_stop], index + 1,
  448. cur->to_time, dept_time);
  449. Vect_append_points(Points, Prev, GV_FORWARD);
  450. Vect_append_points(Points, Cur, GV_FORWARD);
  451. Vect_reset_cats(Cats);
  452. Vect_cat_set(Cats, 2, line_counter);
  453. if (path_layer <= 0)
  454. Vect_write_line(&Out, GV_LINE, Points, Cats);
  455. else
  456. write_subroute(cur, Points, line_counter);
  457. insert_line(line_driver, line_Fi->table, line_counter, path_id,
  458. stop_ids[cur->from_stop], stop_ids[cur->to_stop],
  459. route_id, index, cur->from_time, cur->to_time);
  460. Vect_reset_line(Prev);
  461. Vect_append_points(Prev, Cur, GV_FORWARD);
  462. point_counter++;
  463. line_counter++;
  464. index++;
  465. }
  466. release_route(&head);
  467. }
  468. db_commit_transaction(line_driver);
  469. db_commit_transaction(point_driver);
  470. db_close_database_shutdown_driver(line_driver);
  471. db_close_database_shutdown_driver(point_driver);
  472. Vect_build(&Out);
  473. Vect_close(&In);
  474. Vect_close(&Out);
  475. G_free(stop_x);
  476. G_free(stop_y);
  477. G_free(stop_z);
  478. G_free(stop_node);
  479. exit(EXIT_SUCCESS);
  480. }