Routing and analysis engine for GTFS (General Transit Feed Specification) data
1#include "csa.h"
2
3//' rcpp_make_timetable
4//'
5//' Make timetable from GTFS stop_times. Both stop_ids and trip_ids are vectors
6//' of unique values which are converted to unordered_maps on to 1-indexed
7//' integer values.
8//'
9//' @noRd
10// [[Rcpp::export]]
11Rcpp::DataFrame rcpp_make_timetable (Rcpp::DataFrame stop_times,
12 std::vector <std::string> stop_ids, std::vector <std::string> trip_ids)
13{
14 Timetable_Inputs tt_in;
15 timetable::timetable_in_from_df (stop_times, tt_in);
16
17 size_t n = timetable::count_connections (tt_in);
18
19 Timetable_Outputs tt_out;
20 timetable::initialise_tt_outputs (tt_out, n);
21 timetable::make_timetable (tt_in, tt_out, stop_ids, trip_ids);
22
23 Rcpp::DataFrame timetable = Rcpp::DataFrame::create (
24 Rcpp::Named ("departure_station") = tt_out.departure_station,
25 Rcpp::Named ("arrival_station") = tt_out.arrival_station,
26 Rcpp::Named ("departure_time") = tt_out.departure_time,
27 Rcpp::Named ("arrival_time") = tt_out.arrival_time,
28 Rcpp::Named ("trip_id") = tt_out.trip_id,
29 Rcpp::_["stringsAsFactors"] = false);
30
31 return timetable;
32}
33
34void timetable::timetable_in_from_df (Rcpp::DataFrame &stop_times,
35 Timetable_Inputs &tt_in)
36{
37 tt_in.stop_id = Rcpp::as <std::vector <std::string> > (stop_times ["stop_id"]);
38 tt_in.trip_id = Rcpp::as <std::vector <std::string> > (stop_times ["trip_id"]);
39 tt_in.arrival_time = Rcpp::as <std::vector <int> > (
40 stop_times ["arrival_time"]);
41 tt_in.departure_time = Rcpp::as <std::vector <int> > (
42 stop_times ["departure_time"]);
43}
44
45size_t timetable::count_connections (const Timetable_Inputs &tt_in)
46{
47 size_t n_connections = 0;
48 std::string trip_id_i = tt_in.trip_id [0];
49 for (size_t i = 1; i < tt_in.trip_id.size (); i++)
50 {
51 if (tt_in.trip_id [i] == trip_id_i)
52 n_connections++;
53 else
54 {
55 trip_id_i = tt_in.trip_id [i];
56 }
57 }
58 return n_connections;
59}
60
61void timetable::initialise_tt_outputs (Timetable_Outputs &tt_out, size_t n)
62{
63 tt_out.departure_time.resize (n);
64 tt_out.arrival_time.resize (n);
65 tt_out.departure_station.resize (n);
66 tt_out.arrival_station.resize (n);
67 tt_out.trip_id.resize (n);
68}
69
70void timetable::make_trip_stop_map (const std::vector <std::string> &input,
71 std::unordered_map <std::string, int> &output_map)
72{
73 int count = 1; // 1-indexed
74 for (auto i: input)
75 output_map.emplace (i, count++);
76}
77
78void timetable::make_timetable (const Timetable_Inputs &tt_in,
79 Timetable_Outputs &tt_out,
80 const std::vector <std::string> &stop_ids,
81 const std::vector <std::string> &trip_ids)
82{
83 std::unordered_map <std::string, int> trip_id_map;
84 make_trip_stop_map (trip_ids, trip_id_map);
85
86 std::unordered_map <std::string, int> stop_id_map;
87 make_trip_stop_map (stop_ids, stop_id_map);
88
89 size_t n_connections = 0;
90 std::string trip_id_i = tt_in.trip_id [0];
91 int dest_stop = stop_id_map.at (tt_in.stop_id [0]);
92 for (size_t i = 1; i < tt_in.trip_id.size (); i++)
93 {
94 if (tt_in.trip_id [i] == trip_id_i)
95 {
96 int arrival_stop = stop_id_map.at (tt_in.stop_id [i]);
97 tt_out.departure_station [n_connections] = dest_stop;
98 tt_out.arrival_station [n_connections] = arrival_stop;
99 tt_out.departure_time [n_connections] = tt_in.departure_time [i - 1];
100 tt_out.arrival_time [n_connections] = tt_in.arrival_time [i];
101 tt_out.trip_id [n_connections] = trip_id_map.at (trip_id_i);
102 dest_stop = arrival_stop;
103 n_connections++;
104 } else
105 {
106 dest_stop = stop_id_map.at (tt_in.stop_id [i]);
107 trip_id_i = tt_in.trip_id [i];
108 }
109 }
110}