1 /*****************************************************************************
3 Module: FGGlobalWeatherDatabase.cpp
4 Author: Christian Mayer
6 Called by: main program
8 ---------- Copyright (C) 1999 Christian Mayer (vader@t-online.de) ----------
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22 Place - Suite 330, Boston, MA 02111-1307, USA.
24 Further information about the GNU General Public License can also be found on
25 the world wide web at http://www.gnu.org.
27 FUNCTIONAL DESCRIPTION
28 ------------------------------------------------------------------------------
29 Database for the global weather
30 This database is only called by the local database and by the weather
31 simulator driving this database
34 ------------------------------------------------------------------------------
35 28.05.1999 Christian Mayer Created
36 16.06.1999 Durk Talsma Portability for Linux
37 20.06.1999 Christian Mayer added lots of consts
38 *****************************************************************************/
40 /****************************************************************************/
42 /****************************************************************************/
43 #include "FGGlobalWeatherDatabase.h"
45 /****************************************************************************/
46 /********************************** CODE ************************************/
47 /****************************************************************************/
49 /****************************************************************************/
50 /* Interpolate p which lies inside the triangle x1, x2, x3 */
52 /* x3\ Do this by calulating q and linear interpolate its */
53 /* |\ \ value as it's laying between x1 and x2. */
54 /* | \ \ Then interpolate p as it lays between p and x3 */
56 /* | p \ Advantages: p has exactly the value of a corner */
57 /* | \ \ when it's laying on it. */
58 /* | \ \ If p isn't in the triangle the algoritm */
59 /* x1------q------x2 extrapolates it's value */
60 /****************************************************************************/
61 template<class P, class V>
62 V triangle_interpolate(const P& x1, const V& v1, const P& x2, const V& v2, const P& x3, const V& v3, const P& p)
67 q = x1 + (x2 - x1)*( ((x3-x1).x()*(x1-x2).y() - (x1-x2).x()*(x3-x1).y())/((p-x3).x()*(x2-x1).y() - (x2-x1).x()*(p-x3).y()) );
69 q_value = v1 + (v2 - v1) * (x1.distance3D(q) / x1.distance3D(x2));
71 return q_value + (v3 - q_value) * (q.distance3D(p) / q.distance3D(x3));
74 /****************************************************************************/
75 /* Constructor and Destructor */
76 /****************************************************************************/
77 FGGlobalWeatherDatabase::FGGlobalWeatherDatabase(const FGGlobalWeatherDatabaseStatus& s)
82 FGGlobalWeatherDatabase::~FGGlobalWeatherDatabase()
86 /****************************************************************************/
87 /* Get the physical properties on the specified point p */
88 /* do this by interpolating between the 3 closest points */
89 /****************************************************************************/
90 FGPhysicalProperties FGGlobalWeatherDatabase::get(const Point2D& p) const
92 WeatherPrecition distance[3]; //store the 3 closest distances
93 FGPhysicalProperties2DVectorConstIt iterator[3]; //and the coresponding iterators
96 distance[0] = 9.46e15; //init with a distance that every calculated
97 distance[1] = 9.46e15; //distance is guranteed to be shorter as
98 distance[2] = 9.46e15; //9.46e15 metres are 1 light year...
100 for (FGPhysicalProperties2DVectorConstIt it=database.begin(); it!=database.end(); it++)
101 { //go through the whole database
102 d = it->p.distance2Dsquared(p);
106 distance[2] = distance[1]; distance[1] = distance[0]; distance[0] = d;
107 iterator[2] = iterator[1]; iterator[1] = iterator[0]; iterator[0] = it;
108 //NOTE: The last line causes a warning that an unitialiced variable
109 //is used. You can ignore this warning here.
111 else if (d<distance[1])
113 distance[2] = distance[1]; distance[1] = d;
114 iterator[2] = iterator[1]; iterator[1] = it;
116 else if (d<distance[2])
123 //now I've got the closest entry in xx[0], the 2nd closest in xx[1] and the
127 return triangle_interpolate(
128 iterator[0]->p, (FGPhysicalProperties)*iterator[0],
129 iterator[1]->p, (FGPhysicalProperties)*iterator[1],
130 iterator[2]->p, (FGPhysicalProperties)*iterator[2], p);
133 /****************************************************************************/
134 /* update the database. Since the last call we had dt seconds */
135 /****************************************************************************/
136 void FGGlobalWeatherDatabase::update(const WeatherPrecition& dt)
138 // I've got nothing to update here (yet...)
141 /****************************************************************************/
142 /* Add a physical property on the specified point p */
143 /****************************************************************************/
144 void FGGlobalWeatherDatabase::add(const Point2D& p, const FGPhysicalProperties& x)
146 FGPhysicalProperties2D e;
151 e.Turbulence = x.Turbulence;
152 e.Temperature = x.Temperature;
153 e.AirPressure = x.AirPressure;
154 e.VaporPressure = x.VaporPressure;
157 e.SnowRainIntensity = x.SnowRainIntensity;
158 e.snowRainType = x.snowRainType;
159 e.LightningProbability = x.LightningProbability;
161 database.push_back(e);
164 /****************************************************************************/
165 /* Change the closest physical property to p. If p is further away than */
166 /* tolerance I'm returning false otherwise true */
167 /****************************************************************************/
168 bool FGGlobalWeatherDatabase::change(const FGPhysicalProperties2D& p, const WeatherPrecition& tolerance)
170 for (FGPhysicalProperties2DVectorIt it = database.begin(); it != database.end(); it++)
172 if (it->p.distance3Dsquared(p.p) < (tolerance*tolerance))
173 { //assume that's my point
182 /****************************************************************************/
183 /* Get all, but at least min, stored point in the circle around p with the */
185 /****************************************************************************/
186 FGPhysicalProperties2DVector FGGlobalWeatherDatabase::getAll(const Point2D& p, const WeatherPrecition& r, const unsigned int& min)
188 FGPhysicalProperties2DVector ret_list;
190 if ((DatabaseStatus == FGGlobalWeatherDatabase_only_static)
191 ||(DatabaseStatus == FGGlobalWeatherDatabase_working) )
192 { //doest it make sense?
194 FGPhysicalProperties2DVectorIt *it; //store the closest entries
196 unsigned int act_it = 0;
199 it = new FGPhysicalProperties2DVectorIt[min+1];
200 d = new WeatherPrecition[min+1];
202 for (it[0]=database.begin(); it[act_it]!=database.end(); it[act_it]++)
203 { //go through the whole database
204 d[act_it] = it[act_it]->p.distance2Dsquared(p);
208 ret_list.push_back(*it[act_it]);
213 { //figure out if this distance belongs to the closest ones
214 WeatherPrecition dummy;
215 FGPhysicalProperties2DVectorIt dummyIt;
217 for (i = act_it++; i >= 0;)
222 break; //nope => stop
226 dummy =d[i]; d[i] = d[i+1]; d[i+1] = dummy;
227 dummyIt = it[i]; it[i] = it[i+1]; it[i+1] = dummyIt;
233 if (ret_list.size()<min)
235 for(i = 0; (i < (min - ret_list.size())) && (ret_list.size() < database.size()); i++)
236 ret_list.push_back(*it[i]);