3 XCSoar Glide Computer - http://www.xcsoar.org/
4 Copyright (C) 2000-2013 The XCSoar Project
5 A detailed list of copyright holders can be found in the file "AUTHORS".
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "test_debug.hpp"
25 #include "Waypoint/WaypointVisitor.hpp"
26 #include "Waypoint/Waypoints.hpp"
27 #include "Geo/GeoVector.hpp"
32 class WaypointPredicateCounter
: public WaypointVisitor
35 typedef std::function
<bool(const Waypoint
&wp
)> Predicate
;
42 WaypointPredicateCounter(const Predicate
&_predicate
)
43 :predicate(_predicate
), count(0) {}
45 virtual void Visit(const Waypoint
&wp
) {
50 unsigned GetCounter() const {
56 AddSpiralWaypoints(Waypoints
&waypoints
,
57 const GeoPoint
¢er
= GeoPoint(Angle::Degrees(51.4),
58 Angle::Degrees(7.85)),
59 Angle angle_start
= Angle::Degrees(0),
60 Angle angle_step
= Angle::Degrees(15),
61 fixed distance_start
= fixed(0),
62 fixed distance_step
= fixed(1000),
63 fixed distance_max
= fixed(150000))
65 assert(positive(distance_step
));
67 for (unsigned i
= 0;; ++i
) {
69 vector
.distance
= distance_start
+ distance_step
* i
;
70 if (vector
.distance
> distance_max
)
73 vector
.bearing
= angle_start
+ angle_step
* i
;
76 waypoint
.location
= vector
.EndPoint(center
);
77 waypoint
.original_id
= i
;
78 waypoint
.elevation
= fixed(i
* 10 - 500);
80 StaticString
<256> buffer
;
83 buffer
= _T("Airfield");
84 waypoint
.type
= Waypoint::Type::AIRFIELD
;
85 } else if (i
% 3 == 0) {
87 waypoint
.type
= Waypoint::Type::OUTLANDING
;
89 buffer
= _T("Waypoint");
91 buffer
.AppendFormat(_T(" #%d"), i
+ 1);
92 waypoint
.name
= buffer
;
94 waypoints
.Append(std::move(waypoint
));
101 TestLookups(const Waypoints
&waypoints
, const GeoPoint
¢er
)
103 const Waypoint
*waypoint
;
105 ok1((waypoint
= waypoints
.LookupId(0)) == NULL
);
106 ok1((waypoint
= waypoints
.LookupId(1)) != NULL
);
107 ok1(waypoint
->original_id
== 0);
108 ok1((waypoint
= waypoints
.LookupId(151)) != NULL
);
109 ok1(waypoint
->original_id
== 150);
110 ok1((waypoint
= waypoints
.LookupId(152)) == NULL
);
111 ok1((waypoint
= waypoints
.LookupId(160)) == NULL
);
113 ok1((waypoint
= waypoints
.LookupLocation(center
, fixed(0))) != NULL
);
114 ok1(waypoint
->original_id
== 0);
116 ok1((waypoint
= waypoints
.LookupName(_T("Waypoint #5"))) != NULL
);
117 ok1(waypoint
->original_id
== 4);
119 ok1((waypoint
= waypoints
.LookupLocation(waypoint
->location
, fixed(10000))) != NULL
);
120 ok1(waypoint
->original_id
== 4);
128 BeginsWith(const TCHAR
*_prefix
):prefix(_prefix
) {}
130 bool operator()(const Waypoint
&waypoint
) {
131 return StringStartsWith(waypoint
.name
.c_str(), prefix
);
136 TestNamePrefixVisitor(const Waypoints
&waypoints
, const TCHAR
*prefix
,
137 unsigned expected_results
)
139 WaypointPredicateCounter::Predicate predicate
= BeginsWith(prefix
);
140 WaypointPredicateCounter
prefix_counter(predicate
);
141 waypoints
.VisitNamePrefix(prefix
, prefix_counter
);
142 ok1(prefix_counter
.GetCounter() == expected_results
);
146 TestNamePrefixVisitor(const Waypoints
&waypoints
)
148 TestNamePrefixVisitor(waypoints
, _T(""), 151);
149 TestNamePrefixVisitor(waypoints
, _T("Foo"), 0);
150 TestNamePrefixVisitor(waypoints
, _T("a"), 0);
151 TestNamePrefixVisitor(waypoints
, _T("A"), 22);
152 TestNamePrefixVisitor(waypoints
, _T("Air"), 22);
153 TestNamePrefixVisitor(waypoints
, _T("Field"), 51 - 8);
162 CloserThan(fixed _distance
, const GeoPoint
&_location
)
163 :distance(_distance
), location(_location
) {}
165 bool operator()(const Waypoint
&waypoint
) {
166 return location
.Distance(waypoint
.location
) < distance
;
171 TestRangeVisitor(const Waypoints
&waypoints
, const GeoPoint
&location
,
172 fixed distance
, unsigned expected_results
)
174 WaypointPredicateCounter::Predicate predicate
= CloserThan(distance
, location
);
175 WaypointPredicateCounter
distance_counter(predicate
);
176 waypoints
.VisitWithinRange(location
, distance
, distance_counter
);
177 ok1(distance_counter
.GetCounter() == expected_results
);
181 TestRangeVisitor(const Waypoints
&waypoints
, const GeoPoint
¢er
)
183 TestRangeVisitor(waypoints
, center
, fixed(1), 1);
184 TestRangeVisitor(waypoints
, center
, fixed(999), 1);
185 TestRangeVisitor(waypoints
, center
, fixed(1300), 2);
186 TestRangeVisitor(waypoints
, center
, fixed(10500), 11);
187 TestRangeVisitor(waypoints
, center
, fixed(1000000), 151);
191 OriginalIDAbove5(const Waypoint
&waypoint
) {
192 return waypoint
.original_id
> 5;
196 TestGetNearest(const Waypoints
&waypoints
, const GeoPoint
¢er
)
198 const Waypoint
*waypoint
;
199 GeoPoint near
= GeoVector(fixed(250), Angle::Degrees(15)).EndPoint(center
);
200 GeoPoint far
= GeoVector(fixed(750), Angle::Degrees(15)).EndPoint(center
);
201 GeoPoint further
= GeoVector(fixed(4200), Angle::Degrees(48)).EndPoint(center
);
203 ok1((waypoint
= waypoints
.GetNearest(center
, fixed(1))) != NULL
);
204 ok1(waypoint
->original_id
== 0);
206 ok1((waypoint
= waypoints
.GetNearest(center
, fixed(10000))) != NULL
);
207 ok1(waypoint
->original_id
== 0);
209 ok1((waypoint
= waypoints
.GetNearest(near
, fixed(1))) == NULL
);
211 ok1((waypoint
= waypoints
.GetNearest(near
, fixed(10000))) != NULL
);
212 ok1(waypoint
->original_id
== 0);
214 ok1((waypoint
= waypoints
.GetNearest(far
, fixed(1))) == NULL
);
216 ok1((waypoint
= waypoints
.GetNearest(far
, fixed(10000))) != NULL
);
217 ok1(waypoint
->original_id
== 1);
219 ok1((waypoint
= waypoints
.GetNearestLandable(center
, fixed(1))) != NULL
);
220 ok1(waypoint
->original_id
== 0);
222 ok1((waypoint
= waypoints
.GetNearestLandable(center
, fixed(10000))) != NULL
);
223 ok1(waypoint
->original_id
== 0);
225 ok1((waypoint
= waypoints
.GetNearestLandable(further
, fixed(1))) == NULL
);
227 ok1((waypoint
= waypoints
.GetNearestLandable(further
, fixed(10000))) != NULL
);
228 ok1(waypoint
->original_id
== 3);
230 ok1((waypoint
= waypoints
.GetNearestIf(center
, fixed(1), OriginalIDAbove5
)) == NULL
);
232 ok1((waypoint
= waypoints
.GetNearestIf(center
, fixed(10000), OriginalIDAbove5
)) != NULL
);
233 ok1(waypoint
->original_id
== 6);
237 TestIterator(const Waypoints
&waypoints
)
240 for (auto it
= waypoints
.begin(), end
= waypoints
.end(); it
!= end
; ++it
)
247 TestCopy(Waypoints
& waypoints
)
249 const Waypoint
*wp
= waypoints
.LookupId(5);
253 unsigned size_old
= waypoints
.size();
254 Waypoint wp_copy
= *wp
;
255 wp_copy
.id
= waypoints
.size() + 1;
256 waypoints
.Append(std::move(wp_copy
));
257 waypoints
.Optimise();
258 unsigned size_new
= waypoints
.size();
259 return (size_new
== size_old
+ 1);
263 TestErase(Waypoints
& waypoints
, unsigned id
)
265 waypoints
.Optimise();
267 wp
= waypoints
.LookupId(id
);
271 waypoints
.Erase(*wp
);
272 waypoints
.Optimise();
274 wp
= waypoints
.LookupId(id
);
279 TestReplace(Waypoints
& waypoints
, unsigned id
)
282 wp
= waypoints
.LookupId(id
);
286 tstring oldName
= wp
->name
;
289 copy
.name
= _T("Fred");
290 waypoints
.Replace(*wp
, copy
);
291 waypoints
.Optimise();
293 wp
= waypoints
.LookupId(id
);
294 return wp
!= NULL
&& wp
->name
!= oldName
&& wp
->name
== _T("Fred");
298 main(int argc
, char** argv
)
300 if (!ParseArgs(argc
, argv
))
306 GeoPoint
center(Angle::Degrees(51.4), Angle::Degrees(7.85));
308 // AddSpiralWaypoints creates 151 waypoints from
309 // 0km to 150km distance in 1km steps
310 AddSpiralWaypoints(waypoints
, center
);
312 ok1(!waypoints
.IsEmpty());
313 ok1(waypoints
.size() == 151);
315 TestLookups(waypoints
, center
);
316 TestNamePrefixVisitor(waypoints
);
317 TestRangeVisitor(waypoints
, center
);
318 TestGetNearest(waypoints
, center
);
319 TestIterator(waypoints
);
321 ok(TestCopy(waypoints
), "waypoint copy", 0);
322 ok(TestErase(waypoints
, 3), "waypoint erase", 0);
323 ok(TestReplace(waypoints
, 4), "waypoint replace", 0);
327 ok1(waypoints
.IsEmpty());
328 ok1(waypoints
.size() == 0);
330 return exit_status();