]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/trainroutemetric.cpp
Don't go past end of allocation when checking blocks for a signal
[r2c2.git] / source / libr2c2 / trainroutemetric.cpp
index a2cffbc896504d7df252905a449c63fbbe11c91b..469fc9494715dfea68be9517b7a71f1b783d8b89 100644 (file)
@@ -7,16 +7,24 @@ using namespace std;
 
 namespace R2C2 {
 
-TrainRouteMetric::TrainRouteMetric(const TrackChain &tc)
+TrainRouteMetric::TrainRouteMetric(const TrackChain &tc, TrackChain::Direction dir)
 {
+       /* Initialize goals for tracks in the target chain.  We travel outwards from
+       the target in the search phase so the iters appear to point the wrong way. */
+       TrackChain::Direction reverse_dir = (dir==TrackChain::DOWN ? TrackChain::UP : TrackChain::DOWN);
        const TrackChain::TrackSet &ctracks = tc.get_tracks();
        for(TrackChain::TrackSet::const_iterator i=ctracks.begin(); i!=ctracks.end(); ++i)
        {
-               unsigned nls = (*i)->get_n_link_slots();
-               for(unsigned j=0; j<nls; ++j)
-                       if(Track *link = (*i)->get_link(j))
-                               if(!ctracks.count(link))
-                                       goals.push_back(TrackIter(*i, j));
+               if(dir==TrackChain::UNSPECIFIED)
+               {
+                       unsigned nls = (*i)->get_n_link_slots();
+                       for(unsigned j=0; j<nls; ++j)
+                               if(Track *link = (*i)->get_link(j))
+                                       if(!ctracks.count(link))
+                                               goals.push_back(TrackIter(*i, j));
+               }
+               else if(TrackIter iter = tc.iter_for(**i, reverse_dir))
+                       goals.push_back(iter);
        }
 
        list<TrackIter> queue;
@@ -26,6 +34,9 @@ TrainRouteMetric::TrainRouteMetric(const TrackChain &tc)
                queue.push_back(i->track);
        }
 
+       /* Use Dijkstra's algorithm to find the shortest distance from the goal to
+       every reachable track in the layout.  Entry points here become exit points
+       when looking up distances to the goal. */
        while(!queue.empty())
        {
                TrackIter track = queue.front();