Renderer, ...: use PixelRect::GetCenter()
[xcsoar.git] / test / src / harness_airspace.cpp
blob66a5b9f4330300af4c816942d0ca06cdcebb52ef
1 /* Copyright_License {
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"
34 #include <stdlib.h>
35 #include <fstream>
36 #include <iostream>
38 static void
39 airspace_random_properties(AbstractAirspace& as)
41 AirspaceClass Type = (AirspaceClass)(rand()%14);
42 AirspaceAltitude base;
43 AirspaceAltitude top;
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
53 AbstractAirspace* as;
54 std::vector<GeoPoint> pts;
55 as = new AirspacePolygon(pts);
56 airspaces.Add(as);
58 // try clearing now (we haven't called optimise())
60 airspaces.clear();
61 return true;
64 void setup_airspaces(Airspaces& airspaces, const GeoPoint& center, const unsigned n) {
65 std::ofstream *fin = NULL;
67 if (verbose) {
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++) {
73 AbstractAirspace* as;
74 if (rand()%4!=0) {
75 GeoPoint c;
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);
80 } else {
82 // just for testing, create a random polygon from a convex hull around
83 // random points
84 const unsigned num = rand()%10+5;
85 GeoPoint c;
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++) {
91 GeoPoint p=c;
92 p.longitude += Angle::Degrees(fixed((rand()%200)/1000.0));
93 p.latitude += Angle::Degrees(fixed((rand()%200)/1000.0));
94 pts.push_back(p);
96 as = new AirspacePolygon(pts,true);
98 airspace_random_properties(*as);
99 airspaces.Add(as);
100 if (fin)
101 *fin << *as;
104 delete fin;
106 // try inserting nothing
107 airspaces.Add(NULL);
109 airspaces.Optimise();
114 class AirspaceVisitorPrint final : public AirspaceVisitor {
115 std::ofstream *fout;
116 const bool do_report;
118 public:
119 AirspaceVisitorPrint(const char *fname, const bool _do_report)
120 :do_report(_do_report)
122 if (do_report) {
123 fout = new std::ofstream(fname);
127 ~AirspaceVisitorPrint() {
128 if (do_report) {
129 delete fout;
133 virtual void Visit(const AbstractAirspace &as) override {
134 if (do_report) {
135 *fout << as;
136 *fout << "# Name: " << as.GetName()
137 << "Base: " << as.GetBase()
138 << " Top: " << as.GetTop()
139 << "\n";
145 class AirspaceIntersectionVisitorPrint final
146 : public AirspaceIntersectionVisitor {
147 std::ofstream *fout;
148 std::ofstream *yout;
149 std::ofstream *iout;
150 const bool do_report;
151 const AircraftState m_state;
152 const AirspaceAircraftPerformance &m_perf;
154 public:
155 AirspaceIntersectionVisitorPrint(const char* fname,
156 const char* yname,
157 const char* iname,
158 const bool _do_report,
159 const AircraftState &state,
160 const AirspaceAircraftPerformance &perf)
161 :do_report(_do_report),
162 m_state(state),
163 m_perf(perf)
165 if (do_report) {
166 fout = new std::ofstream(fname);
167 iout = new std::ofstream(iname);
168 yout = new std::ofstream(yname);
172 ~AirspaceIntersectionVisitorPrint() {
173 if (do_report) {
174 delete fout;
175 delete iout;
176 delete yout;
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 {
197 if (do_report) {
198 *yout << as;
199 intersection(as);
205 class AirspaceVisitorClosest final : public AirspaceVisitor {
206 std::ofstream *fout;
207 const TaskProjection &projection;
208 const AircraftState& state;
209 const AirspaceAircraftPerformance &m_perf;
211 public:
212 AirspaceVisitorClosest(const char* fname,
213 const TaskProjection &_projection,
214 const AircraftState &_state,
215 const AirspaceAircraftPerformance &perf):
216 fout(NULL),
217 projection(_projection),
218 state(_state),
219 m_perf(perf)
221 if (verbose)
222 fout = new std::ofstream(fname);
224 ~AirspaceVisitorClosest() {
225 if (fout)
226 delete fout;
229 void closest(const AbstractAirspace &as) {
230 GeoPoint c = as.ClosestPoint(state.location, projection);
231 if (fout) {
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)) {
240 if (fout) {
241 *fout << "# intercept in " << solution.elapsed_time << " h " << solution.altitude << "\n";
246 virtual void Visit(const AbstractAirspace &as) override {
247 closest(as);
252 * Adapter between an AirspaceVisitor and a function class.
254 template<typename V>
255 struct CallVisitor {
256 V &visitor;
258 CallVisitor(V &_visitor):visitor(_visitor) {}
260 template<typename T>
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,
269 bool do_report,
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",
276 do_report);
277 const Airspace *nearest = airspaces.FindNearest(state.location);
278 if (nearest != nullptr) {
279 AirspaceVisitor &v = pvn;
280 v.Visit(*nearest);
284 AirspaceVisitorPrint pvisitor("output/results/res-bb-range.txt",
285 do_report);
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",
298 do_report);
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",
306 do_report,
307 state, perf);
308 airspaces.VisitIntersecting(state.location, target, ivisitor);
312 AirspaceNearestSort ans(state.location);
313 const AbstractAirspace* as = ans.find_nearest(airspaces, range);
314 if (do_report) {
315 std::ofstream fout("output/results/res-bb-sortednearest.txt");
316 if (as) {
317 fout << *as << "\n";
318 } else {
319 fout << "# no nearest found\n";
325 AirspaceSoonestSort ans(state, perf);
326 const AbstractAirspace* as = ans.find_nearest(airspaces);
327 if (do_report) {
328 std::ofstream fout("output/results/res-bb-sortedsoonest.txt");
329 if (as) {
330 fout << *as << "\n";
331 } else {
332 fout << "# no soonest found\n";
338 static void
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) {
348 fout << warning;
349 fout << warning.GetAirspace();
354 void
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);