@@ -91,17 +91,21 @@ namespace dsf::mdt {
9191 tbb::concurrent_set<Id> to_split;
9292
9393 // Returns true if speed between two points is below max_speed_kph
94- auto check_max_speed = [](PointsCluster const & currentCluster,
95- PointsCluster const & previousCluster,
96- double const max_speed_kph) {
94+ auto check_max_speed = [&max_speed_kph](PointsCluster const & currentCluster,
95+ PointsCluster const & previousCluster) {
9796 auto const distance_km = dsf::geometry::haversine_km (currentCluster.centroid (),
9897 previousCluster.centroid ());
9998 auto const current_time =
10099 (currentCluster.lastTimestamp () + currentCluster.firstTimestamp ()) * 0.5 ;
101100 auto const previous_time =
102101 (previousCluster.lastTimestamp () + previousCluster.firstTimestamp ()) * 0.5 ;
103- if (current_time <= previous_time) {
104- spdlog::warn (
102+ if (current_time < previous_time) {
103+ // Should never happen if data is clean
104+ throw std::runtime_error (
105+ " Timestamps are not in increasing order within the trajectory." );
106+ }
107+ if (current_time == previous_time) {
108+ spdlog::debug (
105109 " Non-increasing timestamps detected. Skipping speed check for these points." );
106110 return true ;
107111 }
@@ -110,18 +114,21 @@ namespace dsf::mdt {
110114 return speed_kph <= max_speed_kph;
111115 };
112116 // Returns true if cluster duration is below min_duration_min
113- auto check_min_duration = [](dsf::mdt::PointsCluster const & cluster,
114- std::time_t const min_duration_min) {
115- return cluster.duration () < min_duration_min * SECONDS_IN_MINUTE;
116- };
117+ auto check_min_duration =
118+ [&min_duration_min](dsf::mdt::PointsCluster const & cluster) {
119+ if (!min_duration_min.has_value ()) {
120+ return true ;
121+ }
122+ return cluster.duration () < min_duration_min.value () * SECONDS_IN_MINUTE;
123+ };
117124
118125 tbb::parallel_for_each (
119126 m_trajectories.begin (),
120127 m_trajectories.end (),
121128 [&to_remove,
122129 &to_split,
123- check_max_speed,
124- check_min_duration,
130+ & check_max_speed,
131+ & check_min_duration,
125132 min_points_per_trajectory,
126133 cluster_radius_km,
127134 max_speed_kph,
@@ -142,16 +149,16 @@ namespace dsf::mdt {
142149 return ;
143150 }
144151 auto const & points{trajectory.points ()};
145- for (std::size_t i = 0 ; i < points.size (); ++i) {
152+ auto const nPoints = points.size ();
153+ for (std::size_t i = 0 ; i < nPoints;) {
146154 auto const & currentCluster = points[i];
147- if (min_duration_min.has_value () &&
148- !check_min_duration (currentCluster, min_duration_min.value ())) {
155+ if (!check_min_duration (currentCluster)) {
149156 to_split.insert (uid);
150157 return ;
151158 }
152- if (i > 0 ) {
153- auto const & previousCluster = points[i - 1 ];
154- if (!check_max_speed (currentCluster, previousCluster, max_speed_kph )) {
159+ if (++i < nPoints ) {
160+ auto const & nextCluster = points[i];
161+ if (!check_max_speed (nextCluster, currentCluster )) {
155162 to_split.insert (uid);
156163 return ;
157164 }
@@ -169,8 +176,10 @@ namespace dsf::mdt {
169176 return to_remove.contains (pair.first );
170177 });
171178
172- spdlog::info (" Splitting {} trajectories based on minimum duration requirement." ,
173- to_split.size ());
179+ spdlog::info (
180+ " Splitting {} trajectories based on minimum duration or maximum speed "
181+ " requirements." ,
182+ to_split.size ());
174183 for (auto const & uid : to_split) {
175184 // Extract the trajectory
176185 if (!m_trajectories.contains (uid)) {
@@ -182,18 +191,19 @@ namespace dsf::mdt {
182191
183192 Trajectory newTrajectory;
184193 auto const & points{originalTrajectory.points ()};
185- for (std::size_t i = 0 ; i < points.size (); ++i) {
194+ auto const nPoints = points.size ();
195+ for (std::size_t i = 0 ; i < nPoints;) {
186196 auto const & currentCluster = points[i];
187197 newTrajectory.addCluster (currentCluster);
188198
189199 bool bShouldSplit = false ;
190200
191- if (i > 0 ) {
192- auto const & previousCluster = points[i - 1 ];
193- bShouldSplit = !check_max_speed (currentCluster, previousCluster, max_speed_kph );
201+ if (++i < nPoints ) {
202+ auto const & nextCluster = points[i];
203+ bShouldSplit = !check_max_speed (nextCluster, currentCluster );
194204 }
195- if (min_duration_min. has_value () && !bShouldSplit) {
196- bShouldSplit = !check_min_duration (currentCluster, min_duration_min. value () );
205+ if (!bShouldSplit) {
206+ bShouldSplit = !check_min_duration (currentCluster);
197207 }
198208 // If constraint violated (max speed or min duration) - finalize current trajectory and start a new one
199209 if (bShouldSplit && !newTrajectory.empty ()) {
0 commit comments