]> git.tdb.fi Git - r2c2.git/blobdiff - source/libmarklin/train.cpp
Display the total length of selected tracks in status bar
[r2c2.git] / source / libmarklin / train.cpp
index baa58db0e813ee042141b589812f634f06163f2c..5bc50d85ff23ee5011535e34e5e6142f6b08fccc 100644 (file)
@@ -214,15 +214,19 @@ void Train::set_route(const Route *r)
 
        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 &ep = next.block->get_endpoints()[next.entry];
-               if(!r->get_tracks().count(ep.track))
-                       routes.push_front(Route::find(*ep.track, ep.track_ep, *r));
-
-               /* XXX This is sort of a hack, but it keeps divert() happy.  Need to come
-               up with a better solution when there is time. */
-               routes.push_front(create_lead_route());
+               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))
+               {
+                       Route *lead = Route::find(*next_ep.track, next_ep.track_ep, *r);
+                       create_lead_route(lead, lead);
+                       routes.push_front(lead);
+               }
+               else if(!r->has_track(*first_ep.track))
+                       routes.push_front(create_lead_route(0, r));
        }
 
        reserve_more();
@@ -230,10 +234,10 @@ void Train::set_route(const Route *r)
        signal_route_changed.emit(get_route());
 }
 
-void Train::go_to(const Track &to)
+void Train::go_to(Track &to)
 {
        for(list<BlockRef>::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
-               if(i->block->get_tracks().count(const_cast<Track *>(&to)))
+               if(i->block->has_track(to))
                {
                        signal_arrived.emit();
                        set_route(0);
@@ -246,7 +250,9 @@ void Train::go_to(const Track &to)
        BlockRef next = last.next();
        const Block::Endpoint &ep = next.block->get_endpoints()[next.entry];
 
-       set_route(Route::find(*ep.track, ep.track_ep, to));
+       Route *route = Route::find(*ep.track, ep.track_ep, to);
+       create_lead_route(route, route);
+       set_route(route);
 }
 
 bool Train::divert(Track &from)
@@ -309,7 +315,7 @@ bool Train::divert(Track &from)
 
        unsigned ep = track->get_endpoint_by_link(from);
 
-       set<const Track *> tracks;
+       set<Track *> tracks;
        for(list<RouteRef>::iterator i=routes.begin(); i!=routes.end(); ++i)
                tracks.insert(i->route->get_tracks().begin(), i->route->get_tracks().end());
        Route *diversion = 0;
@@ -342,12 +348,12 @@ bool Train::divert(Track &from)
                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->get_tracks().count(next))
+                       if(i->route->has_track(*next))
                                end = i;
 
                if(end!=routes.end())
                        break;
-               else if(!diversion->get_tracks().count(next))
+               else if(!diversion->has_track(*next))
                        throw Exception("Pathfinder returned a bad route");
 
                ep = next->get_endpoint_by_link(*track);
@@ -466,7 +472,7 @@ void Train::free_noncritical_blocks()
        Track *track = veh.get_track();
        list<BlockRef>::iterator block = cur_blocks.begin();
        bool in_rsv = false;
-       while(block!=rsv_blocks.end() && !block->block->get_tracks().count(track))
+       while(block!=rsv_blocks.end() && !block->block->has_track(*track))
        {
                ++block;
                if(block==cur_blocks.end())
@@ -491,7 +497,7 @@ void Train::free_noncritical_blocks()
                entry = next->get_endpoint_by_link(*track);
                track = next;
 
-               if(!block->block->get_tracks().count(track))
+               if(!block->block->has_track(*track))
                {
                        ++block;
                        if(block==cur_blocks.end())
@@ -582,7 +588,7 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt)
 
                bool ok = false;
                for(list<BlockRef>::const_iterator i=cur_blocks.begin(); (!ok && i!=cur_blocks.end()); ++i)
-                       ok = i->block->get_tracks().count(track);
+                       ok = i->block->has_track(*track);
 
                float d = get_real_speed(current_speed)*(dt/Time::sec);
                if(ok)
@@ -758,7 +764,7 @@ void Train::sensor_event(unsigned addr, bool state)
                        // Check if we've reached the next route
                        if(routes.size()>1)
                        {
-                               const set<const Track *> &rtracks = (++routes.begin())->route->get_tracks();
+                               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))
                                        {
@@ -787,7 +793,7 @@ void Train::sensor_event(unsigned addr, bool state)
                list<BlockRef>::iterator end = cur_blocks.begin();
                for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
                {
-                       if(i->block->get_tracks().count(veh.get_track()))
+                       if(i->block->has_track(*veh.get_track()))
                                break;
                        if(i->block->get_sensor_id())
                        {
@@ -919,7 +925,7 @@ unsigned Train::reserve_more()
                                break;
                        }
                }
-               else if(!routes.empty() && routes.front().route->get_tracks().count(entry_ep.track))
+               else if(!routes.empty() && routes.front().route->has_track(*entry_ep.track))
                        cur_route = routes.begin();
 
                if(link->get_endpoints().size()<2)
@@ -1111,7 +1117,7 @@ float Train::get_reserved_distance_until(const Block *until_block, bool back) co
                return 0;
 
        list<BlockRef>::const_iterator block = cur_blocks.begin();
-       while(block!=rsv_blocks.end() && !block->block->get_tracks().count(track))
+       while(block!=rsv_blocks.end() && !block->block->has_track(*track))
        {
                ++block;
                if(block==cur_blocks.end())
@@ -1140,7 +1146,7 @@ float Train::get_reserved_distance_until(const Block *until_block, bool back) co
 
                Track *next = track->get_link(track->traverse(entry));
 
-               if(!block->block->get_tracks().count(next))
+               if(!block->block->has_track(*next))
                {
                        if(back)
                        {
@@ -1268,54 +1274,60 @@ void Train::reverse_blocks(list<BlockRef> &blocks) const
                i->entry = i->block->traverse(i->entry);
 }
 
-bool Train::advance_route(list<RouteRef>::iterator &iter, const Track &track)
+bool Train::advance_route(list<RouteRef>::iterator &iter, Track &track)
 {
-       while(iter!=routes.end() && !iter->route->get_tracks().count(&track))
+       while(iter!=routes.end() && !iter->route->has_track(track))
                ++iter;
        if(iter==routes.end())
                return false;
 
        list<RouteRef>::iterator next = iter;
        ++next;
-       if(next!=routes.end() && next->diversion && next->route->get_tracks().count(&track))
+       if(next!=routes.end() && next->diversion && next->route->has_track(track))
                iter = next;
 
        return true;
 }
 
-Route *Train::create_lead_route()
+Route *Train::create_lead_route(Route *lead, const Route *target)
 {
-       Route *lead = new Route(layout);
-       lead->set_name("Lead");
-       lead->set_temporary(true);
+       if(!lead)
+       {
+               lead = new Route(layout);
+               lead->set_name("Lead");
+               lead->set_temporary(true);
+       }
 
+       set<Track *> tracks;
        for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=rsv_blocks.end(); )
        {
-               // XXX Make Route eat non-const tracks to get rid of this idiocy and various const_casts
                const set<Track *> &btracks = i->block->get_tracks();
-               set<const Track *> tracks(btracks.begin(), btracks.end());
-               lead->add_tracks(tracks);
+               for(set<Track *>::const_iterator j=btracks.begin(); j!=btracks.end(); ++j)
+                       if(!target || !target->has_track(**j))
+                               tracks.insert(*j);
 
                if(++i==cur_blocks.end())
                        i = rsv_blocks.begin();
        }
 
+       lead->add_tracks(tracks);
+
        return lead;
 }
 
-bool Train::is_valid_diversion(const Route &diversion, const Track &from, unsigned from_ep)
+bool Train::is_valid_diversion(const Route &diversion, Track &from, unsigned from_ep)
 {
        float diversion_len = 0;
-       const Track *track = &from;
+       Track *track = &from;
        unsigned ep = from_ep;
-       while(diversion.get_tracks().count(track))
+       while(diversion.has_track(*track))
        {
                unsigned path = 0;
                if(track->get_turnout_id())
                        path = diversion.get_turnout(track->get_turnout_id());
                diversion_len += track->get_type().get_path_length(path);
 
-               const Track *next = track->get_link(track->traverse(ep, path));
+               Track *next = track->get_link(track->traverse(ep, path));
                ep = next->get_endpoint_by_link(*track);
                track = next;
 
@@ -1327,7 +1339,7 @@ bool Train::is_valid_diversion(const Route &diversion, const Track &from, unsign
        if(!advance_route(route, from))
                return false;
 
-       set<const Track *> visited;
+       set<Track *> visited;
        float route_len = 0;
        track = &from;
        ep = from_ep;
@@ -1338,14 +1350,14 @@ bool Train::is_valid_diversion(const Route &diversion, const Track &from, unsign
                        path = route->route->get_turnout(track->get_turnout_id());
                route_len += track->get_type().get_path_length(path);
 
-               if(track!=&from && diversion.get_tracks().count(track))
+               if(track!=&from && diversion.has_track(*track))
                        break;
 
                if(visited.count(track))
                        return false;
                visited.insert(track);
 
-               const Track *next = track->get_link(track->traverse(ep, path));
+               Track *next = track->get_link(track->traverse(ep, path));
                ep = next->get_endpoint_by_link(*track);
                track = next;