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