]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/block.cpp
b3a96e67f4f59850c58a599c92eced8dc70d96c4
[r2c2.git] / source / libmarklin / block.cpp
1 #include "control.h"
2 #include "block.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 Block::Block(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 Block::Endpoint *Block::get_endpoint_by_link(const Block *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 Block::Endpoint *Block::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=other_ep->link->get_endpoint_by_link(track);
97                 track=other_ep->link;
98
99                 if(tracks.count(track)==0)
100                         return 0;
101         }
102 }
103
104 void Block::check_link(Block &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 Block::reserve(const Train *t)
121 {
122         if(!t || !train)
123         {
124                 train=t;
125                 cout<<"Block "<<this<<" reserved for train "<<train<<'\n';
126                 trfc_mgr.signal_block_reserved.emit(*this, train);
127                 return true;
128         }
129         else
130                 return false;
131 }
132
133 void Block::print_debug()
134 {
135         cout<<"Block "<<id;
136         if((*tracks.begin())->get_sensor_id())
137                 cout<<", sensor="<<(*tracks.begin())->get_sensor_id();
138         cout<<'\n';
139         for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
140         {
141                 cout<<"  Endpoint, link=";
142                 if(i->link)
143                         cout<<i->link->id;
144                 else
145                         cout<<"none";
146                 cout<<", routes="<<i->routes<<'\n';
147         }
148 }
149
150 void Block::find_routes(Track *track, const Track::Endpoint *track_ep, unsigned route, std::set<Marklin::Track *> &visited)
151 {
152         visited.insert(track);
153
154         const Track::EndpointSeq &eps=track->get_endpoints();
155         for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i)
156         {
157                 if(&*i==track_ep) continue;
158                 if(!i->link) continue;
159                 if(!(i->routes&track_ep->routes)) continue;
160                 if(visited.count(i->link)) continue;
161
162                 if(tracks.count(i->link))
163                         find_routes(i->link, i->link->get_endpoint_by_link(track), route, visited);
164                 else
165                 {
166                         for(EndpointSeq::iterator j=endpoints.begin(); j!=endpoints.end(); ++j)
167                                 if(j->track==track && j->track_ep==&*i)
168                                         j->routes|=route;
169                 }
170         }
171
172         visited.erase(--visited.end());
173 }
174
175 unsigned Block::next_id=1;
176
177
178 Block::Endpoint::Endpoint(Track *t, const Track::Endpoint *e):
179         track(t),
180         track_ep(e),
181         link(0),
182         routes(0)
183 { }
184
185 } // namespace Marklin