]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/trackoffsetiter.cpp
Create another track iterator class that holds an offset as well
[r2c2.git] / source / libr2c2 / trackoffsetiter.cpp
diff --git a/source/libr2c2/trackoffsetiter.cpp b/source/libr2c2/trackoffsetiter.cpp
new file mode 100644 (file)
index 0000000..a614569
--- /dev/null
@@ -0,0 +1,131 @@
+#include <msp/strings/format.h>
+#include "blockiter.h"
+#include "route.h"
+#include "track.h"
+#include "tracktype.h"
+#include "trackoffsetiter.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace R2C2 {
+
+incompatible_path::incompatible_path(unsigned a, unsigned e):
+       logic_error(format("got %d, but %d already set", a, e))
+{ }
+
+
+TrackOffsetIter::TrackOffsetIter():
+       _offset(0),
+       _path(0)
+{ }
+
+TrackOffsetIter::TrackOffsetIter(Track *t, unsigned e, float o):
+       _track(t, e),
+       _offset(_track ? o : 0),
+       _path((_track && _offset) ? _track->get_active_path() : -1)
+{ }
+
+TrackOffsetIter::TrackOffsetIter(Track *t, unsigned e, unsigned p, float o):
+       _track(t, e),
+       _offset(o),
+       _path(p)
+{ }
+
+TrackOffsetIter::TrackOffsetIter(const TrackIter &t, float o):
+       _track(t),
+       _offset(_track ? o : 0),
+       _path((_track && _offset) ? _track->get_active_path() : -1)
+{ }
+
+TrackOffsetIter::TrackOffsetIter(const TrackIter &t, unsigned p, float o):
+       _track(t),
+       _offset(o),
+       _path(p)
+{ }
+
+BlockIter TrackOffsetIter::block_iter() const
+{
+       return _track.block_iter();
+}
+
+TrackPoint TrackOffsetIter::point() const
+{
+       if(!_track)
+               return TrackPoint();
+
+       if(_path>=0)
+               return _track->get_point(_track.entry(), _path, _offset);
+       else
+               return _track->get_point(_track.entry(), _offset);
+}
+
+TrackOffsetIter TrackOffsetIter::next() const
+{
+       if(_path>=0)
+               return _track.next(_path);
+       else
+               return _track.next();
+}
+
+TrackOffsetIter TrackOffsetIter::next(unsigned p) const
+{
+       if(_path>=0 && static_cast<unsigned>(_path)!=p)
+               throw incompatible_path(_path, p);
+       
+       return _track.next(p);
+}
+
+TrackOffsetIter TrackOffsetIter::advance(float d, const Route *r) const
+{
+       if(!_track)
+               return TrackOffsetIter();
+
+       if(d<0)
+               return reverse().advance(-d, r).reverse();
+
+       TrackIter t = _track;
+       int p = _path;
+       float o = _offset+d;
+
+       while(t)
+       {
+               if(p<0)
+               {
+                       if(r)
+                               if(unsigned tid = t->get_turnout_id())
+                                       p = r->get_turnout(tid);
+                       if(p<0)
+                               p = t->get_active_path();
+               }
+
+               float length = t->get_type().get_path_length(p);
+               if(o<length)
+                       return TrackOffsetIter(t, p, o);
+
+               o -= length;
+               t = t.next(p);
+               p = -1;
+       }
+
+       return TrackOffsetIter();
+}
+       
+TrackOffsetIter TrackOffsetIter::reverse() const
+{
+       if(!_track)
+               return TrackOffsetIter();
+
+       int p = (_path>=0 ? _path : _track->get_active_path());
+       TrackIter t = _track.reverse(p);
+       float o = t->get_type().get_path_length(p)-_offset;
+
+       return TrackOffsetIter(t, p, o);
+}
+
+bool TrackOffsetIter::operator==(const TrackOffsetIter &other) const
+{
+       return _track==other._track && _offset==other._offset && _path==other._path;
+}
+
+} // namespaec R2C2