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;
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();