]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/trackiter.cpp
Use path coercion in track iterators
[r2c2.git] / source / libr2c2 / trackiter.cpp
index 3c6295bb974437720b7677cf18bdbadab9136381..330e2f66c810bd9ee2c38cd0c6f2f1ebd14ae6d7 100644 (file)
@@ -1,12 +1,5 @@
-/* $Id$
-
-This file is part of R²C²
-Copyright © 2010  Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
 #include <algorithm>
-#include <msp/core/except.h>
+#include "blockiter.h"
 #include "track.h"
 #include "trackiter.h"
 #include "tracktype.h"
@@ -26,24 +19,63 @@ TrackIter::TrackIter(Track *t, unsigned e):
        _entry(t ? e : 0)
 {
        if(_track && _entry>_track->get_type().get_endpoints().size())
-               throw InvalidParameterValue("Endpoint index not valid for track");
+               throw out_of_range("TrackIter::TrackIter");
+}
+
+BlockIter TrackIter::block_iter() const
+{
+       if(!_track)
+               return BlockIter();
+
+       Block &block = _track->get_block();
+       const vector<Block::Endpoint> &beps = block.get_endpoints();
+
+       // See if this track matches an endpoint in the block
+       for(unsigned i=0; i<beps.size(); ++i)
+               if(beps[i].track==_track && beps[i].track_ep==_entry)
+                       return BlockIter(&block, i);
+
+       if(!_track->get_type().is_turnout())
+       {
+               /* Since there was no endpoint match, the preceding track can't be in a
+               different block. */
+               TrackIter rev = flip();
+               TrackIter last;
+               while(rev && &rev.track()->get_block()==&block)
+               {
+                       last = rev;
+                       rev = rev.next();
+               }
+
+               // If we ran out of tracks, return an empty iterator
+               if(!rev)
+                       return BlockIter();
+
+               TrackIter fwd = last.reverse();
+               for(unsigned i=0; i<beps.size(); ++i)
+                       if(beps[i].track==fwd.track() && beps[i].track_ep==fwd.entry())
+                               return BlockIter(&block, i);
+       }
+
+       throw logic_error("internal error (didn't find block entry endpoint)");
 }
 
 const TrackType::Endpoint &TrackIter::endpoint() const
 {
        if(!_track)
-               throw InvalidState("TrackIter is null");
+               throw logic_error("null track");
 
        return _track->get_type().get_endpoint(_entry);
 }
 
 int TrackIter::get_exit(unsigned path) const
 {
+       path = _track->get_type().coerce_path(_entry, path);
        const vector<TrackType::Endpoint> &eps = _track->get_type().get_endpoints();
        
        // Find an endpoint that's connected to the entry and has the requested path
        for(unsigned i=0; i<eps.size(); ++i)
-               if(i!=_entry && (eps[i].paths&(1<<path)) && (eps[i].paths&eps[_entry].paths))
+               if(i!=_entry && eps[i].has_path(path) && eps[i].has_common_paths(eps[_entry]))
                        return i;
 
        return -1;
@@ -68,7 +100,7 @@ TrackIter TrackIter::next(unsigned path) const
 
        TrackIter result;
        result._track = _track->get_link(exit);
-       result._entry = (result._track ? result._track->get_endpoint_by_link(*_track) : 0);
+       result._entry = (result._track ? result._track->get_link_slot(*_track) : 0);
 
        return result;
 }
@@ -100,7 +132,7 @@ TrackIter TrackIter::flip() const
 
        TrackIter result;
        result._track = _track->get_link(_entry);
-       result._entry = (result._track ? result._track->get_endpoint_by_link(*_track) : 0);
+       result._entry = (result._track ? result._track->get_link_slot(*_track) : 0);
 
        return result;
 }
@@ -108,7 +140,7 @@ TrackIter TrackIter::flip() const
 Track &TrackIter::operator*() const
 {
        if(!_track)
-               throw InvalidState("TrackIter is null");
+               throw logic_error("null track");
 
        return *_track;
 }