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