22
22
23
23
static constexpr bool TRACKF_DBG = false ;
24
24
25
+ #include < algorithm> // for for_each
25
26
#include < cassert> // for assert
26
27
#include < cmath> // for nan
27
28
#include < cstdio> // for printf
@@ -195,10 +196,6 @@ void TrackFilter::trackfilter_fill_track_list_cb(const route_head* track) /* ca
195
196
fatal (FatalMsg () << " track: name option is an invalid expression." );
196
197
}
197
198
if (!regex.match (track->rte_name ).hasMatch ()) {
198
- foreach (Waypoint* wpt, track->waypoint_list ) {
199
- track_del_wpt (const_cast <route_head*>(track), wpt);
200
- delete wpt;
201
- }
202
199
track_del_head (const_cast <route_head*>(track));
203
200
return ;
204
201
}
@@ -329,11 +326,20 @@ void TrackFilter::trackfilter_pack()
329
326
330
327
route_head* master = track_list.first ();
331
328
329
+ if (!master->waypoint_list .empty ()) {
330
+ std::for_each (std::next (master->waypoint_list .cbegin ()), master->waypoint_list .cend (),
331
+ [](Waypoint* wpt)->void {wpt->wpt_flags .new_trkseg = 0 ;});
332
+ }
333
+
332
334
while (track_list.size () > 1 ) {
333
335
route_head* curr = track_list.takeAt (1 );
334
336
335
- foreach (Waypoint* wpt, curr->waypoint_list ) {
336
- track_del_wpt (curr, wpt);
337
+ // Steal all the waypoints
338
+ WaypointList curr_wpts;
339
+ track_swap_wpts (curr, curr_wpts);
340
+ // And add them to the master
341
+ foreach (Waypoint* wpt, curr_wpts) {
342
+ wpt->wpt_flags .new_trkseg = 0 ;
337
343
track_add_wpt (master, wpt);
338
344
}
339
345
track_del_head (curr);
@@ -357,15 +363,16 @@ void TrackFilter::trackfilter_merge()
357
363
auto it = track_list.begin ();
358
364
while (it != track_list.end ()) { /* put all points into temp buffer */
359
365
route_head* track = *it;
360
- foreach (Waypoint* wpt, track->waypoint_list ) {
361
- track_del_wpt (track, wpt); /* copies any new_trkseg flag forward, and clears new_trkseg flag. */
366
+ // steal all the wpts
367
+ WaypointList wpts;
368
+ track_swap_wpts (track, wpts);
369
+ // add them to the buff or delete them
370
+ foreach (Waypoint* wpt, wpts) {
362
371
if (wpt->creation_time .isValid ()) {
363
372
// we will put the merged points in one track segment,
364
373
// as it isn't clear how track segments in the original tracks
365
374
// should relate to the merged track.
366
- // track_del_wpt cleared new_trkseg flag for wpt.
367
- // track_add_wpt will set new_trkseg for the first point
368
- // added to a track.
375
+ wpt->wpt_flags .new_trkseg = 0 ;
369
376
buff.append (wpt);
370
377
} else {
371
378
delete wpt;
@@ -416,16 +423,13 @@ void TrackFilter::trackfilter_split()
416
423
fatal (MYNAME " -split: Cannot split more than one track, please pack (or merge) before!\n " );
417
424
} else if (!track_list.isEmpty ()) {
418
425
route_head* master = track_list.first ();
419
- int count = master->rte_waypt_ct ();
426
+ if (master->rte_waypt_ct () <= 1 ) {
427
+ return ;
428
+ }
420
429
421
- int i, j;
422
430
double interval = -1 ; /* seconds */
423
431
double distance = -1 ; /* meters */
424
432
425
- if (count <= 1 ) {
426
- return ;
427
- }
428
-
429
433
/* check additional options */
430
434
431
435
opt_interval = (opt_split && (strlen (opt_split) > 0 ) && (0 != strcmp (opt_split, TRACKFILTER_SPLIT_OPTION)));
@@ -495,36 +499,41 @@ void TrackFilter::trackfilter_split()
495
499
}
496
500
}
497
501
498
- QList<Waypoint*> buff;
502
+ // steal all the waypoints
503
+ WaypointList buff;
504
+ track_swap_wpts (master, buff);
505
+ assert (!buff.empty ()); // enforced above
499
506
500
- foreach (Waypoint* wpt, master->waypoint_list ) {
501
- buff.append (wpt);
502
- }
507
+ trackfilter_split_init_rte_name (master, buff.front ()->GetCreationTime ());
503
508
504
- trackfilter_split_init_rte_name (master, buff. at ( 0 )-> GetCreationTime ());
509
+ route_head* curr = master; /* will be reset by first new track */
505
510
506
- route_head* curr = nullptr ; /* will be set by first new track */
511
+ // add the first waypoint to the first track
512
+ track_add_wpt (curr, buff.front ());
513
+ // and add subsequent waypoints to the first track or a new track
514
+ for (auto prev_it = buff.cbegin (), it = std::next (buff.cbegin ()); it != buff.cend (); ++prev_it, ++it) {
515
+ Waypoint* prev_wpt = *prev_it;
516
+ Waypoint* wpt = *it;
507
517
508
- for (i=0 , j=1 ; j<count; i++, j++) {
509
518
bool new_track_flag;
510
519
511
520
if ((opt_interval == 0 ) && (opt_distance == 0 )) {
512
- // FIXME: This whole function needs to be reconsidered for arbitrary time.
513
- new_track_flag = buff. at (i) ->GetCreationTime ().toLocalTime ().date () !=
514
- buff. at (j) ->GetCreationTime ().toLocalTime ().date ();
521
+ // FIXME: This whole function needs to be reconsidered for arbitrary time.
522
+ new_track_flag = prev_wpt ->GetCreationTime ().toLocalTime ().date () !=
523
+ wpt ->GetCreationTime ().toLocalTime ().date ();
515
524
if constexpr (TRACKF_DBG) {
516
525
if (new_track_flag) {
517
- printf (MYNAME " : new day %s\n " , qPrintable (buff. at (j) ->GetCreationTime ().toLocalTime ().date ().toString (Qt::ISODate)));
526
+ printf (MYNAME " : new day %s\n " , qPrintable (wpt ->GetCreationTime ().toLocalTime ().date ().toString (Qt::ISODate)));
518
527
}
519
528
}
520
529
} else {
521
530
new_track_flag = true ;
522
531
523
532
if (distance > 0 ) {
524
- double rt1 = RAD (buff. at (i) ->latitude );
525
- double rn1 = RAD (buff. at (i) ->longitude );
526
- double rt2 = RAD (buff. at (j) ->latitude );
527
- double rn2 = RAD (buff. at (j) ->longitude );
533
+ double rt1 = RAD (prev_wpt ->latitude );
534
+ double rn1 = RAD (prev_wpt ->longitude );
535
+ double rt2 = RAD (wpt ->latitude );
536
+ double rn2 = RAD (wpt ->longitude );
528
537
double curdist = gcdist (rt1, rn1, rt2, rn2);
529
538
curdist = radtometers (curdist);
530
539
if (curdist <= distance) {
@@ -535,7 +544,7 @@ void TrackFilter::trackfilter_split()
535
544
}
536
545
537
546
if (interval > 0 ) {
538
- double tr_interval = 0.001 * buff. at (i) ->GetCreationTime ().msecsTo (buff. at (j) ->GetCreationTime ());
547
+ double tr_interval = 0.001 * prev_wpt ->GetCreationTime ().msecsTo (wpt ->GetCreationTime ());
539
548
if (tr_interval <= interval) {
540
549
new_track_flag = false ;
541
550
} else if constexpr (TRACKF_DBG) {
@@ -549,14 +558,12 @@ void TrackFilter::trackfilter_split()
549
558
printf (MYNAME " : splitting new track\n " );
550
559
}
551
560
curr = new route_head;
552
- trackfilter_split_init_rte_name (curr, buff. at (j) ->GetCreationTime ());
561
+ trackfilter_split_init_rte_name (curr, wpt ->GetCreationTime ());
553
562
track_add_head (curr);
554
563
track_list.append (curr);
555
564
}
556
- if (curr != nullptr ) {
557
- track_del_wpt (master, buff.at (j));
558
- track_add_wpt (curr, buff.at (j));
559
- }
565
+ wpt->wpt_flags .new_trkseg = 0 ;
566
+ track_add_wpt (curr, wpt);
560
567
}
561
568
}
562
569
}
@@ -728,10 +735,11 @@ void TrackFilter::trackfilter_range()
728
735
}
729
736
730
737
if (!inside) {
731
- track_del_wpt (track, wpt);
732
- delete wpt;
738
+ wpt->wpt_flags .marked_for_deletion = 1 ;
733
739
}
734
740
}
741
+ // delete marked wpts
742
+ track_del_marked_wpts (track);
735
743
736
744
if (track->rte_waypt_empty ()) {
737
745
track_del_head (track);
@@ -756,12 +764,17 @@ void TrackFilter::trackfilter_seg2trk()
756
764
QList<route_head*> new_track_list;
757
765
for (auto * src : qAsConst (track_list)) {
758
766
new_track_list.append (src);
759
- route_head* dest = nullptr ;
767
+ route_head* dest = src ;
760
768
route_head* insert_point = src;
761
769
int trk_seg_num = 1 ;
762
770
bool first = true ;
763
771
764
- foreach (Waypoint* wpt, src->waypoint_list ) {
772
+ // steal all the waypoints from the src
773
+ WaypointList src_wpts;
774
+ track_swap_wpts (src, src_wpts);
775
+
776
+ // and add them back to the original or a new route_head.
777
+ foreach (Waypoint* wpt, src_wpts) {
765
778
if (wpt->wpt_flags .new_trkseg && !first) {
766
779
767
780
dest = new route_head;
@@ -778,18 +791,7 @@ void TrackFilter::trackfilter_seg2trk()
778
791
new_track_list.append (dest);
779
792
}
780
793
781
- /* If we found a track separator, transfer from original to
782
- * new track. We have to reset new_trkseg temporarily to
783
- * prevent track_del_wpt() from copying it to the next track
784
- * point.
785
- */
786
- if (dest) {
787
- unsigned orig_new_trkseg = wpt->wpt_flags .new_trkseg ;
788
- wpt->wpt_flags .new_trkseg = 0 ;
789
- track_del_wpt (src, wpt);
790
- wpt->wpt_flags .new_trkseg = orig_new_trkseg;
791
- track_add_wpt (dest, wpt);
792
- }
794
+ track_add_wpt (dest, wpt);
793
795
first = false ;
794
796
}
795
797
}
@@ -809,13 +811,12 @@ void TrackFilter::trackfilter_trk2seg()
809
811
while (track_list.size () > 1 ) {
810
812
route_head* curr = track_list.takeAt (1 );
811
813
814
+ // steal all the wpts
815
+ WaypointList curr_wpts;
816
+ track_swap_wpts (curr, curr_wpts);
817
+ // and add them to the master
812
818
bool first = true ;
813
- foreach (Waypoint* wpt, curr->waypoint_list ) {
814
-
815
- unsigned orig_new_trkseg = wpt->wpt_flags .new_trkseg ;
816
- wpt->wpt_flags .new_trkseg = 0 ;
817
- track_del_wpt (curr, wpt);
818
- wpt->wpt_flags .new_trkseg = orig_new_trkseg;
819
+ foreach (Waypoint* wpt, curr_wpts) {
819
820
track_add_wpt (master, wpt);
820
821
if (first) {
821
822
wpt->wpt_flags .new_trkseg = 1 ;
@@ -888,18 +889,11 @@ void TrackFilter::trackfilter_faketime()
888
889
889
890
bool TrackFilter::trackfilter_points_are_same (const Waypoint* wpta, const Waypoint* wptb)
890
891
{
891
- // We use a simpler (non great circle) test for lat/lon here as this
892
- // is used for keeping the 'bookends' of non-moving points.
893
- //
894
- // Latitude spacing is about 27 feet per .00001 degree.
895
- // Longitude spacing varies, but the reality is that anything closer
896
- // than 27 feet does little but clutter the output.
897
- // As this is about the limit of consumer grade GPS, it seems a
898
- // reasonable tradeoff.
899
-
900
892
return
901
- std::abs (wpta->latitude - wptb->latitude ) < .00001 &&
902
- std::abs (wpta->longitude - wptb->longitude ) < .00001 &&
893
+ radtometers (gcdist (RAD (wpta->latitude ),
894
+ RAD (wpta->longitude ),
895
+ RAD (wptb->latitude ),
896
+ RAD (wptb->longitude ))) < kDistanceLimit &&
903
897
std::abs (wpta->altitude - wptb->altitude ) < 20 &&
904
898
wpta->courses_equal (*wptb) &&
905
899
wpta->speeds_equal (*wptb) &&
@@ -911,46 +905,45 @@ bool TrackFilter::trackfilter_points_are_same(const Waypoint* wpta, const Waypoi
911
905
void TrackFilter::trackfilter_segment_head (const route_head* rte)
912
906
{
913
907
double avg_dist = 0 ;
914
- int index = 0 ;
915
908
Waypoint* prev_wpt = nullptr ;
916
- // Consider tossing trackpoints closer than this in radians.
917
- // (Empirically determined; It's a few dozen feet.)
918
- const double ktoo_close = 0.000005 ;
919
909
920
- const auto wptlist = rte->waypoint_list ; // track_del_wpt will modify rte->waypoint_list
910
+ const auto wptlist = rte->waypoint_list ;
921
911
for (auto it = wptlist.cbegin (); it != wptlist.cend (); ++it) {
922
912
auto * wpt = *it;
923
- if (index > 0 ) {
924
- double cur_dist = gcdist (RAD (prev_wpt->latitude ),
925
- RAD (prev_wpt->longitude ),
926
- RAD (wpt->latitude ),
927
- RAD (wpt->longitude ));
928
- // Denoise points that are on top of each other.
929
- if (avg_dist == 0 ) {
930
- avg_dist = cur_dist;
931
- }
932
-
933
- if (cur_dist < ktoo_close) {
934
- if (wpt != wptlist.back ()) {
935
- auto * next_wpt = *std::next (it);
913
+ if (it != wptlist.cbegin ()) {
914
+ double cur_dist = radtometers (gcdist (RAD (prev_wpt->latitude ),
915
+ RAD (prev_wpt->longitude ),
916
+ RAD (wpt->latitude ),
917
+ RAD (wpt->longitude )));
918
+
919
+ // Denoise points that are on top of each other,
920
+ // keeping the first and last of the group.
921
+ if (cur_dist < kDistanceLimit ) {
922
+ if (auto next_it = std::next (it); next_it != wptlist.cend ()) {
923
+ auto * next_wpt = *next_it;
936
924
if (trackfilter_points_are_same (prev_wpt, wpt) &&
937
925
trackfilter_points_are_same (wpt, next_wpt)) {
938
- track_del_wpt (const_cast <route_head*>(rte), wpt);
939
- delete wpt;
940
- continue ;
926
+ wpt->wpt_flags .marked_for_deletion = 1 ;
927
+ continue ; // without updating prev_wpt, the first in the group.
941
928
}
942
929
}
943
930
}
944
- if (cur_dist > .001 && cur_dist > 1.2 * avg_dist) {
945
- avg_dist = cur_dist = 0 ;
931
+
932
+ if (avg_dist == 0 ) {
933
+ avg_dist = cur_dist;
934
+ }
935
+
936
+ if (cur_dist > 6378.14 && cur_dist > 1.2 * avg_dist) {
937
+ avg_dist = 0 ;
946
938
wpt->wpt_flags .new_trkseg = 1 ;
939
+ } else {
940
+ // Update weighted moving average;
941
+ avg_dist = (cur_dist + 4.0 * avg_dist) / 5.0 ;
947
942
}
948
- // Update weighted moving average;
949
- avg_dist = (cur_dist + 4.0 * avg_dist) / 5.0 ;
950
943
}
951
944
prev_wpt = wpt;
952
- index++;
953
945
}
946
+ track_del_marked_wpts (const_cast <route_head*>(rte));
954
947
}
955
948
956
949
/* ******************************************************************************
0 commit comments