]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/block.cpp
3ca744ca0c287796396263c825130977be3e4e7f
[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(start.get_sensor_id()),
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()==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, float *len) 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         if(len)
72                 *len=0;
73
74         while(1)
75         {
76                 unsigned cur_route=0;
77                 unsigned tid=track->get_turnout_id();
78                 if(tid)
79                 {
80                         Turnout &turnout=trfc_mgr.get_control().get_turnout(tid);
81                         cur_route=turnout.get_route();
82                 }
83
84                 if(len)
85                         *len+=track->get_type().get_route_length(cur_route);
86
87                 int other_ep=track->traverse(track_ep, cur_route);
88                 if(other_ep<0)
89                         return -1;
90
91                 for(unsigned i=0; i<endpoints.size(); ++i)
92                         if(endpoints[i].track==track && endpoints[i].track_ep==static_cast<unsigned>(other_ep))
93                                 return i;
94
95                 Track *next=track->get_link(other_ep);
96                 track_ep=next->get_endpoint_by_link(*track);
97                 track=next;
98
99                 if(tracks.count(track)==0)
100                         return -1;
101         }
102 }
103
104 void Block::check_link(Block &other)
105 {
106         for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
107         {
108                 if(i->link)
109                         continue;
110
111                 for(vector<Endpoint>::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
112                         if(j->track==i->track->get_link(i->track_ep) && j->track->get_link(j->track_ep)==i->track && !j->link)
113                         {
114                                 i->link=&other;
115                                 j->link=this;
116                         }
117         }
118 }
119
120 Block *Block::get_link(unsigned epi) const
121 {
122         if(epi>=endpoints.size())
123                 throw InvalidParameterValue("Endpoint index out of range");
124         return endpoints[epi].link;
125 }
126
127 bool Block::reserve(const Train *t)
128 {
129         if(!t || !train)
130         {
131                 train=t;
132                 if(train)
133                         cout<<"Block "<<this<<" reserved for train "<<train->get_name()<<'\n';
134                 else
135                         cout<<"Block "<<this<<" freed\n";
136                 trfc_mgr.signal_block_reserved.emit(*this, train);
137                 return true;
138         }
139         else
140                 return false;
141 }
142
143 void Block::print_debug()
144 {
145         cout<<"Block "<<id;
146         if((*tracks.begin())->get_sensor_id())
147                 cout<<", sensor="<<(*tracks.begin())->get_sensor_id();
148         cout<<'\n';
149         for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
150         {
151                 cout<<"  Endpoint, link=";
152                 if(i->link)
153                         cout<<i->link->id;
154                 else
155                         cout<<"none";
156                 cout<<", routes="<<i->routes<<'\n';
157         }
158 }
159
160 void Block::find_routes(Track &track, unsigned track_ep, unsigned route, set<Track *> &visited)
161 {
162         visited.insert(&track);
163
164         const vector<Marklin::Endpoint> &eps=track.get_type().get_endpoints();
165         for(unsigned i=0; i<eps.size(); ++i)
166         {
167                 if(i==track_ep) continue;
168                 Track *link=track.get_link(i);
169                 if(!link) continue;
170                 if(visited.count(link)) continue;
171                 if(!(eps[i].routes&eps[track_ep].routes)) continue;
172
173                 if(tracks.count(link))
174                         find_routes(*link, link->get_endpoint_by_link(track), route, visited);
175                 else
176                 {
177                         for(vector<Endpoint>::iterator j=endpoints.begin(); j!=endpoints.end(); ++j)
178                                 if(j->track==&track && j->track_ep==i)
179                                         j->routes|=route;
180                 }
181         }
182 }
183
184 unsigned Block::next_id=1;
185
186
187 Block::Endpoint::Endpoint(Track *t, unsigned e):
188         track(t),
189         track_ep(e),
190         link(0),
191         routes(0)
192 { }
193
194 } // namespace Marklin