Skip to content

Commit 9324301

Browse files
authored
Merge pull request #3142 from pleroy/Iterators
DiscreteTrajectoryIterator
2 parents b50bf9c + 5c61d02 commit 9324301

8 files changed

+426
-18
lines changed

physics/discrete_trajectory2.hpp

+12-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <vector>
66

77
#include "absl/container/btree_map.h"
8+
#include "base/macros.hpp"
89
#include "base/not_null.hpp"
910
#include "geometry/named_quantities.hpp"
1011
#include "physics/degrees_of_freedom.hpp"
@@ -18,8 +19,9 @@
1819
namespace principia {
1920
namespace physics {
2021

21-
template<typename Frame>
22-
class DiscreteTrajectorySegment;
22+
FORWARD_DECLARE_FROM(discrete_trajectory_segment,
23+
TEMPLATE(typename Frame) class,
24+
DiscreteTrajectorySegment);
2325

2426
namespace internal_discrete_trajectory {
2527

@@ -65,8 +67,8 @@ class DiscreteTrajectory2 : public Trajectory<Frame> {
6567

6668
SegmentIterator NewSegment();
6769

68-
DiscreteTrajectory DetachSegments(iterator begin);
69-
SegmentIterator AttachSegments(DiscreteTrajectory&& trajectory);
70+
DiscreteTrajectory2 DetachSegments(iterator begin);
71+
SegmentIterator AttachSegments(DiscreteTrajectory2&& trajectory);
7072
void DeleteSegments(iterator begin);
7173

7274
void ForgetAfter(Instant const& t);
@@ -78,6 +80,9 @@ class DiscreteTrajectory2 : public Trajectory<Frame> {
7880
void Append(Instant const& t,
7981
DegreesOfFreedom<Frame> const& degrees_of_freedom);
8082

83+
Instant t_min() const override;
84+
Instant t_max() const override;
85+
8186
Position<Frame> EvaluatePosition(Instant const& time) const override;
8287
Velocity<Frame> EvaluateVelocity(Instant const& time) const override;
8388
DegreesOfFreedom<Frame> EvaluateDegreesOfFreedom(
@@ -95,9 +100,9 @@ class DiscreteTrajectory2 : public Trajectory<Frame> {
95100

96101
template<typename F = Frame,
97102
typename = std::enable_if_t<base::is_serializable_v<F>>>
98-
static not_null<std::unique_ptr<DiscreteTrajectory>> ReadFromMessage(
103+
static not_null<std::unique_ptr<DiscreteTrajectory2>> ReadFromMessage(
99104
serialization::DiscreteTrajectory const& message,
100-
std::vector<DiscreteTrajectory<Frame>**> const& tracked);
105+
std::vector<DiscreteTrajectory2**> const& tracked);
101106

102107
private:
103108
using Segments = internal_discrete_trajectory_types::Segments<Frame>;
@@ -107,8 +112,7 @@ class DiscreteTrajectory2 : public Trajectory<Frame> {
107112

108113
} // namespace internal_discrete_trajectory
109114

110-
template<typename Frame>
111-
using DiscreteTrajectory2 = internal_discrete_trajectory::DiscreteTrajectory2;
115+
using internal_discrete_trajectory::DiscreteTrajectory2;
112116

113117
} // namespace physics
114118
} // namespace principia

physics/discrete_trajectory_iterator.hpp

+39-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <optional>
4+
35
#include "absl/container/btree_map.h"
46
#include "geometry/named_quantities.hpp"
57
#include "physics/degrees_of_freedom.hpp"
@@ -27,14 +29,46 @@ class DiscreteTrajectoryIterator {
2729
DiscreteTrajectoryIterator operator++(int);
2830
DiscreteTrajectoryIterator operator--(int);
2931

30-
typename DiscreteTrajectory<Frame>::value_type const& operator*() const;
31-
typename DiscreteTrajectory<Frame>::value_type const* operator->() const;
32+
typename
33+
internal_discrete_trajectory_types::Timeline<Frame>::value_type const&
34+
operator*() const;
35+
typename
36+
internal_discrete_trajectory_types::Timeline<Frame>::value_type const*
37+
operator->() const;
38+
39+
bool operator==(DiscreteTrajectoryIterator const& other) const;
40+
bool operator!=(DiscreteTrajectoryIterator const& other) const;
3241

3342
private:
3443
using Timeline = internal_discrete_trajectory_types::Timeline<Frame>;
3544

45+
// Optional because we cannot construct a point iterator in the end segment.
46+
using OptionalTimelineConstIterator =
47+
std::optional<typename Timeline::const_iterator>;
48+
49+
DiscreteTrajectoryIterator(DiscreteTrajectorySegmentIterator<Frame> segment,
50+
OptionalTimelineConstIterator point);
51+
52+
static bool is_at_end(OptionalTimelineConstIterator point);
53+
54+
static typename Timeline::const_iterator& iterator(
55+
OptionalTimelineConstIterator& point);
56+
static typename Timeline::const_iterator const& iterator(
57+
OptionalTimelineConstIterator const& point);
58+
59+
// |point_| is always an iterator in the timeline of the segment denoted by
60+
// |segment_|. When |segment_| is at the end of its list, |point_| is
61+
// nullopt. It is possible to have repeated times in a segment or across
62+
// segments and the iterator will skip them, so that they will appear as a
63+
// single point to clients.
3664
DiscreteTrajectorySegmentIterator<Frame> segment_;
37-
Timeline::const_iterator point_;
65+
OptionalTimelineConstIterator point_;
66+
67+
// The last time that was seen by the iterator. Used to skip over repeated
68+
// times.
69+
std::optional<Instant> previous_time_;
70+
71+
friend class DiscreteTrajectoryIteratorTest;
3872
};
3973

4074
} // namespace internal_discrete_trajectory_iterator
@@ -43,3 +77,5 @@ using internal_discrete_trajectory_iterator::DiscreteTrajectoryIterator;
4377

4478
} // namespace physics
4579
} // namespace principia
80+
81+
#include "physics/discrete_trajectory_iterator_body.hpp"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#pragma once
2+
3+
#include "physics/discrete_trajectory_iterator.hpp"
4+
5+
#include "geometry/named_quantities.hpp"
6+
7+
namespace principia {
8+
namespace physics {
9+
namespace internal_discrete_trajectory_iterator {
10+
11+
using geometry::Instant;
12+
13+
template<typename Frame>
14+
DiscreteTrajectoryIterator<Frame>&
15+
DiscreteTrajectoryIterator<Frame>::operator++() {
16+
CHECK(!is_at_end(point_));
17+
auto& point = iterator(point_);
18+
for (;;) {
19+
if (point == --segment_->timeline_end()) {
20+
++segment_;
21+
if (segment_ == segment_.end()) {
22+
point_.reset();
23+
break;
24+
} else {
25+
point = segment_->timeline_begin();
26+
}
27+
} else {
28+
++point;
29+
}
30+
if (point->first != previous_time_) {
31+
previous_time_ = point->first;
32+
break;
33+
}
34+
}
35+
return *this;
36+
}
37+
38+
template<typename Frame>
39+
DiscreteTrajectoryIterator<Frame>&
40+
DiscreteTrajectoryIterator<Frame>::operator--() {
41+
if (is_at_end(point_)) {
42+
segment_ = --segment_.end();
43+
point_ = --segment_->timeline_end();
44+
} else {
45+
auto& point = iterator(point_);
46+
for (;;) {
47+
if (point == segment_->timeline_begin()) {
48+
CHECK(segment_ != segment_.begin());
49+
--segment_;
50+
point = --segment_->timeline_end();
51+
} else {
52+
--point;
53+
}
54+
if (point->first != previous_time_) {
55+
previous_time_ = point->first;
56+
break;
57+
}
58+
}
59+
}
60+
return *this;
61+
}
62+
63+
template<typename Frame>
64+
DiscreteTrajectoryIterator<Frame>
65+
DiscreteTrajectoryIterator<Frame>::operator++(int) { // NOLINT
66+
auto const initial = *this;
67+
++*this;
68+
return initial;
69+
}
70+
71+
template<typename Frame>
72+
DiscreteTrajectoryIterator<Frame>
73+
DiscreteTrajectoryIterator<Frame>::operator--(int) { // NOLINT
74+
auto const initial = *this;
75+
--*this;
76+
return initial;
77+
}
78+
79+
template<typename Frame>
80+
typename internal_discrete_trajectory_types::Timeline<Frame>::value_type const&
81+
DiscreteTrajectoryIterator<Frame>::operator*() const {
82+
CHECK(!is_at_end(point_));
83+
return *iterator(point_);
84+
}
85+
86+
template<typename Frame>
87+
typename internal_discrete_trajectory_types::Timeline<Frame>::value_type const*
88+
DiscreteTrajectoryIterator<Frame>::operator->() const {
89+
CHECK(!is_at_end(point_));
90+
return &*iterator(point_);
91+
}
92+
93+
template<typename Frame>
94+
bool DiscreteTrajectoryIterator<Frame>::operator==(
95+
DiscreteTrajectoryIterator const& other) const {
96+
if (is_at_end(point_)) {
97+
return segment_ == other.segment_ && is_at_end(other.point_);
98+
} else if (is_at_end(other.point_)) {
99+
return false;
100+
} else {
101+
return iterator(point_)->first == iterator(other.point_)->first;
102+
}
103+
}
104+
105+
template<typename Frame>
106+
bool DiscreteTrajectoryIterator<Frame>::operator!=(
107+
DiscreteTrajectoryIterator const& other) const {
108+
return !operator==(other);
109+
}
110+
111+
template<typename Frame>
112+
DiscreteTrajectoryIterator<Frame>::DiscreteTrajectoryIterator(
113+
DiscreteTrajectorySegmentIterator<Frame> const segment,
114+
OptionalTimelineConstIterator const point)
115+
: segment_(segment),
116+
point_(point) {}
117+
118+
template<typename Frame>
119+
bool DiscreteTrajectoryIterator<Frame>::is_at_end(
120+
OptionalTimelineConstIterator const point) {
121+
return !point.has_value();
122+
}
123+
124+
template<typename Frame>
125+
typename DiscreteTrajectoryIterator<Frame>::Timeline::const_iterator&
126+
DiscreteTrajectoryIterator<Frame>::iterator(
127+
OptionalTimelineConstIterator& point) {
128+
DCHECK(point.has_value());
129+
return point.value();
130+
}
131+
132+
template<typename Frame>
133+
typename DiscreteTrajectoryIterator<Frame>::Timeline::const_iterator const&
134+
DiscreteTrajectoryIterator<Frame>::iterator(
135+
OptionalTimelineConstIterator const& point) {
136+
DCHECK(point.has_value());
137+
return point.value();
138+
}
139+
140+
} // namespace internal_discrete_trajectory_iterator
141+
} // namespace physics
142+
} // namespace principia

0 commit comments

Comments
 (0)