X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftrainroutemetric.cpp;h=1fc4fcea2389d917ecaa90627791801dc0ee46e2;hb=2225814e69913aecaee53b0505d1b92197621b10;hp=a2cffbc896504d7df252905a449c63fbbe11c91b;hpb=d578d036656c0e89fe9dca5aefd1f81d2777a69e;p=r2c2.git diff --git a/source/libr2c2/trainroutemetric.cpp b/source/libr2c2/trainroutemetric.cpp index a2cffbc..1fc4fce 100644 --- a/source/libr2c2/trainroutemetric.cpp +++ b/source/libr2c2/trainroutemetric.cpp @@ -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; jget_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; jget_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 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(); @@ -57,6 +68,22 @@ void TrainRouteMetric::chain_to(const TrainRouteMetric &metric) i->base_distance = metric.get_distance_from(*i->track.track(), i->track.entry()); } +float TrainRouteMetric::get_distance_from(const Track &track) const +{ + map::const_iterator i = tracks.lower_bound(Key(&track, 0)); + map::const_iterator j = tracks.upper_bound(Key(&track, 255)); + + float result = -1; + for(; i!=j; ++i) + { + float d = i->second.distance+i->second.goal->base_distance; + if(result<0 || d::const_iterator i = tracks.find(Key(&track, exit));