1818#include < array>
1919#include < cstddef>
2020#include < deque>
21+ #include < iterator>
22+ #include < type_traits>
2123#include < vector>
2224
25+ #include < absl/log/check.h>
2326#include < absl/types/span.h>
2427
2528namespace mjpc ::spline {
@@ -79,6 +82,145 @@ class TimeSpline {
7982 using Node = NodeT<double >;
8083 using ConstNode = NodeT<const double >;
8184
85+ // Iterator type for TimeSpline.
86+ // SplineType is TimeSpline or const TimeSpline.
87+ // NodeType is Node or ConstNode.
88+ template <typename SplineType, typename NodeType>
89+ class IteratorT {
90+ public:
91+ using iterator_category = std::random_access_iterator_tag;
92+ using value_type = typename std::remove_cv_t <NodeType>;
93+ using difference_type = int ;
94+ using pointer = NodeType*;
95+ using reference = NodeType&;
96+
97+ IteratorT (SplineType* spline = nullptr , int index = 0 )
98+ : spline_(spline), index_(index) {
99+ if (spline_ != nullptr && index_ != spline->Size ()) {
100+ node_ = spline->NodeAt (index_);
101+ }
102+ }
103+
104+ // Copyable, Movable.
105+ IteratorT<SplineType, NodeType>(
106+ const IteratorT<SplineType, NodeType>& other) = default ;
107+ IteratorT<SplineType, NodeType>& operator =(
108+ const IteratorT<SplineType, NodeType>& other) = default ;
109+ IteratorT<SplineType, NodeType>(IteratorT<SplineType, NodeType>&& other) =
110+ default ;
111+ IteratorT<SplineType, NodeType>& operator =(
112+ IteratorT<SplineType, NodeType>&& other) = default ;
113+
114+ reference operator *() { return node_; }
115+
116+ pointer operator ->() { return &node_; }
117+ pointer operator ->() const { return &node_; }
118+
119+ IteratorT<SplineType, NodeType>& operator ++() {
120+ ++index_;
121+ node_ = index_ == spline_->Size () ? NodeType () : spline_->NodeAt (index_);
122+ return *this ;
123+ }
124+
125+ IteratorT<SplineType, NodeType> operator ++(int ) {
126+ IteratorT<SplineType, NodeType> tmp = *this ;
127+ ++(*this );
128+ return tmp;
129+ }
130+
131+ IteratorT<SplineType, NodeType>& operator --() {
132+ --index_;
133+ node_ = spline_->NodeAt (index_);
134+ return *this ;
135+ }
136+
137+ IteratorT<SplineType, NodeType> operator --(int ) {
138+ IteratorT<SplineType, NodeType> tmp = *this ;
139+ --(*this );
140+ return tmp;
141+ }
142+
143+ IteratorT<SplineType, NodeType>& operator +=(difference_type n) {
144+ if (n != 0 ) {
145+ index_ += n;
146+ node_ =
147+ index_ == spline_->Size () ? NodeType () : spline_->NodeAt (index_);
148+ }
149+ return *this ;
150+ }
151+
152+ IteratorT<SplineType, NodeType>& operator -=(difference_type n) {
153+ return *this += -n;
154+ }
155+
156+ IteratorT<SplineType, NodeType> operator +(difference_type n) const {
157+ IteratorT<SplineType, NodeType> tmp (*this );
158+ tmp += n;
159+ return tmp;
160+ }
161+
162+ IteratorT<SplineType, NodeType> operator -(difference_type n) const {
163+ IteratorT<SplineType, NodeType> tmp (*this );
164+ tmp -= n;
165+ return tmp;
166+ }
167+
168+ friend IteratorT<SplineType, NodeType> operator +(
169+ difference_type n, const IteratorT<SplineType, NodeType>& it) {
170+ return it + n;
171+ }
172+
173+ friend difference_type operator -(const IteratorT<SplineType, NodeType>& x,
174+ const IteratorT<SplineType, NodeType>& y) {
175+ CHECK_EQ (x.spline_ , y.spline_ )
176+ << " Comparing iterators from different splines" ;
177+ if (x != y) return (x.index_ - y.index_ );
178+ return 0 ;
179+ }
180+
181+ NodeType operator [](difference_type n) const { return *(*this + n); }
182+
183+ friend bool operator ==(const IteratorT<SplineType, NodeType>& x,
184+ const IteratorT<SplineType, NodeType>& y) {
185+ return x.spline_ == y.spline_ && x.index_ == y.index_ ;
186+ }
187+
188+ friend bool operator !=(const IteratorT<SplineType, NodeType>& x,
189+ const IteratorT<SplineType, NodeType>& y) {
190+ return !(x == y);
191+ }
192+
193+ friend bool operator <(const IteratorT<SplineType, NodeType>& x,
194+ const IteratorT<SplineType, NodeType>& y) {
195+ CHECK_EQ (x.spline_ , y.spline_ )
196+ << " Comparing iterators from different splines" ;
197+ return x.index_ < y.index_ ;
198+ }
199+
200+ friend bool operator >(const IteratorT<SplineType, NodeType>& x,
201+ const IteratorT<SplineType, NodeType>& y) {
202+ return y < x;
203+ }
204+
205+ friend bool operator <=(const IteratorT<SplineType, NodeType>& x,
206+ const IteratorT<SplineType, NodeType>& y) {
207+ return !(y < x);
208+ }
209+
210+ friend bool operator >=(const IteratorT<SplineType, NodeType>& x,
211+ const IteratorT<SplineType, NodeType>& y) {
212+ return !(x < y);
213+ }
214+
215+ private:
216+ SplineType* spline_ = nullptr ;
217+ int index_ = 0 ;
218+ NodeType node_;
219+ };
220+
221+ using iterator = IteratorT<TimeSpline, Node>;
222+ using const_iterator = IteratorT<const TimeSpline, ConstNode>;
223+
82224 // Returns the number of nodes in the spline.
83225 std::size_t Size () const ;
84226
@@ -88,6 +230,13 @@ class TimeSpline {
88230 Node NodeAt (int index);
89231 ConstNode NodeAt (int index) const ;
90232
233+ // Returns an iterator that iterates over spline nodes in time order.
234+ // Callers must not mutate `time`, but can modify values in `values`.
235+ iterator begin ();
236+ iterator end ();
237+ const_iterator cbegin () const ;
238+ const_iterator cend () const ;
239+
91240 void SetInterpolation (SplineInterpolation interpolation);
92241 SplineInterpolation Interpolation () const ;
93242
0 commit comments