]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/trainroutemetric.cpp
Don't access waypoint and metric data if the router has no destination
[r2c2.git] / source / libr2c2 / trainroutemetric.cpp
1 #include <list>
2 #include "track.h"
3 #include "trackchain.h"
4 #include "trainroutemetric.h"
5
6 using namespace std;
7
8 namespace R2C2 {
9
10 TrainRouteMetric::TrainRouteMetric(const TrackChain &tc)
11 {
12         const TrackChain::TrackSet &ctracks = tc.get_tracks();
13         for(TrackChain::TrackSet::const_iterator i=ctracks.begin(); i!=ctracks.end(); ++i)
14         {
15                 unsigned nls = (*i)->get_n_link_slots();
16                 for(unsigned j=0; j<nls; ++j)
17                         if(Track *link = (*i)->get_link(j))
18                                 if(!ctracks.count(link))
19                                         goals.push_back(TrackIter(*i, j));
20         }
21
22         list<TrackIter> queue;
23         for(vector<Goal>::iterator i=goals.begin(); i!=goals.end(); ++i)
24         {
25                 tracks[Key(i->track.track(), i->track.entry())] = Data(0, &*i);
26                 queue.push_back(i->track);
27         }
28
29         while(!queue.empty())
30         {
31                 TrackIter track = queue.front();
32                 queue.pop_front();
33                 const Data &data = tracks[Key(track.track(), track.entry())];
34
35                 const TrackType::Endpoint &ep = track.endpoint();
36                 for(unsigned i=0; ep.paths>>i; ++i)
37                         if(ep.has_path(i))
38                         {
39                                 TrackIter next = track.next(i);
40                                 if(!next)
41                                         continue;
42
43                                 Data &target = tracks[Key(next.track(), next.entry())];
44                                 float dist = data.distance+track->get_type().get_path_length(i);
45                                 if(target.distance<0 || target.distance>dist)
46                                 {
47                                         target = Data(dist, data.goal);
48                                         queue.push_back(next);
49                                 }
50                         }
51         }
52 }
53
54 void TrainRouteMetric::chain_to(const TrainRouteMetric &metric)
55 {
56         for(vector<Goal>::iterator i=goals.begin(); i!=goals.end(); ++i)
57                 i->base_distance = metric.get_distance_from(*i->track.track(), i->track.entry());
58 }
59
60 float TrainRouteMetric::get_distance_from(const Track &track, unsigned exit) const
61 {
62         map<Key, Data>::const_iterator i = tracks.find(Key(&track, exit));
63         if(i==tracks.end())
64                 return -1;
65
66         return i->second.distance+i->second.goal->base_distance;
67 }
68
69
70 TrainRouteMetric::Goal::Goal():
71         base_distance(0)
72 { }
73
74 TrainRouteMetric::Goal::Goal(const TrackIter &t):
75         track(t),
76         base_distance(0)
77 { }
78
79
80 TrainRouteMetric::Data::Data():
81         distance(-1),
82         goal(0)
83 { }
84
85 TrainRouteMetric::Data::Data(float d, const Goal *g):
86         distance(d),
87         goal(g)
88 { }
89
90 } // namespace R2C2