Renderer, ...: use PixelRect::GetCenter()
[xcsoar.git] / src / Computer / LiftDatabaseComputer.cpp
blobed037543491e5fb1f87abad5f7a38c72c9e880c0
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "LiftDatabaseComputer.hpp"
25 #include "Engine/Navigation/TraceHistory.hpp"
26 #include "NMEA/LiftDatabase.hpp"
27 #include "NMEA/MoreData.hpp"
28 #include "NMEA/CirclingInfo.hpp"
29 #include "Util/Clamp.hpp"
31 void
32 LiftDatabaseComputer::Clear(LiftDatabase &lift_database,
33 TraceVariableHistory &circling_average_trace)
35 lift_database.Clear();
37 circling_average_trace.clear();
40 void
41 LiftDatabaseComputer::Reset(LiftDatabase &lift_database,
42 TraceVariableHistory &circling_average_trace)
44 last_circling = false;
45 last_heading = Angle::Zero();
47 Clear(lift_database, circling_average_trace);
50 /**
51 * This function converts a heading into an unsigned index for the LiftDatabase.
53 * This is calculated with Angles to deal with the 360 degree limit.
55 * 357 = 0
56 * 4 = 0
57 * 5 = 1
58 * 14 = 1
59 * 15 = 2
60 * ...
61 * @param heading The heading to convert
62 * @return The index for the LiftDatabase array
64 static unsigned
65 heading_to_index(Angle &heading)
67 static constexpr Angle afive = Angle::Degrees(5);
69 unsigned index = (unsigned)
70 ((heading + afive).AsBearing().Degrees() / 10);
72 return Clamp(index, 0u, 35u);
75 void
76 LiftDatabaseComputer::Compute(LiftDatabase &lift_database,
77 TraceVariableHistory &circling_average_trace,
78 const MoreData &basic,
79 const CirclingInfo &circling_info)
81 // If we just started circling
82 // -> reset the database because this is a new thermal
83 if (!circling_info.circling && last_circling)
84 Clear(lift_database, circling_average_trace);
86 // Determine the direction in which we are circling
87 bool left = circling_info.TurningLeft();
89 // Depending on the direction set the step size sign for the
90 // following loop
91 Angle heading_step = left ? Angle::Degrees(-10) : Angle::Degrees(10);
93 const Angle heading = basic.attitude.heading;
95 // Start at the last heading and add heading_step until the current heading
96 // is reached. For each heading save the current lift value into the
97 // LiftDatabase. Last and current heading are included since they are
98 // a part of the ten degree interval most of the time.
100 // This is done with Angles to deal with the 360 degrees limit.
101 // e.g. last heading 348 degrees, current heading 21 degrees
103 // The loop condition stops until the current heading is reached.
104 // Depending on the circling direction the current heading will be
105 // smaller or bigger then the last one, because of that negative() is
106 // tested against the left variable.
107 for (Angle h = last_heading;
108 left == negative((heading - h).AsDelta().Degrees());
109 h += heading_step) {
110 unsigned index = heading_to_index(h);
111 lift_database[index] = basic.brutto_vario;
114 // detect zero crossing
115 if ((heading < Angle::QuarterCircle() &&
116 last_heading.Degrees() > fixed(270)) ||
117 (last_heading < Angle::QuarterCircle() &&
118 heading.Degrees() > fixed(270))) {
120 fixed h_av = fixed(0);
121 for (auto i : lift_database)
122 h_av += i;
124 h_av /= lift_database.size();
125 circling_average_trace.push(h_av);
128 last_circling = circling_info.circling;
129 last_heading = basic.attitude.heading;