]> git.tdb.fi Git - r2c2.git/blobdiff - source/libmarklin/route.cpp
Major architecture rework
[r2c2.git] / source / libmarklin / route.cpp
index 40638d9683051fd3fa4581b14f3d6458d89d4880..7db3f324b61e9ce5d753786aac251982cff6ec90 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2007-2009  Mikkosoft Productions, Mikko Rasa
+Copyright © 2007-2010  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -15,12 +15,19 @@ using namespace Msp;
 
 namespace Marklin {
 
-Route::Route(Layout &layout, const string &n):
+Route::Route(Layout &l, const string &n):
+       layout(l),
        name(n)
 {
+       layout.add_route(*this);
        layout.signal_track_removed.connect(sigc::mem_fun(this, &Route::track_removed));
 }
 
+Route::~Route()
+{
+       layout.remove_route(*this);
+}
+
 int Route::get_turnout(unsigned id) const
 {
        map<unsigned, int>::const_iterator i = turnouts.find(id);
@@ -92,17 +99,20 @@ void Route::update_turnouts()
                        const vector<Endpoint> &endpoints = (*i)->get_type().get_endpoints();
                        const vector<Track *> &links = (*i)->get_links();
 
+                       // Build a combined path mask from linked endpoints
                        unsigned mask = 15;
                        for(unsigned j=0; j<endpoints.size(); ++j)
                        {
                                if(!tracks.count(links[j]))
                                        continue;
+
                                if(unsigned tid2=links[j]->get_turnout_id())
                                {
                                        const Endpoint &ep = links[j]->get_type().get_endpoints()[links[j]->get_endpoint_by_link(**i)];
                                        int p = get_turnout(tid2);
                                        if(p>=0 && !(ep.paths&(1<<p)))
                                        {
+                                               // The linked track is a turnout and has a path which is incompatible with this endpoint
                                                mask &= ~endpoints[j].paths;
                                                continue;
                                        }
@@ -110,16 +120,19 @@ void Route::update_turnouts()
                                mask &= endpoints[j].paths;
                        }
 
-                       if(!(mask&(mask-1)))
+                       if(mask && !(mask&(mask-1)))
                        {
+                               // Exactly one possible choice, set the path accordingly
                                unsigned path = 0;
                                for(; (mask && !(mask&1)); mask>>=1, ++path) ;
                                turnouts[tid] = path;
                        }
-                       else
+                       else if(!turnouts.count(tid))
+                               // More than one possible choice, and no existing entry - set as undecided
                                turnouts[tid] = -1;
                }
 
+       // Remove any turnouts that do not exist in the route
        for(map<unsigned, int>::iterator i=turnouts.begin(); i!=turnouts.end();)
        {
                if(!found.count(i->first))
@@ -137,6 +150,7 @@ unsigned Route::check_validity(const Track &trk) const
                int epi=(*i)->get_endpoint_by_link(trk);
                if(epi>=0)
                {
+                       // Linked to an existing track - good
                        result |= 1;
                        const vector<Endpoint> &endpoints = (*i)->get_type().get_endpoints();
                        if(unsigned tid=(*i)->get_turnout_id())
@@ -144,11 +158,13 @@ unsigned Route::check_validity(const Track &trk) const
                                int r = get_turnout(tid);
                                if(r>=0)
                                {
+                                       // Linking to a turnout with path set is only good if we're continuing that path
                                        if(endpoints[epi].paths&(1<<r))
                                                result |= 2;
                                }
                                else
                                {
+                                       // Linked to a turnout with no path set - find out other linked tracks 
                                        unsigned count = 0;
                                        const vector<Track *> &links = (*i)->get_links();
                                        int epj = -1;
@@ -158,15 +174,19 @@ unsigned Route::check_validity(const Track &trk) const
                                                        ++count;
                                                        epj = k;
                                                }
+
+                                       // Only good if at most one other track is linked to the turnout
                                        if(count<=1)
                                        {
                                                result |= 2;
                                                if(epj>=0 && !(endpoints[epi].paths&endpoints[epj].paths))
+                                                       // Impossible path through the turnout - not good
                                                        result &= 3;
                                        }
                                }
                        }
                        else
+                               // Linked to something linear - good
                                result |= 2;
                }
        }