]> git.mxchange.org Git - flightgear.git/blob - src/WeatherCM/FGLocalWeatherDatabase.cpp
f88e87b7e46e157d8a845d8fa0a2c469c545f4e8
[flightgear.git] / src / WeatherCM / FGLocalWeatherDatabase.cpp
1 /*****************************************************************************
2
3  Module:       FGLocalWeatherDatabase.cpp
4  Author:       Christian Mayer
5  Date started: 28.05.99
6  Called by:    main program
7
8  -------- Copyright (C) 1999 Christian Mayer (fgfs@christianmayer.de) --------
9
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
13  version.
14
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
18  details.
19
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.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 FUNCTIONAL DESCRIPTION
28 ------------------------------------------------------------------------------
29 Database for the local weather
30 This database is the only one that gets called from FG
31
32 HISTORY
33 ------------------------------------------------------------------------------
34 28.05.1999 Christian Mayer      Created
35 16.06.1999 Durk Talsma          Portability for Linux
36 20.06.1999 Christian Mayer      added lots of consts
37 11.10.1999 Christian Mayer      changed set<> to map<> on Bernie Bright's 
38                                 suggestion
39 19.10.1999 Christian Mayer      change to use PLIB's sg instead of Point[2/3]D
40                                 and lots of wee code cleaning
41 *****************************************************************************/
42
43 /****************************************************************************/
44 /* INCLUDES                                                                 */
45 /****************************************************************************/
46 #include <Include/compiler.h>
47 #include <Include/fg_constants.h>
48
49 #include <Aircraft/aircraft.hxx>
50
51 #include "FGLocalWeatherDatabase.h"
52 #include "FGVoronoi.h"
53
54
55 /****************************************************************************/
56 /********************************** CODE ************************************/
57 /****************************************************************************/
58
59 /****************************************************************************/
60 /* return the index (better: ID) of the area with point p                   */
61 /****************************************************************************/
62 unsigned int FGLocalWeatherDatabase::AreaWith(const sgVec2& p) const
63 {
64     
65     for (FGMicroWeatherList::size_type i = 0; i != WeatherAreas.size(); i++)
66     {
67         if (WeatherAreas[i].hasPoint(p) == true)
68             return i+1;
69     }
70
71     return 0;   //nothing found
72 }
73
74 /****************************************************************************/
75 /* make tiles out of points on a 2D plane                                   */
76 /****************************************************************************/
77 void FGLocalWeatherDatabase::tileLocalWeather(const FGPhysicalProperties2DVector& EntryList)
78 {
79     FGVoronoiInputList input;
80
81     for (FGPhysicalProperties2DVectorConstIt it1 = EntryList.begin(); it1 != EntryList.end(); it1++)
82         input.push_back(FGVoronoiInput(it1->p, *it1));
83
84     FGVoronoiOutputList output = Voronoiate(input);
85
86     for (FGVoronoiOutputList::iterator it2 = output.begin(); it2 != output.end(); it2++)
87         WeatherAreas.push_back(FGMicroWeather(it2->value, it2->boundary));
88 }
89
90 /****************************************************************************/
91 /* Constructor and Destructor                                               */
92 /****************************************************************************/
93 FGLocalWeatherDatabase* FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 0;
94 FGLocalWeatherDatabase *WeatherDatabase;
95
96 FGLocalWeatherDatabase::FGLocalWeatherDatabase(const sgVec3& posititon, const WeatherPrecision visibility, const DatabaseWorkingType type)
97 {
98     cerr << "Initializing FGLocalWeatherDatabase\n";
99     cerr << "-----------------------------------\n";
100
101     if (theFGLocalWeatherDatabase)
102     {
103         //FG_LOG( FG_GENERAL, FG_ALERT, "Error: only one local weather allowed" );
104         cerr << "Error: only one local weather allowed";
105         exit(-1);
106     }
107
108     setWeatherVisibility(visibility);
109
110     DatabaseStatus = type;
111     global = 0;     //just get sure...
112     sgCopyVec3(last_known_position, posititon);
113
114
115     theFGLocalWeatherDatabase = this;
116
117     switch(DatabaseStatus)
118     {
119     case use_global:
120         {
121             global = new FGGlobalWeatherDatabase;       //initialize GlobalDatabase
122             global->setDatabaseStatus(FGGlobalWeatherDatabase_working);
123             tileLocalWeather(global->getAll(posititon, WeatherVisibility, 3));
124         }
125         break;
126
127     case distant:
128         cerr << "FGLocalWeatherDatabase error: Distant database isn't implemented yet!\n";
129         cerr << "  using random mode instead!\n";
130     case random:
131     case manual:
132     case default_mode:
133         {
134             vector<sgVec2Wrap> emptyList;
135             WeatherAreas.push_back(FGMicroWeather(FGPhysicalProperties2D(), emptyList));   //in these cases I've only got one tile
136         }
137         break;
138
139     default:
140         cerr << "FGLocalWeatherDatabase error: Unknown database type specified!\n";
141     };
142 }
143
144 FGLocalWeatherDatabase::~FGLocalWeatherDatabase()
145 {
146     //Tidying up:
147
148     //delete every stored area
149     WeatherAreas.erase(WeatherAreas.begin(), WeatherAreas.end());
150
151     //delete global database if necessary
152     if (DatabaseStatus == use_global)
153         delete global;
154 }
155
156 /****************************************************************************/
157 /* reset the whole database                                                 */
158 /****************************************************************************/
159 void FGLocalWeatherDatabase::reset(const DatabaseWorkingType type)
160 {
161     //delete global database if necessary
162     if ((DatabaseStatus == use_global) && (type != use_global))
163         delete global;
164
165     DatabaseStatus = type;
166     if (DatabaseStatus == use_global)
167         tileLocalWeather(global->getAll(last_known_position, WeatherVisibility, 3));
168
169     //delete every stored area
170     WeatherAreas.erase(WeatherAreas.begin(), WeatherAreas.end());
171 }
172
173 /****************************************************************************/
174 /* update the database. Since the last call we had dt seconds               */
175 /****************************************************************************/
176 void FGLocalWeatherDatabase::update(const WeatherPrecision dt)
177 {
178     if (DatabaseStatus==use_global)
179         global->update(dt);
180 }
181
182 void FGLocalWeatherDatabase::update(const sgVec3& p) //position has changed
183 {
184     sgCopyVec3(last_known_position, p);
185     //cerr << "****\nupdate inside\n";
186     //cerr << "Parameter: " << p << "\n";
187     //cerr << "****\n";
188 }
189
190 void FGLocalWeatherDatabase::update(const sgVec3& p, const WeatherPrecision dt)   //time and/or position has changed
191 {
192     sgCopyVec3(last_known_position, p);
193
194     if (DatabaseStatus==use_global)
195         global->update(dt);
196 }
197
198 /****************************************************************************/
199 /* Get the physical properties on the specified point p out of the database */
200 /****************************************************************************/
201 FGPhysicalProperty FGLocalWeatherDatabase::get(const sgVec3& p) const
202 {
203     unsigned int a = AreaWith(p);
204     if (a != 0)
205         return WeatherAreas[a-1].get(p[3]);
206     else    //point is outside => ask GlobalWeatherDatabase
207         return global->get(p);
208 }
209
210 FGPhysicalProperties FGLocalWeatherDatabase::get(const sgVec2& p) const
211 {
212     sgVec3 temp;
213     sgSetVec3(temp, p[0], p[1], 0.0);
214
215     unsigned int a = AreaWith(temp);
216     if (a != 0)
217         return WeatherAreas[a-1].get();
218     else    //point is outside => ask GlobalWeatherDatabase
219         return global->get(p);
220 }
221
222 WeatherPrecision FGLocalWeatherDatabase::getAirDensity(const sgVec3& p) const
223 {
224     FGPhysicalProperty dummy;
225     unsigned int a = AreaWith(p);
226     if (a != 0)
227         dummy = WeatherAreas[a-1].get(p[3]);
228     else    //point is outside => ask GlobalWeatherDatabase
229         dummy = global->get(p);
230
231     return 
232         (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) / 
233         (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
234 }
235
236 /****************************************************************************/
237 /* Add a weather feature at the point p and surrounding area                */
238 /****************************************************************************/
239 void FGLocalWeatherDatabase::addWind(const WeatherPrecision alt, const sgVec3& x, const sgVec2& p)
240 {
241     unsigned int a = AreaWith(p);
242     if (a != 0)
243         WeatherAreas[a-1].addWind(alt, x);
244 }
245
246 void FGLocalWeatherDatabase::addTurbulence(const WeatherPrecision alt, const sgVec3& x, const sgVec2& p)
247 {
248     unsigned int a = AreaWith(p);
249     if (a != 0)
250         WeatherAreas[a-1].addTurbulence(alt, x);
251 }
252
253 void FGLocalWeatherDatabase::addTemperature(const WeatherPrecision alt, const WeatherPrecision x, const sgVec2& p)
254 {
255     unsigned int a = AreaWith(p);
256     if (a != 0)
257         WeatherAreas[a-1].addTemperature(alt, x);
258 }
259
260 void FGLocalWeatherDatabase::addAirPressure(const WeatherPrecision alt, const WeatherPrecision x, const sgVec2& p)
261 {
262     unsigned int a = AreaWith(p);
263     if (a != 0)
264         WeatherAreas[a-1].addAirPressure(alt, x);
265 }
266
267 void FGLocalWeatherDatabase::addVaporPressure(const WeatherPrecision alt, const WeatherPrecision x, const sgVec2& p)
268 {
269     unsigned int a = AreaWith(p);
270     if (a != 0)
271         WeatherAreas[a-1].addVaporPressure(alt, x);
272 }
273
274 void FGLocalWeatherDatabase::addCloud(const WeatherPrecision alt, const FGCloudItem& x, const sgVec2& p)
275 {
276     unsigned int a = AreaWith(p);
277     if (a != 0)
278         WeatherAreas[a-1].addCloud(alt, x);
279 }
280
281 void FGLocalWeatherDatabase::setSnowRainIntensity(const WeatherPrecision x, const sgVec2& p)
282 {
283     unsigned int a = AreaWith(p);
284     if (a != 0)
285         WeatherAreas[a-1].setSnowRainIntensity(x);
286 }
287
288 void FGLocalWeatherDatabase::setSnowRainType(const SnowRainType x, const sgVec2& p)
289 {
290     unsigned int a = AreaWith(p);
291     if (a != 0)
292         WeatherAreas[a-1].setSnowRainType(x);
293 }
294
295 void FGLocalWeatherDatabase::setLightningProbability(const WeatherPrecision x, const sgVec2& p)
296 {
297     unsigned int a = AreaWith(p);
298     if (a != 0)
299         WeatherAreas[a-1].setLightningProbability(x);
300 }
301
302 void FGLocalWeatherDatabase::addProperties(const FGPhysicalProperties2D& x)
303 {
304     if (DatabaseStatus==use_global)
305     {
306         global->add(x);
307
308         //BAD, BAD, BAD thing I'm doing here: I'm adding to the global database a point that
309         //changes my voronoi diagram but I don't update it! instead I'm changing one local value
310         //that could be anywhere!!
311         //This only *might* work when the plane moves so far so fast that the diagram gets new
312         //calculated soon...
313         unsigned int a = AreaWith(x.p);
314         if (a != 0)
315             WeatherAreas[a-1].setStoredWeather(x);
316     }
317     else
318     {
319         unsigned int a = AreaWith(x.p);
320         if (a != 0)
321             WeatherAreas[a-1].setStoredWeather(x);
322     }
323 }
324
325 void FGLocalWeatherDatabase::setProperties(const FGPhysicalProperties2D& x)
326 {
327     if (DatabaseStatus==use_global)
328     {
329         global->change(x);
330
331         //BAD, BAD, BAD thing I'm doing here: I'm adding to the global database a point that
332         //changes my voronoi diagram but I don't update it! Instead I'm changing one local value
333         //that could be anywhere!!
334         //This only *might* work when the plane moves so far so fast that the diagram gets newly
335         //calculated soon...
336         unsigned int a = AreaWith(x.p);
337         if (a != 0)
338             WeatherAreas[a-1].setStoredWeather(x);
339     }
340     else
341     {
342         unsigned int a = AreaWith(x.p);
343         if (a != 0)
344             WeatherAreas[a-1].setStoredWeather(x);
345     }
346 }
347
348 void fgUpdateWeatherDatabase(void)
349 {
350     //cerr << "FGLocalWeatherDatabase::update()\n";
351     sgVec3 position;
352     sgSetVec3(position, 
353         current_aircraft.fdm_state->get_Latitude(),
354         current_aircraft.fdm_state->get_Longitude(),
355         current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER);
356
357     WeatherDatabase->update( position );
358 }
359