2 #include <msp/time/units.h>
7 #include "trackcircuit.h"
16 Block::Block(Layout &l, Track &start):
19 sensor_id(start.get_sensor_id()),
20 turnout_id(start.get_turnout_id()),
23 tracks.insert(&start);
24 start.set_block(this);
27 queue.push_back(&start);
31 Track *track = queue.front();
32 queue.erase(queue.begin());
34 const vector<Track *> &links = track->get_links();
35 for(unsigned i=0; i<links.size(); ++i)
36 if(links[i] && !tracks.count(links[i]))
38 if(links[i]->get_sensor_id()==sensor_id && links[i]->get_turnout_id()==turnout_id)
40 queue.push_back(links[i]);
42 links[i]->set_block(this);
45 endpoints.push_back(Endpoint(track, i));
51 for(unsigned i=0; i<endpoints.size(); ++i)
54 endpoints[i].paths |= path;
55 find_paths(endpoints[i].track_iter(), path);
58 sensor = new TrackCircuit(layout, *this);
60 layout.add_block(*this);
65 set<Track *> trks = tracks;
67 for(set<Track *>::iterator i=trks.begin(); i!=trks.end(); ++i)
70 for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
71 if(Block *blk = i->link)
74 blk->break_link(*this);
77 layout.remove_block(*this);
82 TrackChain::Validity Block::check_validity(Track &track) const
84 if(track.get_sensor_id()!=sensor_id || track.get_turnout_id()!=turnout_id)
87 return TrackChain::check_validity(track);
90 const Block::Endpoint &Block::get_endpoint(unsigned i) const
92 if(i>=endpoints.size())
93 throw out_of_range("Block::get_endpoint");
98 int Block::get_endpoint_by_link(Block &other) const
100 for(unsigned i=0; i<endpoints.size(); ++i)
101 if(endpoints[i].link==&other)
107 float Block::get_path_length(unsigned entry, const Route *route) const
109 if(entry>=endpoints.size())
110 throw out_of_range("Block::get_path_length");
112 TrackIter t_iter = endpoints[entry].track_iter();
115 while(t_iter && has_track(*t_iter))
117 unsigned path = (route ? route->get_path(*t_iter) : t_iter->get_active_path());
118 result += t_iter->get_type().get_path_length(path);
120 t_iter = t_iter.next(path);
126 void Block::check_link(Block &other)
128 for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
133 for(vector<Endpoint>::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
134 if(j->track==i->track->get_link(i->track_ep) && j->track->get_link(j->track_ep)==i->track && !j->link)
140 other.determine_id();
145 void Block::break_link(Block &other)
147 for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
151 other.break_link(*this);
156 Block *Block::get_link(unsigned epi) const
158 if(epi>=endpoints.size())
159 throw out_of_range("Block::get_link");
160 return endpoints[epi].link;
163 bool Block::reserve(Train *t)
168 signal_reserved.emit(train);
175 void Block::find_paths(const TrackIter &track, unsigned path)
177 unsigned mask = track.endpoint().paths;
178 for(unsigned i=0; mask>>i; ++i)
181 TrackIter next = track.next(i);
184 else if(has_track(*next))
185 find_paths(track.next(i), path);
189 for(vector<Endpoint>::iterator j=endpoints.begin(); j!=endpoints.end(); ++j)
190 if(j->track==next.track() && j->track_ep==next.entry())
196 void Block::determine_id()
199 id = 0x1000|sensor_id;
201 id = 0x2000|turnout_id;
202 else if(endpoints.size()==2)
204 unsigned id1 = endpoints[0].link ? endpoints[0].link->get_id() : 1;
205 unsigned id2 = endpoints[1].link ? endpoints[1].link->get_id() : 1;
210 else if(endpoints.size()==1)
212 unsigned id1 = endpoints[0].link ? endpoints[0].link->get_id() : 1;
218 Block::Endpoint::Endpoint(Track *t, unsigned e):
225 TrackIter Block::Endpoint::track_iter() const
227 return TrackIter(track, track_ep);