void TrainRouter::route_changed()
{
- train.stop_at(0);
- arriving = 0;
BlockIter fncb = train.get_first_noncritical_block();
- train.refresh_blocks_from(*fncb);
+
+ reserving_route = routes.begin();
+ bool already_at_end = false;
+ if(!routes.empty())
+ {
+ TrackIter track = train.get_block_allocator().first().track_iter();
+ for(; track; track=track.next())
+ {
+ if(!advance_to_track(reserving_route, *track))
+ {
+ already_at_end = true;
+ break;
+ }
+ if(&track->get_block()==fncb.block())
+ break;
+ }
+ }
+
+ if(!already_at_end)
+ {
+ train.stop_at(0);
+ train.refresh_blocks_from(*fncb);
+ }
const Route *route = get_route();
signal_route_changed.emit(route);
void TrainRouter::block_reserved(Block &block, Train *t)
{
+ if(routes.empty())
+ return;
+
if(t!=&train)
{
if(!t)
}
}
- BlockIter b_iter = t->get_block_allocator().iter_for(block);
+ TrackIter track = train.get_block_allocator().iter_for(block).track_iter();
- RouteList::iterator route = routes.begin();
- if(advance_route(route, block))
+ // Is the block a turnout? If so, set it to the proper path.
+ if(unsigned taddr = block.get_turnout_address())
{
- // Check if the block is a turnout and set it to proper path
- if(unsigned taddr = block.get_turnout_address())
+ int path = (*reserving_route)->get_turnout(taddr);
+ if(path>=0)
+ track->set_active_path(path);
+ }
+
+ if(reserving_route==routes.end() || !(*reserving_route)->has_track(*track))
+ {
+ reserving_route = routes.begin();
+ track = t->get_block_allocator().first().track_iter();
+ for(; track; track=track.next())
{
- int path = (*route)->get_turnout(taddr);
- if(path>=0)
- b_iter.track_iter()->set_active_path(path);
+ if(!advance_to_track(reserving_route, *track))
+ throw logic_error("internal error (reservation outside of route)");
+ else if(&track->get_block()==&block)
+ break;
}
+ }
- // Check if the next block is still part of the designated route
- BlockIter b_iter_next = b_iter.next(*route);
-
- RouteList::iterator next_route = route;
- if(!advance_route(next_route, *b_iter_next))
+ // Do we need to move to the next route?
+ for(; track; track=track.next((*reserving_route)->get_path(*track)))
+ {
+ if(!advance_to_track(reserving_route, *track))
{
train.stop_at(&block);
return;
}
+ if(&track->get_block()!=&block)
+ break;
+ }
- if(!sequence_points.empty())
- {
- SequencePoint &sp = sequence_points.front();
- if(sp.block==b_iter_next.block() && !sp.is_cleared())
- train.stop_at(&block);
- }
+ if(!sequence_points.empty())
+ {
+ SequencePoint &sp = sequence_points.front();
+ if(sp.block==&track->get_block() && !sp.is_cleared())
+ train.stop_at(&block);
}
}
return lead;
}
-bool TrainRouter::advance_route(RouteList::iterator &iter, const Block &block)
+bool TrainRouter::is_valid_for_track(const Route &route, Track &track) const
{
- const set<Track *> &tracks = block.get_tracks();
- unsigned turnout_addr = block.get_turnout_address();
- for(; iter!=routes.end(); ++iter)
- {
- if(turnout_addr && (*iter)->get_turnout(turnout_addr)<0)
- continue;
- for(set<Track *>::const_iterator j=tracks.begin(); j!=tracks.end(); ++j)
- if((*iter)->has_track(**j))
- return true;
- }
-
- return false;
+ if(!route.has_track(track))
+ return false;
+ if(track.get_type().is_turnout() && route.get_turnout(track.get_turnout_address())<0)
+ return false;
+ return true;
}
-bool TrainRouter::is_on_route(const Block &block)
+bool TrainRouter::advance_to_track(RouteList::iterator &route, Track &track)
{
- RouteList::iterator iter = routes.begin();
- return advance_route(iter, block);
+ if(!is_valid_for_track(**route, track))
+ {
+ ++route;
+ if(route==routes.end())
+ return false;
+ if(!is_valid_for_track(**route, track))
+ throw logic_error("internal error (routes are not continuous)");
+ }
+
+ return true;
}
void TrainRouter::start_planning(Layout &layout)