]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/trackoffsetiter.cpp
Use path coercion in track iterators
[r2c2.git] / source / libr2c2 / trackoffsetiter.cpp
1 #include <msp/strings/format.h>
2 #include "blockiter.h"
3 #include "route.h"
4 #include "track.h"
5 #include "tracktype.h"
6 #include "trackoffsetiter.h"
7
8 using namespace std;
9 using namespace Msp;
10
11 namespace R2C2 {
12
13 incompatible_path::incompatible_path(unsigned a, unsigned e):
14         logic_error(format("got %d, but %d already set", a, e))
15 { }
16
17
18 TrackOffsetIter::TrackOffsetIter():
19         _offset(0),
20         _path(0)
21 { }
22
23 TrackOffsetIter::TrackOffsetIter(Track *t, unsigned e, float o):
24         _track(t, e),
25         _offset(_track ? o : 0),
26         _path((_track && _offset) ? _track->get_active_path() : -1)
27 {
28         validate();
29 }
30
31 TrackOffsetIter::TrackOffsetIter(Track *t, unsigned e, unsigned p, float o):
32         _track(t, e),
33         _offset(o),
34         _path(p)
35 {
36         validate();
37 }
38
39 TrackOffsetIter::TrackOffsetIter(const TrackIter &t, float o):
40         _track(t),
41         _offset(_track ? o : 0),
42         _path((_track && _offset) ? _track->get_active_path() : -1)
43 {
44         validate();
45 }
46
47 TrackOffsetIter::TrackOffsetIter(const TrackIter &t, unsigned p, float o):
48         _track(t),
49         _offset(o),
50         _path(p)
51 {
52         validate();
53 }
54
55 void TrackOffsetIter::validate()
56 {
57         if(!_track)
58                 return;
59
60         if(_offset<0)
61                 throw invalid_argument("TrackOffsetIter::TrackOffsetIter");
62
63         if(_path>=0)
64         {
65                 if(!_track.endpoint().has_path(_path))
66                         throw invalid_argument("TrackOffsetIter::TrackOffsetIter");
67                 if(_offset>_track->get_type().get_path_length(_path))
68                         throw invalid_argument("TrackOffsetIter::TrackOffsetIter");
69         }
70 }
71
72 BlockIter TrackOffsetIter::block_iter() const
73 {
74         return _track.block_iter();
75 }
76
77 OrientedPoint TrackOffsetIter::point() const
78 {
79         if(!_track)
80                 return OrientedPoint();
81
82         if(_path>=0)
83                 return _track->get_point(_track.entry(), _path, _offset);
84         else
85                 return _track->get_point(_track.entry(), _offset);
86 }
87
88 TrackOffsetIter TrackOffsetIter::next() const
89 {
90         if(_path>=0)
91                 return _track.next(_path);
92         else
93                 return _track.next();
94 }
95
96 TrackOffsetIter TrackOffsetIter::next(unsigned p) const
97 {
98         if(_path>=0 && static_cast<unsigned>(_path)!=p)
99                 throw incompatible_path(_path, p);
100         
101         return _track.next(p);
102 }
103
104 TrackOffsetIter TrackOffsetIter::advance(float d, const Route *r) const
105 {
106         if(!_track)
107                 return TrackOffsetIter();
108
109         if(d<0)
110                 return reverse().advance(-d, r).reverse();
111
112         TrackIter t = _track;
113         int p = _path;
114         float o = _offset+d;
115
116         while(t)
117         {
118                 if(p<0)
119                         p = (r ? r->get_path(*t) : t->get_active_path());
120                 p = t->get_type().coerce_path(t.entry(), p);
121
122                 float length = t->get_type().get_path_length(p);
123                 if(o<length)
124                         return TrackOffsetIter(t, p, o);
125
126                 o -= length;
127                 t = t.next(p);
128                 p = -1;
129         }
130
131         return TrackOffsetIter();
132 }
133         
134 TrackOffsetIter TrackOffsetIter::reverse() const
135 {
136         if(!_track)
137                 return TrackOffsetIter();
138
139         int p = (_path>=0 ? _path : _track->get_active_path());
140         TrackIter t = _track.reverse(p);
141         if(!t)
142                 return TrackOffsetIter();
143
144         float o = t->get_type().get_path_length(p)-_offset;
145
146         return TrackOffsetIter(t, p, o);
147 }
148
149 bool TrackOffsetIter::operator==(const TrackOffsetIter &other) const
150 {
151         return _track==other._track && _offset==other._offset && _path==other._path;
152 }
153
154 } // namespaec R2C2