main.c 16 KB

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