Train timegraph with big step

60 Views Asked by At

I am making a graph in Python tk graphically show the movement of some trains.

Let's say we have train A, B and C. And their hourlyschedules are as follows:

Station 1 Station 2 Station 3
A :35:00 :38:18 :45:06
B :55:06 :59:12 :06:18
C :12:00 :18:12 :23:18

At each station the train has a 42 second stop for passengers to get in and out of the train.

I tried to make a graphic representation but going from :59:12 to :06:18 gives a huge line through the graph. I know why but I dont know how to solve it.

It should look something like this (this is an example with more trains): enter image description here

Can anyone help me get the code to make this graph in Python?

1

There are 1 best solutions below

2
On
  1. Assign a Y value to each station. For example

    Station 1 = 100

    Station 2 = 200

    Station 3 = 300

  2. Define a function to convert your "times" to seconds from an epoch.

    secs = fhm2secs(
       min1, sec1,      // 'time' at station 1
       min, sec )       // time at station to be converted
       s1 = 60 * min1 + sec1
       s  = 60 * min + sec
       if( s < s1 )     // check for hour wrap
           s = s + 60 * 60
       return s
    
  3. Define a function for each train that converts seconds to Y values. For example, in pseudo code, for train A.

    // For simplicity, I have used :35:00 means 3500 seconds
    y = fA( secs )
       IF secs < 3500
         return 100
       IF secs < 3818
         return  100 + ((secs - 3500) / 318 ) * 100
       IF secs < 3860
         return 200
       IF secs < 4506
         return 200 + ((secs - 3860) / 646 ) * 100
       return 300
  1. Plot the three functions' y values against seconds. (Use any plotting library)

Here is a C++ class that implements these ideas

    class cTrains
    {
        std::vector<std::vector<std::string>> vHourlySchedule;
        std::vector<std::vector<int>> vSecsSchedule;
        int maxsecs;
    
    public:
        cTrains()
        {
            generateHourlySchedule();
            convertScheduleToSecs();
        }
        void generateHourlySchedule()
        {
            vHourlySchedule = {
                {":35:00", ":38:18", ":45:06"},
                {":55:06", ":59:12", ":06:18"},
                {":12:00", ":18:12", ":23:18"}};
        }
    
        void convertScheduleToSecs()
        {
            maxsecs = 0;
            for (auto &train : vHourlySchedule)
            {
                std::vector<int> trainSchedule;
                for (std::string &minsec : train)
                {
                    if (!trainSchedule.size())
                        trainSchedule.push_back(fms2secs(0, minsec));
                    else
                    {
                        int secs = fms2secs(trainSchedule[0], minsec);
                        trainSchedule.push_back(secs);
                        if (secs > maxsecs)
                            maxsecs = secs;
                    }
                }
                vSecsSchedule.push_back(trainSchedule);
            }
        }
        int trainY(int train, int sec) const
        {
            if (0 > train || train >= trainCount())
                throw std::runtime_error("trainY bad train index");
    
            const int stationYinc = 100;
            const int stopsecs = 42;
    
            for (int station = 0; station < vSecsSchedule[train].size() - 1; station++)
            {
                int prev = 0;
                if (station > 0)
                    prev = vSecsSchedule[train][station - 1];
                int arr = vSecsSchedule[train][station];
                int nxt = vSecsSchedule[train][station + 1];
                int stationY = (station + 1) * stationYinc;
    
                // check if train has not left the station yet
                if (sec < arr + stopsecs)
                    return stationY + train;
    
                // check if train on way to next station
                if (sec < nxt)
                {
                    // interpolate  between stations
                    double f = ((float)(sec - arr - stopsecs)) / ((float)(nxt - arr - stopsecs));
                    return stationY + f * stationYinc + train;
                }
            }
    
            // train has arrived at last station
            return vSecsSchedule[train].size() * stationYinc + train;
        }
        int trainCount() const
        {
            return vHourlySchedule.size();
        }
    
        std::vector<double> plot(int train)
        {
            const int secinc = 10;
            if (0 > train || train >= trainCount())
                throw std::runtime_error("plot bad train index");
            std::vector<double> ret;
            for (int s = 0; s < maxsecs; s += secinc)
                ret.push_back(trainY(train, s));
            return ret;
        }
    
    private:
        int fms2secs(
            int secs1,                 // secs since epoch at station 1, 0 if not yet available
            const std::string &minsec) // time at station to be converted
        {
            int s = 60 * atoi(minsec.substr(1, 2).c_str()) + atoi(minsec.substr(4, 2).c_str());
            if (s < secs1) // check for hour wrap
                s = s + 60 * 60;
            return s;
        }
    };

Here is the output

enter image description here

The complete application code is at https://gist.github.com/JamesBremner/873e02020b369cb55e8b7915ca3d17cd