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 "AirspacePrinting.hpp"
24 #include "Printing.hpp"
25 #include "harness_airspace.hpp"
26 #include "test_debug.hpp"
27 #include "Airspace/AirspaceIntersectionVisitor.hpp"
28 #include "Airspace/AirspaceNearestSort.hpp"
29 #include "Airspace/AirspaceSoonestSort.hpp"
30 #include "Geo/GeoVector.hpp"
31 #include "Formatter/AirspaceFormatter.hpp"
32 #include "OS/FileUtil.hpp"
39 airspace_random_properties(AbstractAirspace
& as
)
41 AirspaceClass Type
= (AirspaceClass
)(rand()%14);
42 AirspaceAltitude base
;
44 base
.altitude
= fixed(rand()%4000);
45 top
.altitude
= base
.altitude
+fixed(rand()%3000);
46 as
.SetProperties(_T("hello"), Type
, base
, top
);
50 bool test_airspace_extra(Airspaces
&airspaces
) {
51 // try adding a null polygon
54 std::vector
<GeoPoint
> pts
;
55 as
= new AirspacePolygon(pts
);
58 // try clearing now (we haven't called optimise())
64 void setup_airspaces(Airspaces
& airspaces
, const GeoPoint
& center
, const unsigned n
) {
65 std::ofstream
*fin
= NULL
;
68 Directory::Create(_T("output/results"));
69 fin
= new std::ofstream("output/results/res-bb-in.txt");
72 for (unsigned i
=0; i
<n
; i
++) {
76 c
.longitude
= Angle::Degrees(fixed((rand()%1200-600)/1000.0))+center
.longitude
;
77 c
.latitude
= Angle::Degrees(fixed((rand()%1200-600)/1000.0))+center
.latitude
;
78 fixed
radius(10000.0*(0.2+(rand()%12)/12.0));
79 as
= new AirspaceCircle(c
,radius
);
82 // just for testing, create a random polygon from a convex hull around
84 const unsigned num
= rand()%10+5;
86 c
.longitude
= Angle::Degrees(fixed((rand()%1200-600)/1000.0))+center
.longitude
;
87 c
.latitude
= Angle::Degrees(fixed((rand()%1200-600)/1000.0))+center
.latitude
;
89 std::vector
<GeoPoint
> pts
;
90 for (unsigned j
=0; j
<num
; j
++) {
92 p
.longitude
+= Angle::Degrees(fixed((rand()%200)/1000.0));
93 p
.latitude
+= Angle::Degrees(fixed((rand()%200)/1000.0));
96 as
= new AirspacePolygon(pts
,true);
98 airspace_random_properties(*as
);
106 // try inserting nothing
109 airspaces
.Optimise();
114 class AirspaceVisitorPrint final
: public AirspaceVisitor
{
116 const bool do_report
;
119 AirspaceVisitorPrint(const char *fname
, const bool _do_report
)
120 :do_report(_do_report
)
123 fout
= new std::ofstream(fname
);
127 ~AirspaceVisitorPrint() {
133 virtual void Visit(const AbstractAirspace
&as
) override
{
136 *fout
<< "# Name: " << as
.GetName()
137 << "Base: " << as
.GetBase()
138 << " Top: " << as
.GetTop()
145 class AirspaceIntersectionVisitorPrint final
146 : public AirspaceIntersectionVisitor
{
150 const bool do_report
;
151 const AircraftState m_state
;
152 const AirspaceAircraftPerformance
&m_perf
;
155 AirspaceIntersectionVisitorPrint(const char* fname
,
158 const bool _do_report
,
159 const AircraftState
&state
,
160 const AirspaceAircraftPerformance
&perf
)
161 :do_report(_do_report
),
166 fout
= new std::ofstream(fname
);
167 iout
= new std::ofstream(iname
);
168 yout
= new std::ofstream(yname
);
172 ~AirspaceIntersectionVisitorPrint() {
180 void intersection(const AbstractAirspace
&as
) {
181 *fout
<< "# intersection point\n";
182 for (auto it
= intersections
.begin(); it
!= intersections
.end(); ++it
) {
183 const GeoPoint start
= (it
->first
);
184 const GeoPoint end
= (it
->second
);
185 *fout
<< start
.longitude
<< " " << start
.latitude
<< " " << "\n";
186 *fout
<< end
.longitude
<< " " << end
.latitude
<< " " << "\n\n";
189 AirspaceInterceptSolution solution
= Intercept(as
, m_state
, m_perf
);
190 if (solution
.IsValid()) {
191 *iout
<< "# intercept " << solution
.elapsed_time
<< " h " << solution
.altitude
<< "\n";
192 *iout
<< solution
.location
.longitude
<< " " << solution
.location
.latitude
<< " " << "\n\n";
196 virtual void Visit(const AbstractAirspace
&as
) override
{
205 class AirspaceVisitorClosest final
: public AirspaceVisitor
{
207 const TaskProjection
&projection
;
208 const AircraftState
& state
;
209 const AirspaceAircraftPerformance
&m_perf
;
212 AirspaceVisitorClosest(const char* fname
,
213 const TaskProjection
&_projection
,
214 const AircraftState
&_state
,
215 const AirspaceAircraftPerformance
&perf
):
217 projection(_projection
),
222 fout
= new std::ofstream(fname
);
224 ~AirspaceVisitorClosest() {
229 void closest(const AbstractAirspace
&as
) {
230 GeoPoint c
= as
.ClosestPoint(state
.location
, projection
);
232 *fout
<< "# closest point\n";
233 *fout
<< c
.longitude
<< " " << c
.latitude
<< " " << "\n";
234 *fout
<< state
.location
.longitude
<< " " << state
.location
.latitude
<< " " << "\n\n";
236 AirspaceInterceptSolution solution
;
237 GeoVector
vec(state
.location
, c
);
238 vec
.distance
= fixed(20000); // set big distance (for testing)
239 if (as
.Intercept(state
, vec
.EndPoint(state
.location
), projection
, m_perf
, solution
)) {
241 *fout
<< "# intercept in " << solution
.elapsed_time
<< " h " << solution
.altitude
<< "\n";
246 virtual void Visit(const AbstractAirspace
&as
) override
{
252 * Adapter between an AirspaceVisitor and a function class.
258 CallVisitor(V
&_visitor
):visitor(_visitor
) {}
261 void operator()(const T
&t
) {
262 return visitor
.Visit(t
);
266 void scan_airspaces(const AircraftState state
,
267 const Airspaces
& airspaces
,
268 const AirspaceAircraftPerformance
& perf
,
270 const GeoPoint
&target
)
272 const fixed
range(20000.0);
274 Directory::Create(_T("output/results"));
275 AirspaceVisitorPrint
pvn("output/results/res-bb-nearest.txt",
277 const Airspace
*nearest
= airspaces
.FindNearest(state
.location
);
278 if (nearest
!= nullptr) {
279 AirspaceVisitor
&v
= pvn
;
284 AirspaceVisitorPrint
pvisitor("output/results/res-bb-range.txt",
286 airspaces
.VisitWithinRange(state
.location
, range
, pvisitor
);
290 AirspaceVisitorClosest
pvisitor("output/results/res-bb-closest.txt",
291 airspaces
.GetProjection(), state
, perf
);
292 airspaces
.VisitWithinRange(state
.location
, range
, pvisitor
);
296 const std::vector
<Airspace
> vi
= airspaces
.FindInside(state
);
297 AirspaceVisitorPrint
pvi("output/results/res-bb-inside.txt",
299 std::for_each(vi
.begin(), vi
.end(), CallVisitor
<AirspaceVisitor
>(pvi
));
303 AirspaceIntersectionVisitorPrint
ivisitor("output/results/res-bb-intersects.txt",
304 "output/results/res-bb-intersected.txt",
305 "output/results/res-bb-intercepts.txt",
308 airspaces
.VisitIntersecting(state
.location
, target
, ivisitor
);
312 AirspaceNearestSort
ans(state
.location
);
313 const AbstractAirspace
* as
= ans
.find_nearest(airspaces
, range
);
315 std::ofstream
fout("output/results/res-bb-sortednearest.txt");
319 fout
<< "# no nearest found\n";
325 AirspaceSoonestSort
ans(state
, perf
);
326 const AbstractAirspace
* as
= ans
.find_nearest(airspaces
);
328 std::ofstream
fout("output/results/res-bb-sortedsoonest.txt");
332 fout
<< "# no soonest found\n";
339 PrintAirspaceWarnings(const char *path
,
340 const AirspaceWarningManager
&warnings
,
341 const AirspaceWarning::State state
)
343 std::ofstream
fout(path
);
345 for (auto i
= warnings
.begin(), end
= warnings
.end(); i
!= end
; ++i
) {
346 const AirspaceWarning
&warning
= *i
;
347 if (warning
.GetWarningState() == state
) {
349 fout
<< warning
.GetAirspace();
355 print_warnings(const AirspaceWarningManager
&airspace_warnings
)
357 PrintAirspaceWarnings("output/results/res-as-warnings-inside.txt",
358 airspace_warnings
, AirspaceWarning::WARNING_INSIDE
);
359 PrintAirspaceWarnings("output/results/res-as-warnings-glide.txt",
360 airspace_warnings
, AirspaceWarning::WARNING_GLIDE
);
361 PrintAirspaceWarnings("output/results/res-as-warnings-filter.txt",
362 airspace_warnings
, AirspaceWarning::WARNING_FILTER
);
363 PrintAirspaceWarnings("output/results/res-as-warnings-task.txt",
364 airspace_warnings
, AirspaceWarning::WARNING_TASK
);