]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/section.cpp
Initial revision
[r2c2.git] / source / libmarklin / section.cpp
1 #include "control.h"
2 #include "section.h"
3 #include "trafficmanager.h"
4 #include "turnout.h"
5
6 using namespace Msp;
7
8 #include <iostream>
9 using namespace std;
10
11 namespace Marklin {
12
13 Section::Section(TrafficManager &tm, Track *start):
14         trfc_mgr(tm),
15         id(next_id++),
16         sensor_id(0),
17         train(0)
18 {
19         tracks.insert(start);
20
21         if(start->get_sensor_id())
22         {
23                 sensor_id=start->get_sensor_id();
24                 const Track::EndpointSeq &eps=start->get_endpoints();
25                 for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i)
26                         endpoints.push_back(Endpoint(start, &*i));
27         }
28         else
29         {
30                 TrackSeq queue;
31                 queue.push_back(start);
32
33                 while(!queue.empty())
34                 {
35                         Track *track=queue.front();
36                         queue.erase(queue.begin());
37
38                         const Track::EndpointSeq &eps=track->get_endpoints();
39                         for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i)
40                                 if(i->link && tracks.count(i->link)==0)
41                                 {
42                                         if(!i->link->get_sensor_id())
43                                         {
44                                                 queue.push_back(i->link);
45                                                 tracks.insert(i->link);
46                                         }
47                                         else
48                                                 endpoints.push_back(Endpoint(track, &*i));
49                                 }
50                 }
51         }
52
53         unsigned n=0;
54         for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i, ++n)
55         {
56                 unsigned route=1<<n;
57                 i->routes|=route;
58                 set<Track *> visited;
59                 find_routes(i->track, i->track_ep, route, visited);
60         }
61 }
62
63 const Section::Endpoint *Section::get_endpoint_by_link(const Section *other) const
64 {
65         for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
66                 if(i->link==other)
67                         return &*i;
68
69         return 0;
70 }
71
72 const Section::Endpoint *Section::traverse(const Endpoint *ep) const
73 {
74         Track *track=ep->track;
75         const Track::Endpoint *track_ep=ep->track_ep;
76
77         while(1)
78         {
79                 unsigned cur_route=0;
80                 unsigned tid=track->get_turnout_id();
81                 if(tid)
82                 {
83                         Turnout *turnout=trfc_mgr.get_control().get_turnout(tid);
84                         if(turnout)
85                                 cur_route=turnout->get_route();
86                 }
87
88                 const Track::Endpoint *other_ep=track->traverse(track_ep, cur_route);
89                 if(!other_ep)
90                         return 0;
91
92                 for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
93                         if(i->track==track && i->track_ep==other_ep)
94                                 return &*i;
95
96                 track_ep=track->get_endpoint_by_link(other_ep->link);
97                 track=other_ep->link;
98
99                 if(tracks.count(track)==0)
100                         return 0;
101         }
102 }
103
104 void Section::check_link(Section &other)
105 {
106         for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
107         {
108                 if(i->link)
109                         continue;
110
111                 for(EndpointSeq::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
112                         if(j->track==i->track_ep->link && j->track_ep->link==i->track && !j->link)
113                         {
114                                 i->link=&other;
115                                 j->link=this;
116                         }
117         }
118 }
119
120 bool Section::reserve(const Train *t)
121 {
122         if(!t || !train)
123         {
124                 train=t;
125                 return true;
126         }
127         else
128                 return false;
129 }
130
131 void Section::print_debug()
132 {
133         cout<<"Section "<<id;
134         if((*tracks.begin())->get_sensor_id())
135                 cout<<", sensor="<<(*tracks.begin())->get_sensor_id();
136         cout<<'\n';
137         for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
138         {
139                 cout<<"  Endpoint, link=";
140                 if(i->link)
141                         cout<<i->link->id;
142                 else
143                         cout<<"none";
144                 cout<<", routes="<<i->routes<<'\n';
145         }
146 }
147
148 void Section::find_routes(Track *track, const Track::Endpoint *track_ep, unsigned route, std::set<Marklin::Track *> &visited)
149 {
150         visited.insert(track);
151
152         const Track::EndpointSeq &eps=track->get_endpoints();
153         for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i)
154         {
155                 if(&*i==track_ep) continue;
156                 if(!i->link) continue;
157                 if(!(i->routes&track_ep->routes)) continue;
158                 if(visited.count(i->link)) continue;
159
160                 if(tracks.count(i->link))
161                         find_routes(i->link, i->link->get_endpoint_by_link(track), route, visited);
162                 else
163                 {
164                         for(EndpointSeq::iterator j=endpoints.begin(); j!=endpoints.end(); ++j)
165                                 if(j->track==track && j->track_ep==&*i)
166                                         j->routes|=route;
167                 }
168         }
169
170         visited.erase(--visited.end());
171 }
172
173 unsigned Section::next_id=1;
174
175
176 Section::Endpoint::Endpoint(Track *t, const Track::Endpoint *e):
177         track(t),
178         track_ep(e),
179         link(0),
180         routes(0)
181 { }
182
183 } // namespace Marklin