#include "route.h"
#include "simplecontroller.h"
#include "timetable.h"
+#include "trackiter.h"
#include "tracktype.h"
#include "train.h"
#include "vehicle.h"
if(r && !cur_blocks.empty())
{
- BlockRef &first = cur_blocks.front();
- BlockRef &last = (rsv_blocks.empty() ? cur_blocks.back() : rsv_blocks.back());
- BlockRef next = last.next();
- const Block::Endpoint &first_ep = first.block->get_endpoints()[first.entry];
- const Block::Endpoint &next_ep = next.block->get_endpoints()[next.entry];
- if(!r->has_track(*next_ep.track))
+ TrackIter first = cur_blocks.front().track_iter();
+ TrackIter next = (rsv_blocks.empty() ? cur_blocks : rsv_blocks).back().next().track_iter();
+ if(!r->has_track(*next))
{
- Route *lead = Route::find(*next_ep.track, next_ep.track_ep, *r);
+ Route *lead = Route::find(*next, next.entry(), *r);
create_lead_route(lead, lead);
routes.push_front(lead);
}
- else if(!r->has_track(*first_ep.track))
+ else if(!r->has_track(*first))
routes.push_front(create_lead_route(0, r));
}
void Train::go_to(Track &to)
{
- for(list<BlockRef>::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
- if(i->block->has_track(to))
+ for(BlockList::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
+ if((*i)->has_track(to))
{
signal_arrived.emit();
set_route(0);
free_noncritical_blocks();
- BlockRef &last = (rsv_blocks.empty() ? cur_blocks.back() : rsv_blocks.back());
- BlockRef next = last.next();
- const Block::Endpoint &ep = next.block->get_endpoints()[next.entry];
+ TrackIter next = (rsv_blocks.empty() ? cur_blocks : rsv_blocks).back().next().track_iter();
- Route *route = Route::find(*ep.track, ep.track_ep, to);
+ Route *route = Route::find(*next, next.entry(), to);
create_lead_route(route, route);
set_route(route);
}
int path = -1;
unsigned from_ep = 0;
list<RouteRef>::iterator route = routes.begin();
- Block *block = cur_blocks.back().block;
- unsigned entry = cur_blocks.back().entry;
+ BlockIter block = cur_blocks.back();
set<const Track *> visited;
// Follow our routes to find out where we're entering the turnout
while(1)
{
- Block *link = block->get_link(block->traverse(entry, route->route));
- entry = link->get_endpoint_by_link(*block);
- block = link;
+ block = block.next(route->route);
- const Block::Endpoint &entry_ep = block->get_endpoints()[entry];
+ const Block::Endpoint &entry_ep = block->get_endpoints()[block.entry()];
if(visited.count(entry_ep.track))
return false;
break;
}
- Track *track = from.get_link(from.traverse(from_ep, path));
+ TrackIter track = TrackIter(&from, from_ep).next(path);
if(!track)
return false;
list<RouteRef>::iterator end = routes.end();
while(1)
{
- path = 0;
- if(track->get_turnout_id())
- path = diversion->get_turnout(track->get_turnout_id());
- Track *next = track->get_link(track->traverse(ep, path));
-
for(list<RouteRef>::iterator i=route; (end==routes.end() && i!=routes.end()); ++i)
- if(i->route->has_track(*next))
+ if(i->route->has_track(*track))
end = i;
if(end!=routes.end())
break;
- else if(!diversion->has_track(*next))
+ else if(!diversion->has_track(*track))
throw Exception("Pathfinder returned a bad route");
- ep = next->get_endpoint_by_link(*track);
- track = next;
+ unsigned tid = track->get_turnout_id();
+ track = track.next(tid ? diversion->get_turnout(tid) : 0);
}
if(route==end)
return;
}
- cur_blocks.push_back(BlockRef(&block, entry));
+ cur_blocks.push_back(BlockIter(&block, entry));
if(reverse)
{
- unsigned exit = block.traverse(entry);
- const Block::Endpoint &bep = block.get_endpoints()[exit];
- Track *track = bep.track->get_link(bep.track_ep);
- unsigned ep = track->get_endpoint_by_link(*bep.track);
- vehicles.front()->place(*track, ep, 0, Vehicle::FRONT_BUFFER);
+ TrackIter track = BlockIter(&block, entry).reverse().track_iter();
+ vehicles.front()->place(*track, track.entry(), 0, Vehicle::FRONT_BUFFER);
}
else
{
return false;
unsigned nsens = 0;
- for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
+ for(BlockList::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
{
- if(i->block==&block)
+ if(i->block()==&block)
{
if(nsens<1)
return false;
release_blocks(rsv_blocks, i, rsv_blocks.end());
return true;
}
- else if(i->block->get_sensor_id())
+ else if((*i)->get_sensor_id())
++nsens;
}
Vehicle &veh = *(reverse ? vehicles.back() : vehicles.front());
- Track *track = veh.get_track();
- list<BlockRef>::iterator block = cur_blocks.begin();
+ TrackIter track(veh.get_track(), veh.get_entry());
+ BlockList::iterator block = cur_blocks.begin();
bool in_rsv = false;
- while(block!=rsv_blocks.end() && !block->block->has_track(*track))
+ while(block!=rsv_blocks.end() && !(*block)->has_track(*track))
{
++block;
if(block==cur_blocks.end())
}
}
- unsigned entry = veh.get_entry();
float dist = veh.get_offset();
if(reverse)
- entry = track->traverse(entry);
+ track.reverse();
else
dist = track->get_type().get_path_length(track->get_active_path())-dist;
dist -= veh.get_type().get_length()/2;
bool nsens = 0;
while(1)
{
- Track *next = track->get_link(track->traverse(entry));
- entry = next->get_endpoint_by_link(*track);
- track = next;
+ track = track.next();
- if(!block->block->has_track(*track))
+ if(!(*block)->has_track(*track))
{
++block;
if(block==cur_blocks.end())
return;
}
- if(in_rsv && block->block->get_sensor_id())
+ if(in_rsv && (*block)->get_sensor_id())
++nsens;
}
int Train::get_entry_to_block(Block &block) const
{
- for(list<BlockRef>::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
- if(i->block==&block)
- return i->entry;
- for(list<BlockRef>::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
- if(i->block==&block)
- return i->entry;
+ for(BlockList::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
+ if(i->block()==&block)
+ return i->entry();
+ for(BlockList::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
+ if(i->block()==&block)
+ return i->entry();
return -1;
}
Track *track = vehicle.get_track();
bool ok = false;
- for(list<BlockRef>::const_iterator i=cur_blocks.begin(); (!ok && i!=cur_blocks.end()); ++i)
- ok = i->block->has_track(*track);
+ for(BlockList::const_iterator i=cur_blocks.begin(); (!ok && i!=cur_blocks.end()); ++i)
+ ok = (*i)->has_track(*track);
float d = get_real_speed(current_speed)*(dt/Time::sec);
if(ok)
set_route(0);
}
- if(!cur_blocks.empty() && !cur_blocks.front().block->get_sensor_id())
+ if(!cur_blocks.empty() && !cur_blocks.front()->get_sensor_id())
{
- float dist = get_reserved_distance_until(cur_blocks.front().block, true);
+ float dist = get_reserved_distance_until(&*cur_blocks.front(), true);
if(dist>10*layout.get_catalogue().get_scale())
{
- cur_blocks.front().block->reserve(0);
+ cur_blocks.front()->reserve(0);
cur_blocks.pop_front();
}
}
if(!cur_blocks.empty())
{
- list<BlockRef> blocks = cur_blocks;
+ BlockList blocks = cur_blocks;
if(reverse)
reverse_blocks(blocks);
- Block *prev = blocks.front().block->get_endpoints()[blocks.front().entry].link;
+ BlockIter prev = blocks.front().flip();
st.push_back((DataFile::Statement("block_hint"), prev->get_id()));
- for(list<BlockRef>::const_iterator i=blocks.begin(); i!=blocks.end(); ++i)
- st.push_back((DataFile::Statement("block"), i->block->get_id()));
+ for(BlockList::const_iterator i=blocks.begin(); i!=blocks.end(); ++i)
+ st.push_back((DataFile::Statement("block"), (*i)->get_id()));
}
if(!routes.empty())
if(state)
{
// Find the first sensor block from our reserved blocks that isn't this sensor
- list<BlockRef>::iterator i;
+ BlockList::iterator i;
unsigned result = 0;
for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
- if(i->block->get_sensor_id())
+ if((*i)->get_sensor_id())
{
- if(i->block->get_sensor_id()!=addr)
+ if((*i)->get_sensor_id()!=addr)
{
if(result==0)
result = 2;
}
travel_dist = 0;
- float block_len;
- for(list<BlockRef>::iterator j=rsv_blocks.begin(); j!=i; ++j)
+ for(BlockList::iterator j=rsv_blocks.begin(); j!=i; ++j)
{
- j->block->traverse(j->entry, &block_len);
- travel_dist += block_len;
+ travel_dist += (*j)->get_path_length(j->entry());
- if(j->block->get_sensor_id()==addr && !advancing)
+ if((*j)->get_sensor_id()==addr && !advancing)
{
- const Block::Endpoint &bep = j->block->get_endpoints()[j->entry];
+ TrackIter track = j->track_iter();
if(reverse)
{
- Track *track = bep.track->get_link(bep.track_ep);
- unsigned ep = track->get_endpoint_by_link(*bep.track);
- vehicles.back()->place(*track, ep, 0, Vehicle::BACK_AXLE);
+ track = track.flip();
+ vehicles.back()->place(*track, track.entry(), 0, Vehicle::BACK_AXLE);
}
else
- vehicles.front()->place(*bep.track, bep.track_ep, 0, Vehicle::FRONT_AXLE);
+ vehicles.front()->place(*track, track.entry(), 0, Vehicle::FRONT_AXLE);
}
}
last_entry_time = Time::now();
if(routes.size()>1)
{
const set<Track *> &rtracks = (++routes.begin())->route->get_tracks();
- for(list<BlockRef>::iterator j=rsv_blocks.begin(); j!=i; ++j)
- if(rtracks.count(j->block->get_endpoints()[j->entry].track))
+ for(BlockList::iterator j=rsv_blocks.begin(); j!=i; ++j)
+ if(rtracks.count((*j)->get_endpoints()[j->entry()].track))
{
routes.pop_front();
// XXX Exceptions?
const Vehicle &veh = *(reverse ? vehicles.front() : vehicles.back());
// Find the first sensor in our current blocks that's still active
- list<BlockRef>::iterator end = cur_blocks.begin();
- for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
+ BlockList::iterator end = cur_blocks.begin();
+ for(BlockList::iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
{
- if(i->block->has_track(*veh.get_track()))
+ if((*i)->has_track(*veh.get_track()))
break;
- if(i->block->get_sensor_id())
+ if((*i)->get_sensor_id())
{
- if(layout.get_driver().get_sensor(i->block->get_sensor_id()))
+ if(layout.get_driver().get_sensor((*i)->get_sensor_id()))
break;
else
{
if(!active)
return 0;
- BlockRef *start = 0;
+ BlockIter start;
if(!rsv_blocks.empty())
- start = &rsv_blocks.back();
+ start = rsv_blocks.back();
else if(!cur_blocks.empty())
- start = &cur_blocks.back();
- if(!start)
+ start = cur_blocks.back();
+ else
return 0;
pending_block = 0;
// See how many sensor blocks and how much track we already have
unsigned nsens = 0;
float dist = 0;
- for(list<BlockRef>::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
+ for(BlockList::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
{
- if(i->block->get_sensor_id())
+ if((*i)->get_sensor_id())
++nsens;
if(nsens>0)
- {
- float length = 0;
- i->block->traverse(i->entry, &length);
- dist += length;
- }
+ dist += (*i)->get_path_length(i->entry());
}
if(end_of_route)
return nsens;
list<RouteRef>::iterator cur_route = routes.begin();
- advance_route(cur_route, *start->block->get_endpoints()[start->entry].track);
+ advance_route(cur_route, *start.track_iter());
float approach_margin = 50*layout.get_catalogue().get_scale();
float min_dist = controller->get_braking_distance()*1.3+approach_margin*2;
- BlockRef *last = start;
- BlockRef *good = start;
+ BlockIter block = start;
+ BlockIter good = start;
Track *divert_track = 0;
bool try_divert = false;
unsigned good_sens = nsens;
float good_dist = dist;
Train *blocking_train = 0;
- std::list<BlockRef> contested_blocks;
+ BlockList contested_blocks;
SetFlag setf(reserving);
while(good_sens<3 || good_dist<min_dist || !contested_blocks.empty())
{
- // Traverse to the next block
- float length = 0;
- Block *link = 0;
- {
- const Route *route = (cur_route!=routes.end() ? cur_route->route : 0);
- unsigned exit = last->block->traverse(last->entry, route, &length);
- link = last->block->get_link(exit);
- }
- if(!link)
+ BlockIter last = block;
+ block = block.next(cur_route!=routes.end() ? cur_route->route : 0);
+ if(!block)
break;
- int entry = link->get_endpoint_by_link(*last->block);
- if(entry<0)
- throw LogicError("Block links are inconsistent!");
-
- const Block::Endpoint &entry_ep = link->get_endpoints()[entry];
+ TrackIter track = block.track_iter();
if(cur_route!=routes.end())
{
- if(!advance_route(cur_route, *entry_ep.track))
+ if(!advance_route(cur_route, *track))
{
// Keep the blocks if we arrived at the end of the route
if(!blocking_train)
break;
}
}
- else if(!routes.empty() && routes.front().route->has_track(*entry_ep.track))
+ else if(!routes.empty() && routes.front().route->has_track(*track))
cur_route = routes.begin();
- if(link->get_endpoints().size()<2)
+ if(block->get_endpoints().size()<2)
{
if(!blocking_train)
{
if(blocking_train)
{
- if(link->get_train()!=blocking_train)
+ if(block->get_train()!=blocking_train)
{
- if(blocking_train->free_block(*contested_blocks.back().block))
+ if(blocking_train->free_block(*contested_blocks.back()))
{
// Roll back and start actually reserving the blocks
- last = &rsv_blocks.back();
+ block = rsv_blocks.back();
cur_route = routes.begin();
- advance_route(cur_route, *last->block->get_endpoints()[last->entry].track);
+ advance_route(cur_route, *block.track_iter().track());
if(blocking_train->get_priority()==priority)
blocking_train->yield_to(*this);
blocking_train = 0;
else
{
yield_to(*blocking_train);
- pending_block = contested_blocks.front().block;
+ pending_block = contested_blocks.front().block();
try_divert = divert_track;
break;
}
}
else
{
- contested_blocks.push_back(BlockRef(link, entry));
- last = &contested_blocks.back();
+ contested_blocks.push_back(block);
continue;
}
}
- bool reserved = link->reserve(this);
+ bool reserved = block->reserve(this);
if(!reserved)
{
/* We've found another train. If it wants to exit the block from the
same endpoint we're trying to enter from or the other way around,
treat it as coming towards us. Otherwise treat it as going in the
same direction. */
- Train *other_train = link->get_train();
- int other_entry = other_train->get_entry_to_block(*link);
+ Train *other_train = block->get_train();
+ int other_entry = other_train->get_entry_to_block(*block);
if(other_entry<0)
throw LogicError("Block reservation inconsistency");
- bool entry_conflict = (static_cast<unsigned>(entry)==link->traverse(other_entry));
- bool exit_conflict = (link->traverse(entry)==static_cast<unsigned>(other_entry));
- if(!entry_conflict && !last->block->get_turnout_id())
+ unsigned exit = block.reverse().entry();
+ unsigned other_exit = BlockIter(block.block(), other_entry).reverse().entry();
+ bool entry_conflict = (block.entry()==other_exit);
+ bool exit_conflict = (exit==static_cast<unsigned>(other_entry));
+ if(!entry_conflict && !last->get_turnout_id())
{
/* The other train is not coming to the blocks we're holding, so we
can keep them. */
{
/* Ask a lesser priority train going to the same direction to free
the block for us */
- if(other_train->free_block(*link))
- reserved = link->reserve(this);
+ if(other_train->free_block(*block))
+ reserved = block->reserve(this);
}
else if(other_train!=yielding_to && (other_prio<priority || (other_prio==priority && entry_conflict)))
{
enough blocks to get clear of it to avoid a potential deadlock */
blocking_train = other_train;
contested_blocks.clear();
- contested_blocks.push_back(BlockRef(link, entry));
- last = &contested_blocks.back();
+ contested_blocks.push_back(block);
continue;
}
else if(divert_track && (entry_conflict || exit_conflict))
if(!reserved)
{
- pending_block = link;
+ pending_block = &*block;
break;
}
}
- if(link->get_turnout_id())
+ if(block->get_turnout_id())
{
- const Endpoint &track_ep = entry_ep.track->get_type().get_endpoints()[entry_ep.track_ep];
+ const Endpoint &track_ep = track->get_type().get_endpoints()[track.entry()];
bool multiple_paths = (track_ep.paths&(track_ep.paths-1));
- if(multiple_paths || !last->block->get_turnout_id())
+ if(multiple_paths || !last->get_turnout_id())
{
/* We can keep the blocks reserved so far if we are facing the
points or if there was no turnout immediately before this one.
// Figure out what path we'd like to take on the turnout
int path = -1;
for(list<RouteRef>::iterator i=cur_route; (path<0 && i!=routes.end()); ++i)
- path = i->route->get_turnout(link->get_turnout_id());
+ path = i->route->get_turnout(block->get_turnout_id());
if(path<0)
- path = entry_ep.track->get_active_path();
+ path = track->get_active_path();
if(!(track_ep.paths&(1<<path)))
{
for(unsigned i=0; track_ep.paths>>i; ++i)
path = i;
}
- if(path!=static_cast<int>(entry_ep.track->get_active_path()))
+ if(path!=static_cast<int>(track->get_active_path()))
{
// The turnout is set to wrong path - switch and wait for it
- pending_block = link;
- entry_ep.track->set_active_path(path);
+ pending_block = &*block;
+ track->set_active_path(path);
if(pending_block)
{
- link->reserve(0);
+ block->reserve(0);
break;
}
}
- if(multiple_paths && cur_route!=routes.end() && cur_route->diversion!=link->get_turnout_id())
+ if(multiple_paths && cur_route!=routes.end() && cur_route->diversion!=block->get_turnout_id())
/* There's multiple paths to be taken and we are on a route - take
note of the diversion possibility */
- divert_track = entry_ep.track;
+ divert_track = &*track;
}
- if(!contested_blocks.empty() && contested_blocks.front().block==link)
+ if(!contested_blocks.empty() && contested_blocks.front()==block)
contested_blocks.pop_front();
- rsv_blocks.push_back(BlockRef(link, entry));
- last = &rsv_blocks.back();
- if(last->block->get_sensor_id())
+ rsv_blocks.push_back(block);
+ if(block->get_sensor_id())
++nsens;
if(nsens>0)
- dist += length;
+ dist += block->get_path_length(block.entry());
}
// Unreserve blocks that were not good
- while(!rsv_blocks.empty() && &rsv_blocks.back()!=good)
+ while(!rsv_blocks.empty() && rsv_blocks.back()!=good)
{
- rsv_blocks.back().block->reserve(0);
+ rsv_blocks.back()->reserve(0);
rsv_blocks.pop_back();
}
- if(!rsv_blocks.empty() && &rsv_blocks.back()!=start)
+ if(!rsv_blocks.empty() && rsv_blocks.back()!=start)
// We got some new blocks, so no longer need to yield
yielding_to = 0;
// Make any sensorless blocks at the beginning immediately current
- list<BlockRef>::iterator i;
- for(i=rsv_blocks.begin(); (i!=rsv_blocks.end() && !i->block->get_sensor_id()); ++i) ;
+ BlockList::iterator i;
+ for(i=rsv_blocks.begin(); (i!=rsv_blocks.end() && !(*i)->get_sensor_id()); ++i) ;
if(i!=rsv_blocks.begin())
cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
Vehicle &veh = *(reverse!=back ? vehicles.back() : vehicles.front());
const VehicleType &vtype = veh.get_type();
- Track *track = veh.get_track();
+ TrackIter track(veh.get_track(), veh.get_entry());
if(!track)
return 0;
- list<BlockRef>::const_iterator block = cur_blocks.begin();
- while(block!=rsv_blocks.end() && !block->block->has_track(*track))
+ BlockList::const_iterator block = cur_blocks.begin();
+ while(block!=rsv_blocks.end() && !(*block)->has_track(*track))
{
++block;
if(block==cur_blocks.end())
block = rsv_blocks.begin();
}
}
- if(block==rsv_blocks.end() || block->block==until_block)
+ if(block==rsv_blocks.end() || &**block==until_block)
return 0;
- unsigned entry = veh.get_entry();
-
float result = veh.get_offset();
if(reverse!=back)
- entry = track->traverse(entry);
+ track = track.reverse();
else
result = track->get_type().get_path_length(track->get_active_path())-result;
result -= vtype.get_length()/2;
while(1)
{
- if(track->get_type().get_endpoints().size()<2)
+ track = track.next();
+ if(!track)
break;
- Track *next = track->get_link(track->traverse(entry));
-
- if(!block->block->has_track(*next))
+ if(!(*block)->has_track(*track))
{
if(back)
{
break;
}
- if(block->block==until_block)
+ if(&**block==until_block)
break;
}
- entry = next->get_endpoint_by_link(*track);
- track = next;
-
result += track->get_type().get_path_length(track->get_active_path());
}
signal_status_changed.emit(s);
}
-void Train::release_blocks(list<BlockRef> &blocks)
+void Train::release_blocks(BlockList &blocks)
{
release_blocks(blocks, blocks.begin(), blocks.end());
}
-void Train::release_blocks(list<BlockRef> &blocks, list<BlockRef>::iterator begin, list<BlockRef>::iterator end)
+void Train::release_blocks(BlockList &blocks, BlockList::iterator begin, BlockList::iterator end)
{
while(begin!=end)
{
- Block *block = begin->block;
+ Block &block = **begin;
blocks.erase(begin++);
- block->reserve(0);
+ block.reserve(0);
}
}
-void Train::reverse_blocks(list<BlockRef> &blocks) const
+void Train::reverse_blocks(BlockList &blocks) const
{
blocks.reverse();
- for(list<BlockRef>::iterator i=blocks.begin(); i!=blocks.end(); ++i)
- i->entry = i->block->traverse(i->entry);
+ for(BlockList::iterator i=blocks.begin(); i!=blocks.end(); ++i)
+ *i = i->reverse();
}
bool Train::advance_route(list<RouteRef>::iterator &iter, Track &track)
}
set<Track *> tracks;
- for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=rsv_blocks.end(); )
+ for(BlockList::iterator i=cur_blocks.begin(); i!=rsv_blocks.end(); )
{
- const set<Track *> &btracks = i->block->get_tracks();
+ const set<Track *> &btracks = (*i)->get_tracks();
for(set<Track *>::const_iterator j=btracks.begin(); j!=btracks.end(); ++j)
if(!target || !target->has_track(**j))
tracks.insert(*j);
bool Train::is_valid_diversion(const Route &diversion, Track &from, unsigned from_ep)
{
float diversion_len = 0;
- Track *track = &from;
- unsigned ep = from_ep;
+ TrackIter track(&from, from_ep);
while(diversion.has_track(*track))
{
- unsigned path = 0;
- if(track->get_turnout_id())
- path = diversion.get_turnout(track->get_turnout_id());
+ unsigned tid = track->get_turnout_id();
+ unsigned path = (tid ? diversion.get_turnout(tid) : 0);
diversion_len += track->get_type().get_path_length(path);
- Track *next = track->get_link(track->traverse(ep, path));
- ep = next->get_endpoint_by_link(*track);
- track = next;
+ track = track.next(path);
- if(track==&from)
+ if(&*track==&from)
return false;
}
set<Track *> visited;
float route_len = 0;
- track = &from;
- ep = from_ep;
+ track = TrackIter(&from, from_ep);
while(1)
{
- unsigned path = 0;
- if(track->get_turnout_id())
- path = route->route->get_turnout(track->get_turnout_id());
+ unsigned tid = track->get_turnout_id();
+ unsigned path = (tid ? route->route->get_turnout(tid) : 0);
route_len += track->get_type().get_path_length(path);
- if(track!=&from && diversion.has_track(*track))
+ if(&*track!=&from && diversion.has_track(*track))
break;
- if(visited.count(track))
+ if(visited.count(&*track))
return false;
- visited.insert(track);
+ visited.insert(&*track);
- Track *next = track->get_link(track->traverse(ep, path));
- ep = next->get_endpoint_by_link(*track);
- track = next;
+ track = track.next(path);
if(!advance_route(route, *track))
return false;
}
-Train::BlockRef::BlockRef(Block *b, unsigned e):
- block(b),
- entry(e)
-{ }
-
-Train::BlockRef Train::BlockRef::next() const
-{
- Block *blk = block->get_endpoints()[block->traverse(entry)].link;
- if(!blk)
- throw InvalidState("At end of line");
-
- int ep = blk->get_endpoint_by_link(*block);
- if(ep<0)
- throw LogicError("Block links are inconsistent");
-
- return BlockRef(blk, ep);
-}
-
-
Train::RouteRef::RouteRef(const Route *r, unsigned d):
route(r),
diversion(d)
{
if(!obj.cur_blocks.empty())
{
- const BlockRef &blkref = obj.cur_blocks.front();
- const Block::Endpoint &bep = blkref.block->get_endpoints()[blkref.entry];
+ TrackIter track = obj.cur_blocks.front().track_iter();
float offset = 2*obj.layout.get_catalogue().get_scale();
- obj.vehicles.back()->place(*bep.track, bep.track_ep, offset, Vehicle::BACK_BUFFER);
+ obj.vehicles.back()->place(*track, track.entry(), offset, Vehicle::BACK_BUFFER);
obj.set_status("Stopped");
}
entry = 0;
blk->reserve(&obj);
- obj.cur_blocks.push_back(BlockRef(blk, entry));
+ obj.cur_blocks.push_back(BlockIter(blk, entry));
if(blk->get_sensor_id())
obj.layout.get_driver().set_sensor(blk->get_sensor_id(), true);